[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libeufin] branch master updated (ad7171c9 -> 51300a1a)
From: |
gnunet |
Subject: |
[libeufin] branch master updated (ad7171c9 -> 51300a1a) |
Date: |
Tue, 23 Jan 2024 19:39:27 +0100 |
This is an automated email from the git hooks/post-receive script.
antoine pushed a change to branch master
in repository libeufin.
from ad7171c9 Configure ebics logging via CLI flags
new 73a98866 Share database logic
new 8aeffb3f Share TalerAmount logic
new bb7e455b Split utils into common and ebics and ename integration to
testbench
new 51300a1a Share IbanPayto logic and improve full IBAN payto logic
The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.gitignore | 11 +-
Makefile | 12 +-
bank/build.gradle | 6 +-
.../tech/libeufin/bank/BankIntegrationApi.kt | 2 +-
bank/src/main/kotlin/tech/libeufin/bank/Config.kt | 6 +-
.../main/kotlin/tech/libeufin/bank/Constants.kt | 8 +-
.../kotlin/tech/libeufin/bank/ConversionApi.kt | 3 +-
.../main/kotlin/tech/libeufin/bank/CoreBankApi.kt | 8 +-
bank/src/main/kotlin/tech/libeufin/bank/Error.kt | 3 +-
bank/src/main/kotlin/tech/libeufin/bank/Main.kt | 28 +--
bank/src/main/kotlin/tech/libeufin/bank/Params.kt | 3 +-
.../main/kotlin/tech/libeufin/bank/RevenueApi.kt | 2 +-
.../main/kotlin/tech/libeufin/bank/TalerCommon.kt | 182 +------------------
.../main/kotlin/tech/libeufin/bank/TalerMessage.kt | 17 +-
.../kotlin/tech/libeufin/bank/WireGatewayApi.kt | 2 +-
.../main/kotlin/tech/libeufin/bank/auth/auth.kt | 4 +-
.../kotlin/tech/libeufin/bank/db/AccountDAO.kt | 18 +-
.../kotlin/tech/libeufin/bank/db/CashoutDAO.kt | 2 +-
.../kotlin/tech/libeufin/bank/db/ConversionDAO.kt | 2 +-
.../main/kotlin/tech/libeufin/bank/db/Database.kt | 65 +------
.../kotlin/tech/libeufin/bank/db/ExchangeDAO.kt | 2 +-
.../tech/libeufin/bank/db/NotificationWatcher.kt | 2 +-
.../main/kotlin/tech/libeufin/bank/db/TanDAO.kt | 2 +-
.../main/kotlin/tech/libeufin/bank/db/TokenDAO.kt | 2 +-
.../kotlin/tech/libeufin/bank/db/TransactionDAO.kt | 4 +-
.../kotlin/tech/libeufin/bank/db/WithdrawalDAO.kt | 4 +-
bank/src/main/kotlin/tech/libeufin/bank/helpers.kt | 5 +-
bank/src/test/kotlin/AmountTest.kt | 44 ++---
bank/src/test/kotlin/BankIntegrationApiTest.kt | 3 +-
bank/src/test/kotlin/ConversionApiTest.kt | 2 +-
bank/src/test/kotlin/CoreBankApiTest.kt | 30 ++-
bank/src/test/kotlin/DatabaseTest.kt | 36 +---
bank/src/test/kotlin/JsonTest.kt | 1 +
bank/src/test/kotlin/SecurityTest.kt | 2 +-
bank/src/test/kotlin/StatsTest.kt | 2 +-
bank/src/test/kotlin/WireGatewayApiTest.kt | 3 +-
bank/src/test/kotlin/helpers.kt | 18 +-
bank/src/test/kotlin/routines.kt | 3 +-
build.gradle | 2 +-
{util => common}/build.gradle | 9 +-
{util => common}/import.py | 2 +-
{util => common}/src/main/kotlin/Backoff.kt | 2 +-
{util => common}/src/main/kotlin/Cli.kt | 9 +-
{util => common}/src/main/kotlin/Client.kt | 3 +-
{util => common}/src/main/kotlin/Config.kt | 2 +-
.../src/main/kotlin/Constants.kt | 17 +-
{util => common}/src/main/kotlin/CryptoUtil.kt | 3 +-
{util => common}/src/main/kotlin/DB.kt | 62 ++++++-
{util => common}/src/main/kotlin/Encoding.kt | 2 +-
{util => common}/src/main/kotlin/HTTP.kt | 2 +-
common/src/main/kotlin/TalerCommon.kt | 201 +++++++++++++++++++++
{util => common}/src/main/kotlin/TalerConfig.kt | 2 +
{util => common}/src/main/kotlin/TalerErrorCode.kt | 2 +-
{util => common}/src/main/kotlin/iban.kt | 2 +-
{util => common}/src/main/kotlin/strings.kt | 3 +-
{util => common}/src/main/kotlin/time.kt | 2 +-
.../src/main/resources/xsd/camt.052.001.02.xsd | 0
.../src/main/resources/xsd/camt.053.001.02.xsd | 0
.../src/main/resources/xsd/camt.054.001.02.xsd | 0
.../src/main/resources/xsd/ebics_H004.xsd | 0
.../src/main/resources/xsd/ebics_H005.xsd | 0
.../src/main/resources/xsd/ebics_hev.xsd | 0
.../resources/xsd/ebics_keymgmt_request_H004.xsd | 0
.../resources/xsd/ebics_keymgmt_request_H005.xsd | 0
.../resources/xsd/ebics_keymgmt_response_H004.xsd | 0
.../resources/xsd/ebics_keymgmt_response_H005.xsd | 0
.../src/main/resources/xsd/ebics_orders_H004.xsd | 0
.../src/main/resources/xsd/ebics_orders_H005.xsd | 0
.../src/main/resources/xsd/ebics_request_H004.xsd | 0
.../src/main/resources/xsd/ebics_request_H005.xsd | 0
.../src/main/resources/xsd/ebics_response_H004.xsd | 0
.../src/main/resources/xsd/ebics_response_H005.xsd | 0
.../main/resources/xsd/ebics_signature_S002.xsd | 0
.../src/main/resources/xsd/ebics_signatures.xsd | 0
.../src/main/resources/xsd/ebics_types_H004.xsd | 0
.../src/main/resources/xsd/ebics_types_H005.xsd | 0
.../main/resources/xsd/pain.001.001.03.ch.02.xsd | 0
.../src/main/resources/xsd/pain.001.001.03.xsd | 0
.../main/resources/xsd/pain.001.001.09.ch.03.xsd | 0
.../src/main/resources/xsd/pain.002.001.13.xsd | 0
.../src/main/resources/xsd/xmldsig-core-schema.xsd | 0
common/src/test/kotlin/AmountTest.kt | 62 +++++++
{util => common}/src/test/kotlin/CryptoUtilTest.kt | 3 +-
common/src/test/kotlin/PaytoTest.kt | 80 ++++++++
.../src/test/kotlin/TalerConfigTest.kt | 1 +
{util => common}/src/test/kotlin/TimeTest.kt | 4 +-
{util => common}/src/test/resources/ebics_hev.xml | 0
.../src/test/resources/ebics_ini_inner_key.xml | 0
.../test/resources/ebics_ini_request_sample.xml | 0
.../src/test/resources/hia_request.xml | 0
.../src/test/resources/hia_request_order_data.xml | 0
.../src/test/resources/hpb_request.xml | 0
.../src/test/resources/signature1/doc.xml | 0
.../src/test/resources/signature1/public_key.txt | 0
{util => ebics}/build.gradle | 12 +-
{util => ebics}/import.py | 2 +-
{util => ebics}/src/main/kotlin/Ebics.kt | 15 +-
{util => ebics}/src/main/kotlin/EbicsCodeSets.kt | 2 +-
{util => ebics}/src/main/kotlin/EbicsOrderUtil.kt | 3 +-
{util => ebics}/src/main/kotlin/XMLUtil.kt | 4 +-
{util => ebics}/src/main/kotlin/XmlCombinators.kt | 2 +-
.../ebics_h004/EbicsKeyManagementResponse.kt | 2 +-
.../src/main/kotlin/ebics_h004/EbicsNpkdRequest.kt | 2 +-
.../src/main/kotlin/ebics_h004/EbicsRequest.kt | 4 +-
.../src/main/kotlin/ebics_h004/EbicsResponse.kt | 6 +-
.../src/main/kotlin/ebics_h004/EbicsTypes.kt | 2 +-
.../kotlin/ebics_h004/EbicsUnsecuredRequest.kt | 6 +-
.../main/kotlin/ebics_h004/HIARequestOrderData.kt | 2 +-
.../main/kotlin/ebics_h004/HKDResponseOrderData.kt | 2 +-
.../main/kotlin/ebics_h004/HPBResponseOrderData.kt | 2 +-
.../main/kotlin/ebics_h004/HTDResponseOrderData.kt | 2 +-
.../src/main/kotlin/ebics_h004/package-info.java | 2 +-
.../src/main/kotlin/ebics_h005/Ebics3Request.kt | 4 +-
.../src/main/kotlin/ebics_h005/Ebics3Response.kt | 8 +-
.../src/main/kotlin/ebics_h005/Ebics3Types.kt | 2 +-
.../src/main/kotlin/ebics_h005/package-info.java | 2 +-
.../src/main/kotlin/ebics_hev/EbicsMessages.kt | 2 +-
.../src/main/kotlin/ebics_hev/package-info.java | 2 +-
.../src/main/kotlin/ebics_s001/SignatureTypes.kt | 2 +-
.../main/kotlin/ebics_s001/UserSignatureData.kt | 2 +-
.../src/main/kotlin/ebics_s001/package-info.java | 2 +-
.../src/main/kotlin/ebics_s002/SignatureTypes.kt | 2 +-
.../kotlin/ebics_s002/UserSignatureDataEbics3.kt | 2 +-
.../src/main/kotlin/ebics_s002/package-info.java | 2 +-
ebics/src/main/resources/version.txt | 1 +
.../src/main/resources/xsd/camt.052.001.02.xsd | 0
.../src/main/resources/xsd/camt.053.001.02.xsd | 0
.../src/main/resources/xsd/camt.054.001.02.xsd | 0
.../src/main/resources/xsd/ebics_H004.xsd | 0
.../src/main/resources/xsd/ebics_H005.xsd | 0
.../src/main/resources/xsd/ebics_hev.xsd | 0
.../resources/xsd/ebics_keymgmt_request_H004.xsd | 0
.../resources/xsd/ebics_keymgmt_request_H005.xsd | 0
.../resources/xsd/ebics_keymgmt_response_H004.xsd | 0
.../resources/xsd/ebics_keymgmt_response_H005.xsd | 0
.../src/main/resources/xsd/ebics_orders_H004.xsd | 0
.../src/main/resources/xsd/ebics_orders_H005.xsd | 0
.../src/main/resources/xsd/ebics_request_H004.xsd | 0
.../src/main/resources/xsd/ebics_request_H005.xsd | 0
.../src/main/resources/xsd/ebics_response_H004.xsd | 0
.../src/main/resources/xsd/ebics_response_H005.xsd | 0
.../main/resources/xsd/ebics_signature_S002.xsd | 0
.../src/main/resources/xsd/ebics_signatures.xsd | 0
.../src/main/resources/xsd/ebics_types_H004.xsd | 0
.../src/main/resources/xsd/ebics_types_H005.xsd | 0
.../main/resources/xsd/pain.001.001.03.ch.02.xsd | 0
.../src/main/resources/xsd/pain.001.001.03.xsd | 0
.../main/resources/xsd/pain.001.001.09.ch.03.xsd | 0
.../src/main/resources/xsd/pain.002.001.13.xsd | 0
.../src/main/resources/xsd/xmldsig-core-schema.xsd | 0
.../src/test/kotlin/EbicsMessagesTest.kt | 12 +-
.../src/test/kotlin/EbicsOrderUtilTest.kt | 6 +-
.../src/test/kotlin/SignatureDataTest.kt | 8 +-
.../src/test/kotlin/XmlCombinatorsTest.kt | 4 +-
{util => ebics}/src/test/kotlin/XmlUtilTest.kt | 14 +-
{util => ebics}/src/test/resources/ebics_hev.xml | 0
.../src/test/resources/ebics_ini_inner_key.xml | 0
.../test/resources/ebics_ini_request_sample.xml | 0
{util => ebics}/src/test/resources/hia_request.xml | 0
.../src/test/resources/hia_request_order_data.xml | 0
{util => ebics}/src/test/resources/hpb_request.xml | 0
.../src/test/resources/signature1/doc.xml | 0
.../src/test/resources/signature1/public_key.txt | 0
nexus/build.gradle | 5 +-
.../main/kotlin/tech/libeufin/nexus/Database.kt | 141 ++++-----------
.../src/main/kotlin/tech/libeufin/nexus/DbInit.kt | 2 +-
.../main/kotlin/tech/libeufin/nexus/EbicsFetch.kt | 56 +-----
.../main/kotlin/tech/libeufin/nexus/EbicsSetup.kt | 8 +-
.../main/kotlin/tech/libeufin/nexus/EbicsSubmit.kt | 12 +-
.../main/kotlin/tech/libeufin/nexus/Iso20022.kt | 22 +--
nexus/src/main/kotlin/tech/libeufin/nexus/Log.kt | 2 +-
nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt | 6 +-
.../kotlin/tech/libeufin/nexus/ebics/Ebics2.kt | 6 +-
.../kotlin/tech/libeufin/nexus/ebics/Ebics3.kt | 10 +-
.../tech/libeufin/nexus/ebics/EbicsCommon.kt | 5 +-
nexus/src/test/kotlin/CliTest.kt | 2 +-
nexus/src/test/kotlin/Common.kt | 6 +-
nexus/src/test/kotlin/ConfigLoading.kt | 2 +-
nexus/src/test/kotlin/DatabaseTest.kt | 19 +-
nexus/src/test/kotlin/Ebics.kt | 4 +-
nexus/src/test/kotlin/Keys.kt | 2 +-
nexus/src/test/kotlin/MySerializers.kt | 4 +-
nexus/src/test/kotlin/Parsing.kt | 61 +------
settings.gradle | 5 +-
{integration => testbench}/build.gradle | 6 +-
{integration => testbench}/conf/integration.conf | 0
{integration => testbench}/conf/mini.conf | 0
{integration => testbench}/conf/netzbon.conf | 0
{integration => testbench}/conf/postfinance.conf | 0
{integration => testbench}/src/main/kotlin/Main.kt | 20 +-
.../src/test/kotlin/IntegrationTest.kt | 66 +++----
util/src/main/kotlin/IbanPayto.kt | 104 -----------
util/src/test/kotlin/PaytoTest.kt | 51 ------
193 files changed, 768 insertions(+), 1034 deletions(-)
copy {util => common}/build.gradle (76%)
copy {util => common}/import.py (98%)
rename {util => common}/src/main/kotlin/Backoff.kt (97%)
rename {util => common}/src/main/kotlin/Cli.kt (96%)
rename {util => common}/src/main/kotlin/Client.kt (97%)
rename {util => common}/src/main/kotlin/Config.kt (97%)
copy bank/src/main/kotlin/tech/libeufin/bank/Metadata.kt =>
common/src/main/kotlin/Constants.kt (67%)
rename {util => common}/src/main/kotlin/CryptoUtil.kt (99%)
rename {util => common}/src/main/kotlin/DB.kt (83%)
rename {util => common}/src/main/kotlin/Encoding.kt (99%)
rename {util => common}/src/main/kotlin/HTTP.kt (98%)
create mode 100644 common/src/main/kotlin/TalerCommon.kt
rename {util => common}/src/main/kotlin/TalerConfig.kt (99%)
rename {util => common}/src/main/kotlin/TalerErrorCode.kt (99%)
rename {util => common}/src/main/kotlin/iban.kt (98%)
rename {util => common}/src/main/kotlin/strings.kt (97%)
rename {util => common}/src/main/kotlin/time.kt (99%)
copy {util => common}/src/main/resources/xsd/camt.052.001.02.xsd (100%)
copy {util => common}/src/main/resources/xsd/camt.053.001.02.xsd (100%)
copy {util => common}/src/main/resources/xsd/camt.054.001.02.xsd (100%)
copy {util => common}/src/main/resources/xsd/ebics_H004.xsd (100%)
copy {util => common}/src/main/resources/xsd/ebics_H005.xsd (100%)
copy {util => common}/src/main/resources/xsd/ebics_hev.xsd (100%)
copy {util => common}/src/main/resources/xsd/ebics_keymgmt_request_H004.xsd
(100%)
copy {util => common}/src/main/resources/xsd/ebics_keymgmt_request_H005.xsd
(100%)
copy {util => common}/src/main/resources/xsd/ebics_keymgmt_response_H004.xsd
(100%)
copy {util => common}/src/main/resources/xsd/ebics_keymgmt_response_H005.xsd
(100%)
copy {util => common}/src/main/resources/xsd/ebics_orders_H004.xsd (100%)
copy {util => common}/src/main/resources/xsd/ebics_orders_H005.xsd (100%)
copy {util => common}/src/main/resources/xsd/ebics_request_H004.xsd (100%)
copy {util => common}/src/main/resources/xsd/ebics_request_H005.xsd (100%)
copy {util => common}/src/main/resources/xsd/ebics_response_H004.xsd (100%)
copy {util => common}/src/main/resources/xsd/ebics_response_H005.xsd (100%)
copy {util => common}/src/main/resources/xsd/ebics_signature_S002.xsd (100%)
copy {util => common}/src/main/resources/xsd/ebics_signatures.xsd (100%)
copy {util => common}/src/main/resources/xsd/ebics_types_H004.xsd (100%)
copy {util => common}/src/main/resources/xsd/ebics_types_H005.xsd (100%)
copy {util => common}/src/main/resources/xsd/pain.001.001.03.ch.02.xsd (100%)
copy {util => common}/src/main/resources/xsd/pain.001.001.03.xsd (100%)
copy {util => common}/src/main/resources/xsd/pain.001.001.09.ch.03.xsd (100%)
copy {util => common}/src/main/resources/xsd/pain.002.001.13.xsd (100%)
copy {util => common}/src/main/resources/xsd/xmldsig-core-schema.xsd (100%)
create mode 100644 common/src/test/kotlin/AmountTest.kt
rename {util => common}/src/test/kotlin/CryptoUtilTest.kt (99%)
create mode 100644 common/src/test/kotlin/PaytoTest.kt
rename {util => common}/src/test/kotlin/TalerConfigTest.kt (98%)
rename {util => common}/src/test/kotlin/TimeTest.kt (95%)
copy {util => common}/src/test/resources/ebics_hev.xml (100%)
copy {util => common}/src/test/resources/ebics_ini_inner_key.xml (100%)
copy {util => common}/src/test/resources/ebics_ini_request_sample.xml (100%)
copy {util => common}/src/test/resources/hia_request.xml (100%)
copy {util => common}/src/test/resources/hia_request_order_data.xml (100%)
copy {util => common}/src/test/resources/hpb_request.xml (100%)
copy {util => common}/src/test/resources/signature1/doc.xml (100%)
copy {util => common}/src/test/resources/signature1/public_key.txt (100%)
rename {util => ebics}/build.gradle (61%)
rename {util => ebics}/import.py (98%)
rename {util => ebics}/src/main/kotlin/Ebics.kt (96%)
rename {util => ebics}/src/main/kotlin/EbicsCodeSets.kt (99%)
rename {util => ebics}/src/main/kotlin/EbicsOrderUtil.kt (97%)
rename {util => ebics}/src/main/kotlin/XMLUtil.kt (99%)
rename {util => ebics}/src/main/kotlin/XmlCombinators.kt (99%)
rename {util =>
ebics}/src/main/kotlin/ebics_h004/EbicsKeyManagementResponse.kt (98%)
rename {util => ebics}/src/main/kotlin/ebics_h004/EbicsNpkdRequest.kt (99%)
rename {util => ebics}/src/main/kotlin/ebics_h004/EbicsRequest.kt (99%)
rename {util => ebics}/src/main/kotlin/ebics_h004/EbicsResponse.kt (99%)
rename {util => ebics}/src/main/kotlin/ebics_h004/EbicsTypes.kt (99%)
rename {util => ebics}/src/main/kotlin/ebics_h004/EbicsUnsecuredRequest.kt
(98%)
rename {util => ebics}/src/main/kotlin/ebics_h004/HIARequestOrderData.kt (96%)
rename {util => ebics}/src/main/kotlin/ebics_h004/HKDResponseOrderData.kt (92%)
rename {util => ebics}/src/main/kotlin/ebics_h004/HPBResponseOrderData.kt (95%)
rename {util => ebics}/src/main/kotlin/ebics_h004/HTDResponseOrderData.kt (91%)
rename {util => ebics}/src/main/kotlin/ebics_h004/package-info.java (76%)
rename {util => ebics}/src/main/kotlin/ebics_h005/Ebics3Request.kt (99%)
rename {util => ebics}/src/main/kotlin/ebics_h005/Ebics3Response.kt (98%)
rename {util => ebics}/src/main/kotlin/ebics_h005/Ebics3Types.kt (99%)
rename {util => ebics}/src/main/kotlin/ebics_h005/package-info.java (78%)
rename {util => ebics}/src/main/kotlin/ebics_hev/EbicsMessages.kt (98%)
rename {util => ebics}/src/main/kotlin/ebics_hev/package-info.java (89%)
rename {util => ebics}/src/main/kotlin/ebics_s001/SignatureTypes.kt (98%)
rename {util => ebics}/src/main/kotlin/ebics_s001/UserSignatureData.kt (95%)
rename {util => ebics}/src/main/kotlin/ebics_s001/package-info.java (76%)
rename {util => ebics}/src/main/kotlin/ebics_s002/SignatureTypes.kt (98%)
rename {util => ebics}/src/main/kotlin/ebics_s002/UserSignatureDataEbics3.kt
(95%)
rename {util => ebics}/src/main/kotlin/ebics_s002/package-info.java (76%)
create mode 100644 ebics/src/main/resources/version.txt
rename {util => ebics}/src/main/resources/xsd/camt.052.001.02.xsd (100%)
rename {util => ebics}/src/main/resources/xsd/camt.053.001.02.xsd (100%)
rename {util => ebics}/src/main/resources/xsd/camt.054.001.02.xsd (100%)
rename {util => ebics}/src/main/resources/xsd/ebics_H004.xsd (100%)
rename {util => ebics}/src/main/resources/xsd/ebics_H005.xsd (100%)
rename {util => ebics}/src/main/resources/xsd/ebics_hev.xsd (100%)
rename {util => ebics}/src/main/resources/xsd/ebics_keymgmt_request_H004.xsd
(100%)
rename {util => ebics}/src/main/resources/xsd/ebics_keymgmt_request_H005.xsd
(100%)
rename {util => ebics}/src/main/resources/xsd/ebics_keymgmt_response_H004.xsd
(100%)
rename {util => ebics}/src/main/resources/xsd/ebics_keymgmt_response_H005.xsd
(100%)
rename {util => ebics}/src/main/resources/xsd/ebics_orders_H004.xsd (100%)
rename {util => ebics}/src/main/resources/xsd/ebics_orders_H005.xsd (100%)
rename {util => ebics}/src/main/resources/xsd/ebics_request_H004.xsd (100%)
rename {util => ebics}/src/main/resources/xsd/ebics_request_H005.xsd (100%)
rename {util => ebics}/src/main/resources/xsd/ebics_response_H004.xsd (100%)
rename {util => ebics}/src/main/resources/xsd/ebics_response_H005.xsd (100%)
rename {util => ebics}/src/main/resources/xsd/ebics_signature_S002.xsd (100%)
rename {util => ebics}/src/main/resources/xsd/ebics_signatures.xsd (100%)
rename {util => ebics}/src/main/resources/xsd/ebics_types_H004.xsd (100%)
rename {util => ebics}/src/main/resources/xsd/ebics_types_H005.xsd (100%)
rename {util => ebics}/src/main/resources/xsd/pain.001.001.03.ch.02.xsd (100%)
rename {util => ebics}/src/main/resources/xsd/pain.001.001.03.xsd (100%)
rename {util => ebics}/src/main/resources/xsd/pain.001.001.09.ch.03.xsd (100%)
rename {util => ebics}/src/main/resources/xsd/pain.002.001.13.xsd (100%)
rename {util => ebics}/src/main/resources/xsd/xmldsig-core-schema.xsd (100%)
rename {util => ebics}/src/test/kotlin/EbicsMessagesTest.kt (98%)
rename {util => ebics}/src/test/kotlin/EbicsOrderUtilTest.kt (99%)
rename {util => ebics}/src/test/kotlin/SignatureDataTest.kt (95%)
rename {util => ebics}/src/test/kotlin/XmlCombinatorsTest.kt (96%)
rename {util => ebics}/src/test/kotlin/XmlUtilTest.kt (95%)
rename {util => ebics}/src/test/resources/ebics_hev.xml (100%)
rename {util => ebics}/src/test/resources/ebics_ini_inner_key.xml (100%)
rename {util => ebics}/src/test/resources/ebics_ini_request_sample.xml (100%)
rename {util => ebics}/src/test/resources/hia_request.xml (100%)
rename {util => ebics}/src/test/resources/hia_request_order_data.xml (100%)
rename {util => ebics}/src/test/resources/hpb_request.xml (100%)
rename {util => ebics}/src/test/resources/signature1/doc.xml (100%)
rename {util => ebics}/src/test/resources/signature1/public_key.txt (100%)
rename {integration => testbench}/build.gradle (86%)
rename {integration => testbench}/conf/integration.conf (100%)
rename {integration => testbench}/conf/mini.conf (100%)
rename {integration => testbench}/conf/netzbon.conf (100%)
rename {integration => testbench}/conf/postfinance.conf (100%)
rename {integration => testbench}/src/main/kotlin/Main.kt (92%)
rename {integration => testbench}/src/test/kotlin/IntegrationTest.kt (84%)
delete mode 100644 util/src/main/kotlin/IbanPayto.kt
delete mode 100644 util/src/test/kotlin/PaytoTest.kt
diff --git a/.gitignore b/.gitignore
index 8d1b734f..d046aaa3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,13 +1,8 @@
.idea/*
.vscode
-/nexus/bin/
-/sandbox/bin/
-/util/bin/
-nexus/libeufin-nexus-dev
nexus/test
-integration/test
-integration/config.json
-sandbox/libeufin-sandbox-dev
+testbench/test
+testbench/config.json
configure
build/
.gradle
@@ -26,7 +21,7 @@ __pycache__
*.log
.DS_Store
*.mk
-util/src/main/resources/version.txt
+common/src/main/resources/version.txt
debian/usr/share/libeufin/demobank-ui/index.js
debian/usr/share/libeufin/demobank-ui/*.html
debian/usr/share/libeufin/demobank-ui/*.css
diff --git a/Makefile b/Makefile
index e4c393f6..9a63ae7e 100644
--- a/Makefile
+++ b/Makefile
@@ -110,13 +110,13 @@ bank-test: install-nobuild-bank-files
nexus-test: install-nobuild-nexus-files
./gradlew :nexus:test --tests $(test) -i
-.PHONY: integration-test
-integration-test: install-nobuild-bank-files install-nobuild-nexus-files
- ./gradlew :integration:test --tests $(test) -i
+.PHONY: testbench-test
+testbench-test: install-nobuild-bank-files install-nobuild-nexus-files
+ ./gradlew :testbench:test --tests $(test) -i
-.PHONY: integration
-integration: install-nobuild-bank-files install-nobuild-nexus-files
- ./gradlew :integration:run --console=plain --args="$(test)"
+.PHONY: testbench
+testbench: install-nobuild-bank-files install-nobuild-nexus-files
+ ./gradlew :testbench:run --console=plain --args="$(platform)"
.PHONY: doc
doc:
diff --git a/bank/build.gradle b/bank/build.gradle
index 0f0bb006..1e9558ba 100644
--- a/bank/build.gradle
+++ b/bank/build.gradle
@@ -21,11 +21,9 @@ dependencies {
// Core language libraries
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version")
- // LibEuFin util library
- implementation(project(":util"))
+ implementation(project(":common"))
implementation("org.postgresql:postgresql:$postgres_version")
- implementation("com.zaxxer:HikariCP:5.0.1")
implementation("com.github.ajalt.clikt:clikt:$clikt_version")
implementation("io.ktor:ktor-server-core:$ktor_version")
@@ -42,7 +40,7 @@ dependencies {
testImplementation("org.jetbrains.kotlin:kotlin-test:$kotlin_version")
testImplementation("io.ktor:ktor-server-test-host:$ktor_version")
- testImplementation(project(":util"))
+ testImplementation(project(":common"))
}
application {
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/BankIntegrationApi.kt
b/bank/src/main/kotlin/tech/libeufin/bank/BankIntegrationApi.kt
index ae3419f4..be38286f 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/BankIntegrationApi.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/BankIntegrationApi.kt
@@ -26,7 +26,7 @@ import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.ktor.http.*
-import net.taler.common.errorcodes.TalerErrorCode
+import tech.libeufin.common.TalerErrorCode
import tech.libeufin.bank.db.*
import tech.libeufin.bank.db.WithdrawalDAO.*
import java.lang.AssertionError
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Config.kt
b/bank/src/main/kotlin/tech/libeufin/bank/Config.kt
index 4604ad04..a1dd7711 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/Config.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/Config.kt
@@ -18,12 +18,10 @@
*/
package tech.libeufin.bank
-import ConfigSource
-import TalerConfig
-import TalerConfigError
+import tech.libeufin.common.*
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
-import tech.libeufin.util.DatabaseConfig
+import tech.libeufin.common.DatabaseConfig
/**
* Application the parsed configuration.
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Constants.kt
b/bank/src/main/kotlin/tech/libeufin/bank/Constants.kt
index a1c65035..ef647112 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/Constants.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/Constants.kt
@@ -18,7 +18,7 @@
*/
package tech.libeufin.bank
-import ConfigSource
+import tech.libeufin.common.*
import java.time.Duration
// Config
@@ -39,11 +39,7 @@ const val IBAN_ALLOCATION_RETRY_COUNTER: Int = 5;
// Security
const val MAX_BODY_LENGTH: Long = 4 * 1024 // 4kB
-// DB
-const val MIN_VERSION: Int = 14
-const val SERIALIZATION_RETRY: Int = 10;
-
-// API version
+// API version
const val COREBANK_API_VERSION: String = "4:0:0"
const val CONVERSION_API_VERSION: String = "0:0:0"
const val INTEGRATION_API_VERSION: String = "2:0:2"
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/ConversionApi.kt
b/bank/src/main/kotlin/tech/libeufin/bank/ConversionApi.kt
index d9e88942..6707eff0 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/ConversionApi.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/ConversionApi.kt
@@ -24,11 +24,10 @@ import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import java.util.*
-import tech.libeufin.util.*
+import tech.libeufin.common.*
import tech.libeufin.bank.auth.*
import tech.libeufin.bank.db.ConversionDAO.*
import tech.libeufin.bank.db.*
-import net.taler.common.errorcodes.TalerErrorCode
fun Routing.conversionApi(db: Database, ctx: BankConfig) =
conditional(ctx.allowConversion) {
get("/conversion-info/config") {
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt
b/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt
index 04616e88..d17842fe 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt
@@ -32,8 +32,6 @@ import kotlinx.serialization.json.Json
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.future.await
import kotlinx.coroutines.withContext
-import net.taler.common.errorcodes.TalerErrorCode
-import net.taler.wallet.crypto.Base32Crockford
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import tech.libeufin.bank.*
@@ -45,7 +43,7 @@ import tech.libeufin.bank.db.CashoutDAO.*
import tech.libeufin.bank.db.ExchangeDAO.*
import tech.libeufin.bank.db.TransactionDAO.*
import tech.libeufin.bank.db.WithdrawalDAO.*
-import tech.libeufin.util.*
+import tech.libeufin.common.*
private val logger: Logger = LoggerFactory.getLogger("libeufin-bank-api")
@@ -140,7 +138,7 @@ private fun Routing.coreBankTokenApi(db: Database) {
}
}
-suspend fun createAccount(db: Database, ctx: BankConfig, req:
RegisterAccountRequest, isAdmin: Boolean): Pair<AccountCreationResult,
IbanPayTo> {
+suspend fun createAccount(db: Database, ctx: BankConfig, req:
RegisterAccountRequest, isAdmin: Boolean): Pair<AccountCreationResult,
IbanPayto> {
// Prohibit reserved usernames:
if (RESERVED_ACCOUNTS.contains(req.username))
throw conflict(
@@ -185,7 +183,7 @@ suspend fun createAccount(db: Database, ctx: BankConfig,
req: RegisterAccountReq
var retry = if (req.payto_uri == null) IBAN_ALLOCATION_RETRY_COUNTER else 0
while (true) {
- val internalPayto = req.payto_uri ?: IbanPayTo(genIbanPaytoUri())
+ val internalPayto = req.payto_uri ?: IbanPayto(genIbanPaytoUri())
val res = db.account.create(
login = req.username,
name = req.name,
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Error.kt
b/bank/src/main/kotlin/tech/libeufin/bank/Error.kt
index 04c3881e..eacf6a08 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/Error.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/Error.kt
@@ -23,8 +23,7 @@ import io.ktor.server.response.*
import io.ktor.server.application.ApplicationCall
import io.ktor.util.AttributeKey
import kotlinx.serialization.Serializable
-import net.taler.common.errorcodes.TalerErrorCode
-import tech.libeufin.util.*
+import tech.libeufin.common.*
/**
* Convenience type to throw errors along the bank activity
* and that is meant to be caught by Ktor and responded to the
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Main.kt
b/bank/src/main/kotlin/tech/libeufin/bank/Main.kt
index 89eac6d2..575efe6c 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/Main.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/Main.kt
@@ -48,14 +48,13 @@ import java.io.File
import kotlinx.coroutines.*
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.*
-import net.taler.common.errorcodes.TalerErrorCode
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.slf4j.event.Level
import org.postgresql.util.PSQLState
import tech.libeufin.bank.db.AccountDAO.*
import tech.libeufin.bank.db.*
-import tech.libeufin.util.*
+import tech.libeufin.common.*
private val logger: Logger = LoggerFactory.getLogger("libeufin-bank")
// Dirty local variable to stop the server in test TODO remove this ugly hack
@@ -172,13 +171,16 @@ fun Application.corebankWebApp(db: Database, ctx:
BankConfig) {
while (rootCause?.cause != null)
rootCause = rootCause.cause
// Telling apart invalid JSON vs missing parameter vs
invalid parameter.
- val talerErrorCode = when (cause) {
- is MissingRequestParameterException ->
+ val talerErrorCode = when {
+ cause is MissingRequestParameterException ->
TalerErrorCode.GENERIC_PARAMETER_MISSING
-
- is ParameterConversionException ->
+ cause is ParameterConversionException ->
TalerErrorCode.GENERIC_PARAMETER_MALFORMED
-
+ rootCause is CommonError -> when (rootCause) {
+ is CommonError.AmountFormat ->
TalerErrorCode.BANK_BAD_FORMAT_AMOUNT
+ is CommonError.AmountNumberTooBig ->
TalerErrorCode.BANK_NUMBER_TOO_BIG
+ is CommonError.IbanPayto ->
TalerErrorCode.GENERIC_JSON_INVALID
+ }
else -> TalerErrorCode.GENERIC_JSON_INVALID
}
call.err(
@@ -363,7 +365,7 @@ class EditAccount : CliktCommand(
private val email: String? by option(help = "E-Mail address used for TAN
transmission")
private val phone: String? by option(help = "Phone number used for TAN
transmission")
private val tan_channel: String? by option(help = "which channel TAN
challenges should be sent to")
- private val cashout_payto_uri: IbanPayTo? by option(help = "Payto URI of a
fiant account who receive cashout amount").convert { IbanPayTo(it) }
+ private val cashout_payto_uri: IbanPayto? by option(help = "Payto URI of a
fiant account who receive cashout amount").convert { IbanPayto(it) }
private val debit_threshold: TalerAmount? by option(help = "Max debit
allowed for this account").convert { TalerAmount(it) }
override fun run() = cliCmd(logger, common.log) {
@@ -424,13 +426,13 @@ class CreateAccountOption: OptionGroup() {
).flag()
val email: String? by option(help = "E-Mail address used for TAN
transmission")
val phone: String? by option(help = "Phone number used for TAN
transmission")
- val cashout_payto_uri: IbanPayTo? by option(
+ val cashout_payto_uri: IbanPayto? by option(
help = "Payto URI of a fiant account who receive cashout amount"
- ).convert { IbanPayTo(it) }
- val internal_payto_uri: IbanPayTo? by option(hidden = true).convert {
IbanPayTo(it) }
- val payto_uri: IbanPayTo? by option(
+ ).convert { IbanPayto(it) }
+ val internal_payto_uri: IbanPayto? by option(hidden = true).convert {
IbanPayto(it) }
+ val payto_uri: IbanPayto? by option(
help = "Payto URI of this account"
- ).convert { IbanPayTo(it) }
+ ).convert { IbanPayto(it) }
val debit_threshold: TalerAmount? by option(
help = "Max debit allowed for this account")
.convert { TalerAmount(it) }
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Params.kt
b/bank/src/main/kotlin/tech/libeufin/bank/Params.kt
index bdfa2dd8..7b3e53e8 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/Params.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/Params.kt
@@ -27,8 +27,7 @@ import io.ktor.server.util.*
import java.time.*
import java.time.temporal.*
import java.util.*
-import net.taler.common.errorcodes.TalerErrorCode
-import tech.libeufin.util.*
+import tech.libeufin.common.*
fun Parameters.expect(name: String): String
= get(name) ?: throw badRequest("Missing '$name' parameter",
TalerErrorCode.GENERIC_PARAMETER_MISSING)
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/RevenueApi.kt
b/bank/src/main/kotlin/tech/libeufin/bank/RevenueApi.kt
index 4575b106..7200de47 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/RevenueApi.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/RevenueApi.kt
@@ -24,7 +24,7 @@ import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import java.util.*
-import tech.libeufin.util.*
+import tech.libeufin.common.*
import tech.libeufin.bank.auth.*
import tech.libeufin.bank.db.*
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/TalerCommon.kt
b/bank/src/main/kotlin/tech/libeufin/bank/TalerCommon.kt
index fa135161..389ebc8b 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/TalerCommon.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/TalerCommon.kt
@@ -19,6 +19,7 @@
package tech.libeufin.bank
+import tech.libeufin.common.*
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.application.*
@@ -32,9 +33,6 @@ import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
import kotlinx.serialization.json.*
-import net.taler.common.errorcodes.TalerErrorCode
-import net.taler.wallet.crypto.Base32Crockford
-import net.taler.wallet.crypto.EncodingException
/** 32-byte Crockford's Base32 encoded data */
@Serializable(with = Base32Crockford32B.Serializer::class)
@@ -197,98 +195,6 @@ data class TalerProtocolTimestamp(
}
}
-/**
- * Represents a Taler amount. This type can be used both
- * to hold database records and amounts coming from the parser.
- * If maybeCurrency is null, then the constructor defaults it
- * to be the "internal currency". Internal currency is the one
- * with which Libeufin-Bank moves funds within itself, therefore
- * not to be mistaken with the cashout currency, which is the one
- * that gets credited to Libeufin-Bank users to their cashout_payto_uri.
- *
- * maybeCurrency is typically null when the TalerAmount object gets
- * defined by the Database class.
- */
-@Serializable(with = TalerAmount.Serializer::class)
-class TalerAmount {
- val value: Long
- val frac: Int
- val currency: String
-
- constructor(value: Long, frac: Int, currency: String) {
- this.value = value
- this.frac = frac
- this.currency = currency
- }
- constructor(encoded: String) {
- val match = PATTERN.matchEntire(encoded) ?: throw badRequest(
- "Invalid amount format",
- TalerErrorCode.BANK_BAD_FORMAT_AMOUNT
- );
- val (currency, value, frac) = match.destructured
- this.currency = currency
- this.value = value.toLongOrNull() ?: throw badRequest(
- "Invalid value",
- TalerErrorCode.BANK_BAD_FORMAT_AMOUNT
- )
- if (this.value > MAX_VALUE) throw badRequest(
- "Value specified in amount is too large",
- TalerErrorCode.BANK_NUMBER_TOO_BIG
- )
- this.frac = if (frac.isEmpty()) {
- 0
- } else {
- var tmp = frac.toIntOrNull() ?: throw badRequest(
- "Invalid fractional value",
- TalerErrorCode.BANK_BAD_FORMAT_AMOUNT
- )
- if (tmp > FRACTION_BASE) throw badRequest(
- "Fractional calue specified in amount is too large",
- TalerErrorCode.BANK_NUMBER_TOO_BIG
- )
- repeat(8 - frac.length) {
- tmp *= 10
- }
- tmp
- }
- }
-
- override fun equals(other: Any?): Boolean {
- return other is TalerAmount &&
- other.value == this.value &&
- other.frac == this.frac &&
- other.currency == this.currency
- }
-
- override fun toString(): String {
- if (frac == 0) {
- return "$currency:$value"
- } else {
- return "$currency:$value.${frac.toString().padStart(8, '0')}"
- .dropLastWhile { it == '0' } // Trim useless fractional
trailing 0
- }
- }
-
- internal object Serializer : KSerializer<TalerAmount> {
- override val descriptor: SerialDescriptor =
- PrimitiveSerialDescriptor("TalerAmount", PrimitiveKind.STRING)
-
- override fun serialize(encoder: Encoder, value: TalerAmount) {
- encoder.encodeString(value.toString())
- }
-
- override fun deserialize(decoder: Decoder): TalerAmount {
- return TalerAmount(decoder.decodeString())
- }
- }
-
- companion object {
- const val FRACTION_BASE = 100000000
- const val MAX_VALUE = 4503599627370496L; // 2^52
- private val PATTERN =
Regex("([A-Z]{1,11}):([0-9]+)(?:\\.([0-9]{1,8}))?");
- }
-}
-
@Serializable(with = DecimalNumber.Serializer::class)
class DecimalNumber {
val value: Long
@@ -413,88 +319,4 @@ class ExchangeUrl {
return ExchangeUrl(decoder.decodeString())
}
}
-}
-
-sealed class PaytoUri {
- abstract val amount: TalerAmount?
- abstract val message: String?
- abstract val receiverName: String?
-}
-
-// TODO x-taler-bank Payto
-
-@Serializable(with = IbanPayTo.Serializer::class)
-class IbanPayTo: PaytoUri {
- val parsed: URI
- val canonical: String
- val iban: String
- override val amount: TalerAmount?
- override val message: String?
- override val receiverName: String?
-
- constructor(raw: String) {
- parsed = URI(raw)
- require(parsed.scheme == "payto") { "expect a payto URI" }
- require(parsed.host == "iban") { "expect a IBAN payto URI" }
-
- val splitPath = parsed.path.split("/").filter { it.isNotEmpty() }
- require(splitPath.size < 3 && splitPath.isNotEmpty()) { "too many path
segments" }
- val rawIban = if (splitPath.size == 1) splitPath[0] else splitPath[1]
- iban = rawIban.uppercase().replace(SEPARATOR, "")
- checkIban(iban)
- canonical = "payto://iban/$iban"
-
- val params = (parsed.query ?: "").parseUrlEncodedParameters();
- amount = params["amount"]?.run { TalerAmount(this) }
- message = params["message"]
- receiverName = params["receiver-name"]
- }
-
- /** Canonical IBAN payto with receiver-name parameter if present */
- fun maybeFull(): String {
- return canonical + if (receiverName != null) ("?receiver-name=" +
receiverName.encodeURLParameter()) else ""
- }
-
- /** Canonical IBAN payto with receiver-name parameter, fail if absent */
- fun expectFull(): String {
- return canonical + "?receiver-name=" +
receiverName!!.encodeURLParameter()
- }
-
- /** Canonical IBAN payto with receiver-name parameter set to [defaultName]
if absent */
- fun fullOptName(defaultName: String): String {
- return canonical + "?receiver-name=" + (receiverName ?:
defaultName).encodeURLParameter()
- }
-
- override fun toString(): String = canonical
-
- internal object Serializer : KSerializer<IbanPayTo> {
- override val descriptor: SerialDescriptor =
- PrimitiveSerialDescriptor("IbanPayTo", PrimitiveKind.STRING)
-
- override fun serialize(encoder: Encoder, value: IbanPayTo) {
- encoder.encodeString(value.parsed.toString())
- }
-
- override fun deserialize(decoder: Decoder): IbanPayTo {
- return IbanPayTo(decoder.decodeString())
- }
- }
-
- companion object {
- private val SEPARATOR = Regex("[\\ \\-]");
-
- fun checkIban(iban: String) {
- val builder = StringBuilder(iban.length + iban.asSequence().map {
if (it.isDigit()) 1 else 2 }.sum())
- (iban.subSequence(4, iban.length).asSequence() +
iban.subSequence(0, 4).asSequence()).forEach {
- if (it.isDigit()) {
- builder.append(it)
- } else {
- builder.append((it.code - 'A'.code) + 10)
- }
- }
- val str = builder.toString()
- val mod = str.toBigInteger().mod(97.toBigInteger()).toInt();
- if (mod != 1) throw badRequest("Iban malformed, modulo is $mod
expected 1")
- }
- }
-}
+}
\ No newline at end of file
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/TalerMessage.kt
b/bank/src/main/kotlin/tech/libeufin/bank/TalerMessage.kt
index 3d27fbac..b4857085 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/TalerMessage.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/TalerMessage.kt
@@ -19,11 +19,10 @@
package tech.libeufin.bank
+import tech.libeufin.common.*
import io.ktor.http.*
import io.ktor.server.application.*
import kotlinx.serialization.*
-import net.taler.wallet.crypto.Base32Crockford
-import net.taler.wallet.crypto.EncodingException
import java.time.Duration
import java.time.Instant
import java.time.temporal.ChronoUnit
@@ -173,8 +172,8 @@ data class RegisterAccountRequest(
val is_public: Boolean = false,
val is_taler_exchange: Boolean = false,
val contact_data: ChallengeContactData? = null,
- val cashout_payto_uri: IbanPayTo? = null,
- val payto_uri: IbanPayTo? = null,
+ val cashout_payto_uri: IbanPayto? = null,
+ val payto_uri: IbanPayto? = null,
val debit_threshold: TalerAmount? = null,
val tan_channel: TanChannel? = null,
)
@@ -190,7 +189,7 @@ data class RegisterAccountResponse(
@Serializable
data class AccountReconfiguration(
val contact_data: ChallengeContactData? = null,
- val cashout_payto_uri: Option<IbanPayTo?> = Option.None,
+ val cashout_payto_uri: Option<IbanPayto?> = Option.None,
val name: String? = null,
val is_public: Boolean? = null,
val debit_threshold: TalerAmount? = null,
@@ -359,7 +358,7 @@ data class AccountData(
@Serializable
data class TransactionCreateRequest(
- val payto_uri: IbanPayTo,
+ val payto_uri: IbanPayto,
val amount: TalerAmount?
)
@@ -441,7 +440,7 @@ data class BankWithdrawalOperationStatus(
@Serializable
data class BankWithdrawalOperationPostRequest(
val reserve_pub: EddsaPublicKey,
- val selected_exchange: IbanPayTo,
+ val selected_exchange: IbanPayto,
)
/**
@@ -524,7 +523,7 @@ data class ConversionResponse(
data class AddIncomingRequest(
val amount: TalerAmount,
val reserve_pub: EddsaPublicKey,
- val debit_account: IbanPayTo
+ val debit_account: IbanPayto
)
/**
@@ -612,7 +611,7 @@ data class TransferRequest(
val amount: TalerAmount,
val exchange_base_url: ExchangeUrl,
val wtid: ShortHashCode,
- val credit_account: IbanPayTo
+ val credit_account: IbanPayto
)
/**
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/WireGatewayApi.kt
b/bank/src/main/kotlin/tech/libeufin/bank/WireGatewayApi.kt
index fa376fd4..eba396a1 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/WireGatewayApi.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/WireGatewayApi.kt
@@ -28,7 +28,7 @@ import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.ktor.util.pipeline.PipelineContext
import java.time.Instant
-import net.taler.common.errorcodes.TalerErrorCode
+import tech.libeufin.common.*
import tech.libeufin.bank.db.*
import tech.libeufin.bank.db.ExchangeDAO.*
import tech.libeufin.bank.auth.*
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/auth/auth.kt
b/bank/src/main/kotlin/tech/libeufin/bank/auth/auth.kt
index 7898dad6..b7b5befe 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/auth/auth.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/auth/auth.kt
@@ -26,12 +26,10 @@ import io.ktor.server.response.header
import io.ktor.util.AttributeKey
import io.ktor.util.pipeline.PipelineContext
import java.time.Instant
-import net.taler.common.errorcodes.TalerErrorCode
-import net.taler.wallet.crypto.Base32Crockford
import tech.libeufin.bank.db.AccountDAO.*
import tech.libeufin.bank.db.*
import tech.libeufin.bank.*
-import tech.libeufin.util.*
+import tech.libeufin.common.*
/** Used to store if the currenly authenticated user is admin */
private val AUTH_IS_ADMIN = AttributeKey<Boolean>("is_admin");
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/AccountDAO.kt
b/bank/src/main/kotlin/tech/libeufin/bank/db/AccountDAO.kt
index e9e30c52..cfd65156 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/db/AccountDAO.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/db/AccountDAO.kt
@@ -19,7 +19,7 @@
package tech.libeufin.bank.db
-import tech.libeufin.util.*
+import tech.libeufin.common.*
import java.time.*
import java.sql.Types
import tech.libeufin.bank.*
@@ -41,8 +41,8 @@ class AccountDAO(private val db: Database) {
name: String,
email: String?,
phone: String?,
- cashoutPayto: IbanPayTo?,
- internalPaytoUri: IbanPayTo,
+ cashoutPayto: IbanPayto?,
+ internalPaytoUri: IbanPayto,
isPublic: Boolean,
isTalerExchange: Boolean,
maxDebt: TalerAmount,
@@ -71,7 +71,7 @@ class AccountDAO(private val db: Database) {
setString(1, name)
setString(2, email)
setString(3, phone)
- setString(4, cashoutPayto?.fullOptName(name))
+ setString(4, cashoutPayto?.full(name)?.full)
setBoolean(5, checkPaytoIdempotent)
setString(6, internalPaytoUri.canonical)
setBoolean(7, isPublic)
@@ -122,7 +122,7 @@ class AccountDAO(private val db: Database) {
setString(3, name)
setString(4, email)
setString(5, phone)
- setString(6, cashoutPayto?.fullOptName(name))
+ setString(6, cashoutPayto?.full(name)?.full)
setString(7, tanChannel?.name)
oneOrNull { it.getLong("customer_id") }!!
}
@@ -223,7 +223,7 @@ class AccountDAO(private val db: Database) {
suspend fun reconfig(
login: String,
name: String?,
- cashoutPayto: Option<IbanPayTo?>,
+ cashoutPayto: Option<IbanPayto?>,
phone: Option<String?>,
email: Option<String?>,
tan_channel: Option<TanChannel?>,
@@ -292,12 +292,12 @@ class AccountDAO(private val db: Database) {
null -> null
}
// Cashout payto with a receiver-name using if receiver-name is
missing the new named if present or the current one
- val cashoutPaytoNamed = cashoutPayto.get()?.fullOptName(name ?:
curr.name)
+ val fullCashoutPayto = cashoutPayto.get()?.full(name ?: curr.name)
// Check reconfig rights
if (checkName && name != curr.name)
return@transaction AccountPatchResult.NonAdminName
- if (checkCashout && cashoutPaytoNamed != curr.cashoutPayTo)
+ if (checkCashout && fullCashoutPayto?.full != curr.cashoutPayTo)
return@transaction AccountPatchResult.NonAdminCashout
if (checkDebtLimit && debtLimit != curr.debtLimit)
return@transaction AccountPatchResult.NonAdminDebtLimit
@@ -352,7 +352,7 @@ class AccountDAO(private val db: Database) {
},
"WHERE customer_id = ?",
sequence {
- cashoutPayto.some { yield(cashoutPaytoNamed) }
+ cashoutPayto.some { yield(fullCashoutPayto?.full) }
phone.some { yield(it) }
email.some { yield(it) }
tan_channel.some { yield(it?.name) }
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/CashoutDAO.kt
b/bank/src/main/kotlin/tech/libeufin/bank/db/CashoutDAO.kt
index a7950aa2..25e6ed61 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/db/CashoutDAO.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/db/CashoutDAO.kt
@@ -22,7 +22,7 @@ package tech.libeufin.bank.db
import java.time.Duration
import java.time.Instant
import java.util.concurrent.TimeUnit
-import tech.libeufin.util.*
+import tech.libeufin.common.*
import tech.libeufin.bank.*
/** Data access logic for cashout operations */
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/ConversionDAO.kt
b/bank/src/main/kotlin/tech/libeufin/bank/db/ConversionDAO.kt
index b2d521c7..fc46b91e 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/db/ConversionDAO.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/db/ConversionDAO.kt
@@ -19,7 +19,7 @@
package tech.libeufin.bank.db
-import tech.libeufin.util.*
+import tech.libeufin.common.*
import tech.libeufin.bank.*
import tech.libeufin.bank.*
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/Database.kt
b/bank/src/main/kotlin/tech/libeufin/bank/db/Database.kt
index 27cbfc2f..a0edbdec 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/db/Database.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/db/Database.kt
@@ -32,10 +32,8 @@ import java.util.concurrent.TimeUnit
import kotlin.math.abs
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.*
-import com.zaxxer.hikari.*
-import tech.libeufin.util.*
+import tech.libeufin.common.*
import io.ktor.http.HttpStatusCode
-import net.taler.common.errorcodes.TalerErrorCode
import tech.libeufin.bank.*
private val logger: Logger = LoggerFactory.getLogger("libeufin-bank-db")
@@ -59,27 +57,8 @@ private val logger: Logger =
LoggerFactory.getLogger("libeufin-bank-db")
internal fun faultyTimestampByBank() = internalServerError("Bank took
overflowing timestamp")
internal fun faultyDurationByClient() = badRequest("Overflowing duration,
please specify 'forever' instead.")
-class Database(dbConfig: String, internal val bankCurrency: String, internal
val fiatCurrency: String?): java.io.Closeable {
- val dbPool: HikariDataSource
- internal val notifWatcher: NotificationWatcher
-
- init {
- val pgSource = pgDataSource(dbConfig)
- val config = HikariConfig();
- config.dataSource = pgSource
- config.connectionInitSql = "SET search_path TO libeufin_bank;SET
SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE;"
- config.validate()
- dbPool = HikariDataSource(config);
- dbPool.getConnection().use { con ->
- val meta = con.getMetaData();
- val majorVersion = meta.getDatabaseMajorVersion()
- val minorVersion = meta.getDatabaseMinorVersion()
- if (majorVersion < MIN_VERSION) {
- throw Exception("postgres version must be at least
$MIN_VERSION.0 got $majorVersion.$minorVersion")
- }
- }
- notifWatcher = NotificationWatcher(pgSource)
- }
+class Database(dbConfig: String, internal val bankCurrency: String, internal
val fiatCurrency: String?): DbPool(dbConfig, "libeufin_bank") {
+ internal val notifWatcher: NotificationWatcher =
NotificationWatcher(pgSource)
val cashout = CashoutDAO(this)
val withdrawal = WithdrawalDAO(this)
@@ -142,36 +121,6 @@ class Database(dbConfig: String, internal val
bankCurrency: String, internal val
} ?: throw internalServerError("No result from DB procedure
stats_get_frame")
}
- override fun close() {
- dbPool.close()
- }
-
- suspend fun <R> conn(lambda: suspend (PgConnection) -> R): R {
- // Use a coroutine dispatcher that we can block as JDBC API is blocking
- return withContext(Dispatchers.IO) {
- val conn = dbPool.getConnection()
- conn.use{ it -> lambda(it.unwrap(PgConnection::class.java)) }
- }
- }
-
-
- suspend fun <R> serializable(lambda: suspend (PgConnection) -> R): R =
conn { conn ->
- repeat(SERIALIZATION_RETRY) {
- try {
- return@conn lambda(conn);
- } catch (e: SQLException) {
- if (e.sqlState != PSQLState.SERIALIZATION_FAILURE.state)
- throw e
- }
- }
- try {
- return@conn lambda(conn)
- } catch(e: SQLException) {
- logger.warn("Serialization failure after $SERIALIZATION_RETRY
retry")
- throw e
- }
- }
-
/** Apply paging logic to a sql query */
internal suspend fun <T> page(
params: PageParams,
@@ -260,12 +209,4 @@ fun ResultSet.getTalerTimestamp(name: String):
TalerProtocolTimestamp{
return TalerProtocolTimestamp(
getLong(name).microsToJavaInstant() ?: throw faultyTimestampByBank()
)
-}
-
-fun ResultSet.getAmount(name: String, currency: String): TalerAmount{
- return TalerAmount(
- getLong("${name}_val"),
- getInt("${name}_frac"),
- currency
- )
}
\ No newline at end of file
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/ExchangeDAO.kt
b/bank/src/main/kotlin/tech/libeufin/bank/db/ExchangeDAO.kt
index 44cb272c..3339bae6 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/db/ExchangeDAO.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/db/ExchangeDAO.kt
@@ -23,7 +23,7 @@ import java.util.UUID
import java.time.Instant
import java.time.Duration
import java.util.concurrent.TimeUnit
-import tech.libeufin.util.*
+import tech.libeufin.common.*
import tech.libeufin.bank.*
/** Data access logic for exchange specific logic */
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/NotificationWatcher.kt
b/bank/src/main/kotlin/tech/libeufin/bank/db/NotificationWatcher.kt
index c17ffb58..973423e1 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/db/NotificationWatcher.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/db/NotificationWatcher.kt
@@ -26,7 +26,7 @@ import kotlinx.coroutines.flow.*
import org.postgresql.ds.PGSimpleDataSource
import org.slf4j.Logger
import org.slf4j.LoggerFactory
-import tech.libeufin.util.*
+import tech.libeufin.common.*
import tech.libeufin.bank.*
private val logger: Logger =
LoggerFactory.getLogger("libeufin-bank-db-watcher")
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/TanDAO.kt
b/bank/src/main/kotlin/tech/libeufin/bank/db/TanDAO.kt
index 457d1216..3594b188 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/db/TanDAO.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/db/TanDAO.kt
@@ -19,7 +19,7 @@
package tech.libeufin.bank.db
-import tech.libeufin.util.*
+import tech.libeufin.common.*
import tech.libeufin.bank.*
import tech.libeufin.bank.db.*
import java.util.concurrent.TimeUnit
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/TokenDAO.kt
b/bank/src/main/kotlin/tech/libeufin/bank/db/TokenDAO.kt
index d3754938..92708308 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/db/TokenDAO.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/db/TokenDAO.kt
@@ -19,7 +19,7 @@
package tech.libeufin.bank.db
-import tech.libeufin.util.*
+import tech.libeufin.common.*
import java.time.Instant
import tech.libeufin.bank.*
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/TransactionDAO.kt
b/bank/src/main/kotlin/tech/libeufin/bank/db/TransactionDAO.kt
index 9c21fd53..b6038dc5 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/db/TransactionDAO.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/db/TransactionDAO.kt
@@ -21,7 +21,7 @@ package tech.libeufin.bank.db
import org.slf4j.Logger
import org.slf4j.LoggerFactory
-import tech.libeufin.util.*
+import tech.libeufin.common.*
import java.time.*
import java.sql.Types
import tech.libeufin.bank.*
@@ -43,7 +43,7 @@ class TransactionDAO(private val db: Database) {
/** Create a new transaction */
suspend fun create(
- creditAccountPayto: IbanPayTo,
+ creditAccountPayto: IbanPayto,
debitAccountUsername: String,
subject: String,
amount: TalerAmount,
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/WithdrawalDAO.kt
b/bank/src/main/kotlin/tech/libeufin/bank/db/WithdrawalDAO.kt
index 380263b4..72b92490 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/db/WithdrawalDAO.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/db/WithdrawalDAO.kt
@@ -23,7 +23,7 @@ import java.util.UUID
import java.time.Instant
import java.time.Duration
import java.util.concurrent.TimeUnit
-import tech.libeufin.util.*
+import tech.libeufin.common.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.*
import tech.libeufin.bank.*
@@ -102,7 +102,7 @@ class WithdrawalDAO(private val db: Database) {
/** Set details ([exchangePayto] & [reservePub]) for withdrawal operation
[uuid] */
suspend fun setDetails(
uuid: UUID,
- exchangePayto: IbanPayTo,
+ exchangePayto: IbanPayto,
reservePub: EddsaPublicKey
): WithdrawalSelectionResult = db.serializable { conn ->
val stmt = conn.prepareStatement("""
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt
b/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt
index 47de2b15..b40223c6 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt
@@ -36,8 +36,7 @@ import java.net.*
import java.time.*
import java.time.temporal.*
import java.util.*
-import net.taler.common.errorcodes.TalerErrorCode
-import tech.libeufin.util.*
+import tech.libeufin.common.*
import tech.libeufin.bank.db.*
import tech.libeufin.bank.db.AccountDAO.*
import tech.libeufin.bank.auth.*
@@ -126,7 +125,7 @@ suspend fun maybeCreateAdminAccount(db: Database, ctx:
BankConfig, pw: String? =
login = "admin",
password = pwStr,
name = "Bank administrator",
- internalPaytoUri = IbanPayTo(genIbanPaytoUri()),
+ internalPaytoUri = IbanPayto(genIbanPaytoUri()),
isPublic = false,
isTalerExchange = false,
maxDebt = ctx.defaultDebtLimit,
diff --git a/bank/src/test/kotlin/AmountTest.kt
b/bank/src/test/kotlin/AmountTest.kt
index 43b6fbef..e23cdfda 100644
--- a/bank/src/test/kotlin/AmountTest.kt
+++ b/bank/src/test/kotlin/AmountTest.kt
@@ -26,13 +26,12 @@ import tech.libeufin.bank.*
import tech.libeufin.bank.db.*
import tech.libeufin.bank.db.TransactionDAO.*
import tech.libeufin.bank.db.WithdrawalDAO.*
-import tech.libeufin.util.*
+import tech.libeufin.common.*
class AmountTest {
// Test amount computation in database
@Test
- fun computationTest() = bankSetup { db ->
- val conn = db.dbPool.getConnection().unwrap(PgConnection::class.java)
+ fun computationTest() = bankSetup { db -> db.conn { conn ->
conn.execSQLUpdate("UPDATE libeufin_bank.bank_accounts SET balance.val
= 100000 WHERE internal_payto_uri = '$customerPayto'")
val stmt = conn.prepareStatement("""
UPDATE libeufin_bank.bank_accounts
@@ -125,29 +124,7 @@ class AmountTest {
hasBalanceDebt = true,
maxDebt = TalerAmount(0, 1, "KUDOS")
))
-
-
- }
-
- @Test
- fun parse() {
- assertEquals(TalerAmount("EUR:4"), TalerAmount(4L, 0, "EUR"))
- assertEquals(TalerAmount("EUR:0.02"), TalerAmount(0L, 2000000, "EUR"))
- assertEquals(TalerAmount("EUR:4.12"), TalerAmount(4L, 12000000, "EUR"))
- assertEquals(TalerAmount("LOCAL:4444.1000"), TalerAmount(4444L,
10000000, "LOCAL"))
- assertEquals(TalerAmount("EUR:${TalerAmount.MAX_VALUE}.99999999"),
TalerAmount(TalerAmount.MAX_VALUE, 99999999, "EUR"))
-
- assertException("Invalid amount format") {TalerAmount("")}
- assertException("Invalid amount format") {TalerAmount("EUR")}
- assertException("Invalid amount format") {TalerAmount("eur:12")}
- assertException("Invalid amount format") {TalerAmount(" EUR:12")}
- assertException("Invalid amount format") {TalerAmount("EUR:1.")}
- assertException("Invalid amount format") {TalerAmount("EUR:.1")}
- assertException("Invalid amount format")
{TalerAmount("AZERTYUIOPQSD:12")}
- assertException("Value specified in amount is too large")
{TalerAmount("EUR:${Long.MAX_VALUE}")}
- assertException("Invalid amount format")
{TalerAmount("EUR:4.000000000")}
- assertException("Invalid amount format") {TalerAmount("EUR:4.4a")}
- }
+ }}
@Test
fun parseRoundTrip() {
@@ -336,4 +313,19 @@ class AmountTest {
}
}
}
+
+ @Test
+ fun apiError() = bankSetup { _ ->
+ val base = obj {
+ "payto_uri" to "$exchangePayto?message=payout"
+ }
+
+ // Check OK
+ client.postA("/accounts/merchant/transactions") {
+ json(base) { "amount" to "KUDOS:0.3ABC" }
+ }.assertBadRequest(TalerErrorCode.BANK_BAD_FORMAT_AMOUNT)
+ client.postA("/accounts/merchant/transactions") {
+ json(base) { "amount" to "KUDOS:999999999999999999" }
+ }.assertBadRequest(TalerErrorCode.BANK_NUMBER_TOO_BIG)
+ }
}
\ No newline at end of file
diff --git a/bank/src/test/kotlin/BankIntegrationApiTest.kt
b/bank/src/test/kotlin/BankIntegrationApiTest.kt
index ce6b46c7..d2205f21 100644
--- a/bank/src/test/kotlin/BankIntegrationApiTest.kt
+++ b/bank/src/test/kotlin/BankIntegrationApiTest.kt
@@ -26,11 +26,10 @@ import java.util.*
import kotlin.test.*
import kotlinx.coroutines.*
import kotlinx.serialization.json.*
-import net.taler.common.errorcodes.TalerErrorCode
import org.junit.Test
import tech.libeufin.bank.*
import tech.libeufin.bank.db.*
-import tech.libeufin.util.*
+import tech.libeufin.common.*
class BankIntegrationApiTest {
// GET /taler-integration/config
diff --git a/bank/src/test/kotlin/ConversionApiTest.kt
b/bank/src/test/kotlin/ConversionApiTest.kt
index 588a4e54..a228705f 100644
--- a/bank/src/test/kotlin/ConversionApiTest.kt
+++ b/bank/src/test/kotlin/ConversionApiTest.kt
@@ -26,9 +26,9 @@ import java.util.*
import kotlin.test.*
import kotlinx.coroutines.*
import kotlinx.serialization.json.*
-import net.taler.common.errorcodes.TalerErrorCode
import org.junit.Test
import tech.libeufin.bank.*
+import tech.libeufin.common.*
class ConversionApiTest {
// GET /conversion-info/config
diff --git a/bank/src/test/kotlin/CoreBankApiTest.kt
b/bank/src/test/kotlin/CoreBankApiTest.kt
index c9ecfa03..bd001feb 100644
--- a/bank/src/test/kotlin/CoreBankApiTest.kt
+++ b/bank/src/test/kotlin/CoreBankApiTest.kt
@@ -30,12 +30,10 @@ import java.util.*
import kotlin.test.*
import kotlinx.coroutines.*
import kotlinx.serialization.json.JsonElement
-import net.taler.common.errorcodes.TalerErrorCode
-import net.taler.wallet.crypto.Base32Crockford
import org.junit.Test
import tech.libeufin.bank.*
import tech.libeufin.bank.db.*
-import tech.libeufin.util.*
+import tech.libeufin.common.*
class CoreBankConfigTest {
// GET /config
@@ -195,20 +193,20 @@ class CoreBankAccountsApiTest {
}
// Check given payto
- val ibanPayto = IbanPayTo(genIbanPaytoUri())
+ val IbanPayto = IbanPayto(genIbanPaytoUri())
val req = obj {
"username" to "foo"
"password" to "password"
"name" to "Jane"
"is_public" to true
- "payto_uri" to ibanPayto
+ "payto_uri" to IbanPayto
"is_taler_exchange" to true
}
// Check Ok
client.post("/accounts") {
json(req)
}.assertOkJson<RegisterAccountResponse> {
- assertEquals(ibanPayto.canonical, it.internal_payto_uri)
+ assertEquals(IbanPayto.canonical, it.internal_payto_uri)
}
// Testing idempotency
client.post("/accounts") {
@@ -305,13 +303,13 @@ class CoreBankAccountsApiTest {
"username" to "cashout_guess"
"password" to "cashout_guess-password"
"name" to "Mr Guess My Name"
- "cashout_payto_uri" to ibanPayto
+ "cashout_payto_uri" to IbanPayto
}
}.assertOk()
client.getA("/accounts/cashout_guess").assertOkJson<AccountData> {
- assertEquals(ibanPayto.fullOptName("Mr Guess My Name"),
it.cashout_payto_uri)
+ assertEquals(IbanPayto.full("Mr Guess My Name").full,
it.cashout_payto_uri)
}
- val full = ibanPayto.fullOptName("Santa Claus")
+ val full = IbanPayto.full("Santa Claus").full
client.post("/accounts") {
json {
"username" to "cashout_keep"
@@ -488,7 +486,7 @@ class CoreBankAccountsApiTest {
}
// Successful attempt now
- val cashout = IbanPayTo(genIbanPaytoUri())
+ val cashout = IbanPayto(genIbanPaytoUri())
val req = obj {
"cashout_payto_uri" to cashout
"name" to "Roger"
@@ -521,7 +519,7 @@ class CoreBankAccountsApiTest {
// Check patch
client.getA("/accounts/merchant").assertOkJson<AccountData> { obj ->
assertEquals("Roger", obj.name)
- assertEquals(cashout.fullOptName(obj.name), obj.cashout_payto_uri)
+ assertEquals(cashout.full(obj.name).full, obj.cashout_payto_uri)
assertEquals("+99", obj.contact_data?.phone?.get())
assertEquals("foo@example.com", obj.contact_data?.email?.get())
assertEquals(TalerAmount("KUDOS:100"), obj.debit_threshold)
@@ -535,7 +533,7 @@ class CoreBankAccountsApiTest {
}.assertNoContent()
client.getA("/accounts/merchant").assertOkJson<AccountData> { obj ->
assertEquals("Roger", obj.name)
- assertEquals(cashout.fullOptName(obj.name), obj.cashout_payto_uri)
+ assertEquals(cashout.full(obj.name).full, obj.cashout_payto_uri)
assertEquals("+99", obj.contact_data?.phone?.get())
assertEquals("foo@example.com", obj.contact_data?.email?.get())
assertEquals(TalerAmount("KUDOS:100"), obj.debit_threshold)
@@ -559,10 +557,10 @@ class CoreBankAccountsApiTest {
}
}.assertOk()
for ((cashout, name, expect) in listOf(
- Triple(cashout.canonical, null, cashout.fullOptName("Mr Cashout
Cashout")),
- Triple(cashout.canonical, "New name", cashout.fullOptName("New
name")),
- Triple(cashout.fullOptName("Full name"), null,
cashout.fullOptName("Full name")),
- Triple(cashout.fullOptName("Full second name"), "Another name",
cashout.fullOptName("Full second name"))
+ Triple(cashout.canonical, null, cashout.full("Mr Cashout
Cashout").full),
+ Triple(cashout.canonical, "New name", cashout.full("New
name").full),
+ Triple(cashout.full("Full name").full, null, cashout.full("Full
name").full),
+ Triple(cashout.full("Full second name").full, "Another name",
cashout.full("Full second name").full)
)) {
client.patch("/accounts/cashout") {
pwAuth("admin")
diff --git a/bank/src/test/kotlin/DatabaseTest.kt
b/bank/src/test/kotlin/DatabaseTest.kt
index de1e608f..01cb0dd2 100644
--- a/bank/src/test/kotlin/DatabaseTest.kt
+++ b/bank/src/test/kotlin/DatabaseTest.kt
@@ -30,7 +30,7 @@ import kotlinx.coroutines.*
import org.junit.Test
import tech.libeufin.bank.*
import tech.libeufin.bank.db.AccountDAO.*
-import tech.libeufin.util.*
+import tech.libeufin.common.*
class DatabaseTest {
@@ -168,40 +168,6 @@ class DatabaseTest {
assertEquals(Triple(true, false, false), cTry(this, "new-code",
expired))
}
}}
-
- // Testing iban payto uri normalization
- @Test
- fun ibanPayto() = setup { _, _ ->
- val canonical = "payto://iban/CH9300762011623852957"
- val inputs = listOf(
- "payto://iban/BIC/CH9300762011623852957?receiver-name=NotGiven",
- "payto://iban/CH9300762011623852957?receiver-name=Grothoff%20Hans",
- "payto://iban/ch%209300-7620-1162-3852-957",
- )
- val names = listOf(
- "NotGiven", "Grothoff Hans", null
- )
- val full = listOf(
- "payto://iban/CH9300762011623852957?receiver-name=NotGiven",
- "payto://iban/CH9300762011623852957?receiver-name=Grothoff%20Hans",
- canonical
- )
- for ((i, input) in inputs.withIndex()) {
- val payto = IbanPayTo(input)
- assertEquals(canonical, payto.canonical)
- assertEquals(full[i], payto.maybeFull())
- assertEquals(names[i], payto.receiverName)
- }
-
- assertEquals(
- "payto://iban/CH9300762011623852957?receiver-name=Grothoff%20Hans",
-
IbanPayTo("payto://iban/CH9300762011623852957?receiver-name=Grothoff%20Hans").fullOptName("Santa
Claus")
- )
- assertEquals(
- "payto://iban/CH9300762011623852957?receiver-name=Santa%20Claus",
- IbanPayTo("payto://iban/CH9300762011623852957").fullOptName("Santa
Claus")
- )
- }
}
diff --git a/bank/src/test/kotlin/JsonTest.kt b/bank/src/test/kotlin/JsonTest.kt
index 82af4d2d..3a7e5f21 100644
--- a/bank/src/test/kotlin/JsonTest.kt
+++ b/bank/src/test/kotlin/JsonTest.kt
@@ -25,6 +25,7 @@ import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import org.junit.Test
import tech.libeufin.bank.*
+import tech.libeufin.common.*
@Serializable
data class MyJsonType(
diff --git a/bank/src/test/kotlin/SecurityTest.kt
b/bank/src/test/kotlin/SecurityTest.kt
index c73140e2..b3c5f5ac 100644
--- a/bank/src/test/kotlin/SecurityTest.kt
+++ b/bank/src/test/kotlin/SecurityTest.kt
@@ -27,7 +27,7 @@ import kotlin.test.*
import kotlinx.coroutines.*
import org.junit.Test
import tech.libeufin.bank.*
-import tech.libeufin.util.*
+import tech.libeufin.common.*
class SecurityTest {
@Test
diff --git a/bank/src/test/kotlin/StatsTest.kt
b/bank/src/test/kotlin/StatsTest.kt
index 4198dbe4..1aa1979e 100644
--- a/bank/src/test/kotlin/StatsTest.kt
+++ b/bank/src/test/kotlin/StatsTest.kt
@@ -28,7 +28,7 @@ import java.util.*
import kotlin.test.*
import org.junit.Test
import tech.libeufin.bank.*
-import tech.libeufin.util.*
+import tech.libeufin.common.*
class StatsTest {
@Test
diff --git a/bank/src/test/kotlin/WireGatewayApiTest.kt
b/bank/src/test/kotlin/WireGatewayApiTest.kt
index 89c199ca..150de96a 100644
--- a/bank/src/test/kotlin/WireGatewayApiTest.kt
+++ b/bank/src/test/kotlin/WireGatewayApiTest.kt
@@ -25,10 +25,9 @@ import io.ktor.server.testing.*
import java.util.*
import kotlinx.coroutines.*
import kotlinx.serialization.json.*
-import net.taler.common.errorcodes.TalerErrorCode
import org.junit.Test
import tech.libeufin.bank.*
-import tech.libeufin.util.*
+import tech.libeufin.common.*
class WireGatewayApiTest {
// Testing the POST /transfer call from the TWG API.
diff --git a/bank/src/test/kotlin/helpers.kt b/bank/src/test/kotlin/helpers.kt
index 951d24f5..69c0ede9 100644
--- a/bank/src/test/kotlin/helpers.kt
+++ b/bank/src/test/kotlin/helpers.kt
@@ -29,28 +29,26 @@ import kotlin.test.*
import kotlin.random.Random
import kotlinx.coroutines.*
import kotlinx.serialization.json.*
-import net.taler.common.errorcodes.TalerErrorCode
-import net.taler.wallet.crypto.Base32Crockford
import tech.libeufin.bank.*
import tech.libeufin.bank.db.*
import tech.libeufin.bank.db.AccountDAO.*
-import tech.libeufin.util.*
+import tech.libeufin.common.*
/* ----- Setup ----- */
-val merchantPayto = IbanPayTo(genIbanPaytoUri())
-val exchangePayto = IbanPayTo(genIbanPaytoUri())
-val customerPayto = IbanPayTo(genIbanPaytoUri())
-val unknownPayto = IbanPayTo(genIbanPaytoUri())
-var tmpPayTo = IbanPayTo(genIbanPaytoUri())
+val merchantPayto = IbanPayto(genIbanPaytoUri())
+val exchangePayto = IbanPayto(genIbanPaytoUri())
+val customerPayto = IbanPayto(genIbanPaytoUri())
+val unknownPayto = IbanPayto(genIbanPaytoUri())
+var tmpPayTo = IbanPayto(genIbanPaytoUri())
val paytos = mapOf(
"merchant" to merchantPayto,
"exchange" to exchangePayto,
"customer" to customerPayto
)
-fun genTmpPayTo(): IbanPayTo {
- tmpPayTo = IbanPayTo(genIbanPaytoUri())
+fun genTmpPayTo(): IbanPayto {
+ tmpPayTo = IbanPayto(genIbanPaytoUri())
return tmpPayTo
}
diff --git a/bank/src/test/kotlin/routines.kt b/bank/src/test/kotlin/routines.kt
index 92fdfd9c..6618b157 100644
--- a/bank/src/test/kotlin/routines.kt
+++ b/bank/src/test/kotlin/routines.kt
@@ -18,7 +18,7 @@
*/
import tech.libeufin.bank.*
-import tech.libeufin.util.*
+import tech.libeufin.common.*
import io.ktor.client.statement.HttpResponse
import io.ktor.server.testing.ApplicationTestBuilder
import io.ktor.client.request.*
@@ -26,7 +26,6 @@ import io.ktor.http.*
import kotlin.test.*
import kotlinx.coroutines.*
import kotlinx.serialization.json.*
-import net.taler.common.errorcodes.TalerErrorCode
// Test endpoint is correctly authenticated
suspend fun ApplicationTestBuilder.authRoutine(
diff --git a/build.gradle b/build.gradle
index 87891a99..35df956e 100644
--- a/build.gradle
+++ b/build.gradle
@@ -52,7 +52,7 @@ task versionFile() {
}
def gitHash = stdout.toString().trim()
def version = getRootProject().version
- new File("${projectDir}/util/src/main/resources", "version.txt").text =
"v$version-git-$gitHash"
+ new File("${projectDir}/common/src/main/resources", "version.txt").text =
"v$version-git-$gitHash"
}
// See:
https://stackoverflow.com/questions/24936781/gradle-plugin-project-version-number
diff --git a/util/build.gradle b/common/build.gradle
similarity index 76%
copy from util/build.gradle
copy to common/build.gradle
index 0bd9b551..79b7fda3 100644
--- a/util/build.gradle
+++ b/common/build.gradle
@@ -1,8 +1,6 @@
-import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
-
plugins {
- id("java")
id("kotlin")
+ id("org.jetbrains.kotlin.plugin.serialization") version "$kotlin_version"
}
version = rootProject.version
@@ -19,14 +17,11 @@ sourceSets.main.java.srcDirs = ["src/main/kotlin"]
dependencies {
implementation("ch.qos.logback:logback-classic:1.4.5")
- // XML Stuff
- implementation("javax.xml.bind:jaxb-api:2.3.1")
- implementation("org.glassfish.jaxb:jaxb-runtime:2.3.1")
- implementation("org.apache.santuario:xmlsec:2.2.2")
// Crypto
implementation("org.bouncycastle:bcprov-jdk15on:1.69")
// Database helper
implementation("org.postgresql:postgresql:$postgres_version")
+ implementation("com.zaxxer:HikariCP:5.0.1")
implementation("io.ktor:ktor-serialization-kotlinx-json:$ktor_version")
implementation("io.ktor:ktor-server-test-host:$ktor_version")
diff --git a/util/import.py b/common/import.py
similarity index 98%
copy from util/import.py
copy to common/import.py
index e1389052..769f1a3d 100644
--- a/util/import.py
+++ b/common/import.py
@@ -56,7 +56,7 @@ kt = f"""/*
// THIS FILE IS GENERATED, DO NOT EDIT
-package tech.libeufin.util
+package tech.libeufin.common
{extractCodeSet("ExternalStatusReason1Code", "ExternalStatusReasonCode")}
diff --git a/util/src/main/kotlin/Backoff.kt b/common/src/main/kotlin/Backoff.kt
similarity index 97%
rename from util/src/main/kotlin/Backoff.kt
rename to common/src/main/kotlin/Backoff.kt
index db31e266..fdbc358f 100644
--- a/util/src/main/kotlin/Backoff.kt
+++ b/common/src/main/kotlin/Backoff.kt
@@ -17,7 +17,7 @@
* <http://www.gnu.org/licenses/>
*/
-package tech.libeufin.util
+package tech.libeufin.common
import kotlin.random.Random
diff --git a/util/src/main/kotlin/Cli.kt b/common/src/main/kotlin/Cli.kt
similarity index 96%
rename from util/src/main/kotlin/Cli.kt
rename to common/src/main/kotlin/Cli.kt
index 0c1803f5..2db1e906 100644
--- a/util/src/main/kotlin/Cli.kt
+++ b/common/src/main/kotlin/Cli.kt
@@ -17,11 +17,8 @@
* <http://www.gnu.org/licenses/>
*/
-package tech.libeufin.util
+package tech.libeufin.common
-import ConfigSource
-import TalerConfig
-import TalerConfigError
import com.github.ajalt.clikt.core.*
import com.github.ajalt.clikt.parameters.types.*
import com.github.ajalt.clikt.parameters.arguments.*
@@ -41,11 +38,11 @@ fun cliCmd(logger: Logger, level: Level, lambda: () ->
Unit) {
try {
lambda()
} catch (e: Throwable) {
- var msg = StringBuilder(e.message)
+ var msg = StringBuilder(e.message ?: e::class.simpleName)
var cause = e.cause;
while (cause != null) {
msg.append(": ")
- msg.append(cause.message)
+ msg.append(cause.message ?: cause::class.simpleName)
cause = cause.cause
}
logger.error(msg.toString())
diff --git a/util/src/main/kotlin/Client.kt b/common/src/main/kotlin/Client.kt
similarity index 97%
rename from util/src/main/kotlin/Client.kt
rename to common/src/main/kotlin/Client.kt
index 3ffbdbeb..b65f59db 100644
--- a/util/src/main/kotlin/Client.kt
+++ b/common/src/main/kotlin/Client.kt
@@ -17,7 +17,7 @@
* <http://www.gnu.org/licenses/>
*/
-package tech.libeufin.util
+package tech.libeufin.common
import io.ktor.http.*
import kotlinx.serialization.json.*
@@ -26,7 +26,6 @@ import io.ktor.client.statement.*
import java.io.ByteArrayOutputStream
import java.util.zip.DeflaterOutputStream
import kotlin.test.assertEquals
-import net.taler.common.errorcodes.TalerErrorCode
/* ----- Json DSL ----- */
diff --git a/util/src/main/kotlin/Config.kt b/common/src/main/kotlin/Config.kt
similarity index 97%
rename from util/src/main/kotlin/Config.kt
rename to common/src/main/kotlin/Config.kt
index 124a9db8..95496839 100644
--- a/util/src/main/kotlin/Config.kt
+++ b/common/src/main/kotlin/Config.kt
@@ -17,7 +17,7 @@
* <http://www.gnu.org/licenses/>
*/
-package tech.libeufin.util
+package tech.libeufin.common
import ch.qos.logback.core.util.Loader
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Metadata.kt
b/common/src/main/kotlin/Constants.kt
similarity index 67%
copy from bank/src/main/kotlin/tech/libeufin/bank/Metadata.kt
copy to common/src/main/kotlin/Constants.kt
index 4c1a13d7..054011d4 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/Metadata.kt
+++ b/common/src/main/kotlin/Constants.kt
@@ -1,6 +1,6 @@
/*
* This file is part of LibEuFin.
- * Copyright (C) 2023 Taler Systems S.A.
+ * Copyright (C) 2024 Taler Systems S.A.
* LibEuFin is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
@@ -16,15 +16,8 @@
* License along with LibEuFin; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>
*/
-package tech.libeufin.bank
+package tech.libeufin.common
-private val PATTERN = Regex("[a-z0-9A-Z]{52}")
-
-fun parseIncomingTxMetadata(subject: String): EddsaPublicKey? {
- val match = PATTERN.find(subject)?.value ?: return null;
- try {
- return EddsaPublicKey(match)
- } catch (e: Exception) {
- return null
- }
-}
\ No newline at end of file
+// DB
+const val MIN_VERSION: Int = 14
+const val SERIALIZATION_RETRY: Int = 10;
\ No newline at end of file
diff --git a/util/src/main/kotlin/CryptoUtil.kt
b/common/src/main/kotlin/CryptoUtil.kt
similarity index 99%
rename from util/src/main/kotlin/CryptoUtil.kt
rename to common/src/main/kotlin/CryptoUtil.kt
index 923e84da..bcf19ae1 100644
--- a/util/src/main/kotlin/CryptoUtil.kt
+++ b/common/src/main/kotlin/CryptoUtil.kt
@@ -17,9 +17,8 @@
* <http://www.gnu.org/licenses/>
*/
-package tech.libeufin.util
+package tech.libeufin.common
-import net.taler.wallet.crypto.Base32Crockford
import org.bouncycastle.jce.provider.BouncyCastleProvider
import java.io.ByteArrayOutputStream
import java.math.BigInteger
diff --git a/util/src/main/kotlin/DB.kt b/common/src/main/kotlin/DB.kt
similarity index 83%
rename from util/src/main/kotlin/DB.kt
rename to common/src/main/kotlin/DB.kt
index facff98b..5707bd7f 100644
--- a/util/src/main/kotlin/DB.kt
+++ b/common/src/main/kotlin/DB.kt
@@ -17,7 +17,7 @@
* <http://www.gnu.org/licenses/>
*/
-package tech.libeufin.util
+package tech.libeufin.common
import org.postgresql.ds.PGSimpleDataSource
import org.postgresql.jdbc.PgConnection
@@ -29,6 +29,8 @@ import java.net.URI
import java.sql.PreparedStatement
import java.sql.ResultSet
import java.sql.SQLException
+import kotlinx.coroutines.*
+import com.zaxxer.hikari.*
fun getCurrentUser(): String = System.getProperty("user.name")
@@ -276,4 +278,62 @@ fun resetDatabaseTables(conn: PgConnection, cfg:
DatabaseConfig, sqlFilePrefix:
val sqlDrop = File("${cfg.sqlDir}/$sqlFilePrefix-drop.sql").readText()
conn.execSQLUpdate(sqlDrop)
+}
+
+abstract class DbPool(cfg: String, schema: String): java.io.Closeable {
+ val pgSource = pgDataSource(cfg)
+ private val pool: HikariDataSource
+
+ init {
+ val config = HikariConfig();
+ config.dataSource = pgSource
+ config.schema = schema
+ config.transactionIsolation = "TRANSACTION_SERIALIZABLE"
+ pool = HikariDataSource(config)
+ pool.getConnection().use { con ->
+ val meta = con.getMetaData();
+ val majorVersion = meta.getDatabaseMajorVersion()
+ val minorVersion = meta.getDatabaseMinorVersion()
+ if (majorVersion < MIN_VERSION) {
+ throw Exception("postgres version must be at least
$MIN_VERSION.0 got $majorVersion.$minorVersion")
+ }
+ }
+ }
+
+ suspend fun <R> conn(lambda: suspend (PgConnection) -> R): R {
+ // Use a coroutine dispatcher that we can block as JDBC API is blocking
+ return withContext(Dispatchers.IO) {
+ val conn = pool.getConnection()
+ conn.use{ it -> lambda(it.unwrap(PgConnection::class.java)) }
+ }
+ }
+
+ suspend fun <R> serializable(lambda: suspend (PgConnection) -> R): R =
conn { conn ->
+ repeat(SERIALIZATION_RETRY) {
+ try {
+ return@conn lambda(conn);
+ } catch (e: SQLException) {
+ if (e.sqlState != PSQLState.SERIALIZATION_FAILURE.state)
+ throw e
+ }
+ }
+ try {
+ return@conn lambda(conn)
+ } catch(e: SQLException) {
+ logger.warn("Serialization failure after $SERIALIZATION_RETRY
retry")
+ throw e
+ }
+ }
+
+ override fun close() {
+ pool.close()
+ }
+}
+
+fun ResultSet.getAmount(name: String, currency: String): TalerAmount{
+ return TalerAmount(
+ getLong("${name}_val"),
+ getInt("${name}_frac"),
+ currency
+ )
}
\ No newline at end of file
diff --git a/util/src/main/kotlin/Encoding.kt
b/common/src/main/kotlin/Encoding.kt
similarity index 99%
rename from util/src/main/kotlin/Encoding.kt
rename to common/src/main/kotlin/Encoding.kt
index dc76ffeb..cef7b0c0 100644
--- a/util/src/main/kotlin/Encoding.kt
+++ b/common/src/main/kotlin/Encoding.kt
@@ -17,7 +17,7 @@
* <http://www.gnu.org/licenses/>
*/
-package net.taler.wallet.crypto
+package tech.libeufin.common
import java.io.ByteArrayOutputStream
diff --git a/util/src/main/kotlin/HTTP.kt b/common/src/main/kotlin/HTTP.kt
similarity index 98%
rename from util/src/main/kotlin/HTTP.kt
rename to common/src/main/kotlin/HTTP.kt
index 5b194283..3ba10dcf 100644
--- a/util/src/main/kotlin/HTTP.kt
+++ b/common/src/main/kotlin/HTTP.kt
@@ -17,7 +17,7 @@
* <http://www.gnu.org/licenses/>
*/
-package tech.libeufin.util
+package tech.libeufin.common
import io.ktor.http.*
import io.ktor.server.application.*
diff --git a/common/src/main/kotlin/TalerCommon.kt
b/common/src/main/kotlin/TalerCommon.kt
new file mode 100644
index 00000000..76c8d801
--- /dev/null
+++ b/common/src/main/kotlin/TalerCommon.kt
@@ -0,0 +1,201 @@
+/*
+ * This file is part of LibEuFin.
+ * Copyright (C) 2024 Taler Systems S.A.
+ *
+ * LibEuFin is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3, or
+ * (at your option) any later version.
+ *
+ * LibEuFin 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 LibEuFin; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>
+ */
+
+package tech.libeufin.common
+
+import kotlinx.serialization.*
+import kotlinx.serialization.descriptors.*
+import kotlinx.serialization.encoding.*
+import kotlinx.serialization.json.*
+import io.ktor.http.*
+import java.net.URI
+
+sealed class CommonError(msg: String): Exception(msg) {
+ class AmountFormat(msg: String): CommonError(msg)
+ class AmountNumberTooBig(msg: String): CommonError(msg)
+ class IbanPayto(msg: String): CommonError(msg)
+}
+
+@Serializable(with = TalerAmount.Serializer::class)
+class TalerAmount {
+ val value: Long
+ val frac: Int
+ val currency: String
+
+ constructor(value: Long, frac: Int, currency: String) {
+ this.value = value
+ this.frac = frac
+ this.currency = currency
+ }
+ constructor(encoded: String) {
+ val match = PATTERN.matchEntire(encoded) ?:
+ throw CommonError.AmountFormat("Invalid amount format");
+ val (currency, value, frac) = match.destructured
+ this.currency = currency
+ this.value = value.toLongOrNull() ?:
+ throw CommonError.AmountFormat("Invalid value")
+ if (this.value > MAX_VALUE)
+ throw CommonError.AmountNumberTooBig("Value specified in amount is
too large")
+ this.frac = if (frac.isEmpty()) {
+ 0
+ } else {
+ var tmp = frac.toIntOrNull() ?:
+ throw CommonError.AmountFormat("Invalid fractional value")
+ if (tmp > FRACTION_BASE)
+ throw CommonError.AmountFormat("Fractional calue specified in
amount is too large")
+ repeat(8 - frac.length) {
+ tmp *= 10
+ }
+ tmp
+ }
+ }
+
+ override fun equals(other: Any?): Boolean {
+ return other is TalerAmount &&
+ other.value == this.value &&
+ other.frac == this.frac &&
+ other.currency == this.currency
+ }
+
+ override fun toString(): String {
+ if (frac == 0) {
+ return "$currency:$value"
+ } else {
+ return "$currency:$value.${frac.toString().padStart(8, '0')}"
+ .dropLastWhile { it == '0' } // Trim useless fractional
trailing 0
+ }
+ }
+
+ internal object Serializer : KSerializer<TalerAmount> {
+ override val descriptor: SerialDescriptor =
+ PrimitiveSerialDescriptor("TalerAmount", PrimitiveKind.STRING)
+
+ override fun serialize(encoder: Encoder, value: TalerAmount) {
+ encoder.encodeString(value.toString())
+ }
+
+ override fun deserialize(decoder: Decoder): TalerAmount {
+ return TalerAmount(decoder.decodeString())
+ }
+ }
+
+ companion object {
+ const val FRACTION_BASE = 100000000
+ const val MAX_VALUE = 4503599627370496L; // 2^52
+ private val PATTERN =
Regex("([A-Z]{1,11}):([0-9]+)(?:\\.([0-9]{1,8}))?");
+ }
+}
+
+
+sealed class PaytoUri {
+ abstract val amount: TalerAmount?
+ abstract val message: String?
+ abstract val receiverName: String?
+}
+
+// TODO x-taler-bank Payto
+
+@Serializable(with = IbanPayto.Serializer::class)
+class IbanPayto: PaytoUri {
+ val parsed: URI
+ val canonical: String
+ val iban: String
+ override val amount: TalerAmount?
+ override val message: String?
+ override val receiverName: String?
+
+ constructor(raw: String) {
+ println(raw)
+ try {
+ parsed = URI(raw)
+ } catch (e: Exception) {
+ throw CommonError.IbanPayto("expecteda valid URI")
+ }
+
+ if (parsed.scheme != "payto") throw CommonError.IbanPayto("expect a
payto URI")
+ if (parsed.host != "iban") throw CommonError.IbanPayto("expect a IBAN
payto URI")
+
+ val splitPath = parsed.path.split("/").filter { it.isNotEmpty() }
+ val rawIban = when (splitPath.size) {
+ 1 -> splitPath[0]
+ 2 -> splitPath[1]
+ else -> throw CommonError.IbanPayto("too many path segments")
+ }
+ iban = rawIban.uppercase().replace(SEPARATOR, "")
+ checkIban(iban)
+ canonical = "payto://iban/$iban"
+
+ val params = (parsed.query ?: "").parseUrlEncodedParameters();
+ amount = params["amount"]?.run { TalerAmount(this) }
+ message = params["message"]
+ receiverName = params["receiver-name"]
+ }
+
+ /** Full IBAN payto with receiver-name parameter if present */
+ fun maybeFull(): FullIbanPayto? {
+ return FullIbanPayto(this, receiverName ?: return null)
+ }
+
+ /** Full IBAN payto with receiver-name parameter if present, fail if
absent */
+ fun requireFull(): FullIbanPayto {
+ return maybeFull() ?: throw Exception("Missing receiver-name")
+ }
+
+ /** Full IBAN payto with receiver-name parameter set to [defaultName] if
absent */
+ fun full(defaultName: String): FullIbanPayto {
+ return FullIbanPayto(this, receiverName ?: defaultName)
+ }
+
+ override fun toString(): String = canonical
+
+ internal object Serializer : KSerializer<IbanPayto> {
+ override val descriptor: SerialDescriptor =
+ PrimitiveSerialDescriptor("IbanPayto", PrimitiveKind.STRING)
+
+ override fun serialize(encoder: Encoder, value: IbanPayto) {
+ encoder.encodeString(value.parsed.toString())
+ }
+
+ override fun deserialize(decoder: Decoder): IbanPayto {
+ return IbanPayto(decoder.decodeString())
+ }
+ }
+
+ companion object {
+ private val SEPARATOR = Regex("[\\ \\-]");
+
+ fun checkIban(iban: String) {
+ val builder = StringBuilder(iban.length + iban.asSequence().map {
if (it.isDigit()) 1 else 2 }.sum())
+ (iban.subSequence(4, iban.length).asSequence() +
iban.subSequence(0, 4).asSequence()).forEach {
+ if (it.isDigit()) {
+ builder.append(it)
+ } else {
+ builder.append((it.code - 'A'.code) + 10)
+ }
+ }
+ val str = builder.toString()
+ val mod = str.toBigInteger().mod(97.toBigInteger()).toInt();
+ if (mod != 1) throw CommonError.IbanPayto("Iban malformed, modulo
is $mod expected 1")
+ }
+ }
+}
+
+class FullIbanPayto(val payto: IbanPayto, val receiverName: String) {
+ val full = payto.canonical + "?receiver-name=" +
receiverName.encodeURLParameter()
+}
\ No newline at end of file
diff --git a/util/src/main/kotlin/TalerConfig.kt
b/common/src/main/kotlin/TalerConfig.kt
similarity index 99%
rename from util/src/main/kotlin/TalerConfig.kt
rename to common/src/main/kotlin/TalerConfig.kt
index b9435d19..a45b33e8 100644
--- a/util/src/main/kotlin/TalerConfig.kt
+++ b/common/src/main/kotlin/TalerConfig.kt
@@ -17,6 +17,8 @@
* <http://www.gnu.org/licenses/>
*/
+package tech.libeufin.common
+
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.io.File
diff --git a/util/src/main/kotlin/TalerErrorCode.kt
b/common/src/main/kotlin/TalerErrorCode.kt
similarity index 99%
rename from util/src/main/kotlin/TalerErrorCode.kt
rename to common/src/main/kotlin/TalerErrorCode.kt
index ff1e6af8..e37f2eb5 100644
--- a/util/src/main/kotlin/TalerErrorCode.kt
+++ b/common/src/main/kotlin/TalerErrorCode.kt
@@ -20,7 +20,7 @@
Note: the LGPL does not apply to all components of GNU Taler,
but it does apply to this file.
*/
-package net.taler.common.errorcodes
+package tech.libeufin.common
enum class TalerErrorCode(val code: Int) {
diff --git a/util/src/main/kotlin/iban.kt b/common/src/main/kotlin/iban.kt
similarity index 98%
rename from util/src/main/kotlin/iban.kt
rename to common/src/main/kotlin/iban.kt
index 00c635ac..499ad8e7 100644
--- a/util/src/main/kotlin/iban.kt
+++ b/common/src/main/kotlin/iban.kt
@@ -17,7 +17,7 @@
* <http://www.gnu.org/licenses/>
*/
-package tech.libeufin.util
+package tech.libeufin.common
fun getIban(): String {
val ccNoCheck = "131400" // DE00
diff --git a/util/src/main/kotlin/strings.kt b/common/src/main/kotlin/strings.kt
similarity index 97%
rename from util/src/main/kotlin/strings.kt
rename to common/src/main/kotlin/strings.kt
index 43639cd5..7dc10d1e 100644
--- a/util/src/main/kotlin/strings.kt
+++ b/common/src/main/kotlin/strings.kt
@@ -17,9 +17,8 @@
* <http://www.gnu.org/licenses/>
*/
-package tech.libeufin.util
+package tech.libeufin.common
-import net.taler.wallet.crypto.Base32Crockford
import java.math.BigInteger
import java.util.*
diff --git a/util/src/main/kotlin/time.kt b/common/src/main/kotlin/time.kt
similarity index 99%
rename from util/src/main/kotlin/time.kt
rename to common/src/main/kotlin/time.kt
index d1ed8b21..fee05d01 100644
--- a/util/src/main/kotlin/time.kt
+++ b/common/src/main/kotlin/time.kt
@@ -17,7 +17,7 @@
* <http://www.gnu.org/licenses/>
*/
-package tech.libeufin.util
+package tech.libeufin.common
import org.slf4j.Logger
import org.slf4j.LoggerFactory
diff --git a/util/src/main/resources/xsd/camt.052.001.02.xsd
b/common/src/main/resources/xsd/camt.052.001.02.xsd
similarity index 100%
copy from util/src/main/resources/xsd/camt.052.001.02.xsd
copy to common/src/main/resources/xsd/camt.052.001.02.xsd
diff --git a/util/src/main/resources/xsd/camt.053.001.02.xsd
b/common/src/main/resources/xsd/camt.053.001.02.xsd
similarity index 100%
copy from util/src/main/resources/xsd/camt.053.001.02.xsd
copy to common/src/main/resources/xsd/camt.053.001.02.xsd
diff --git a/util/src/main/resources/xsd/camt.054.001.02.xsd
b/common/src/main/resources/xsd/camt.054.001.02.xsd
similarity index 100%
copy from util/src/main/resources/xsd/camt.054.001.02.xsd
copy to common/src/main/resources/xsd/camt.054.001.02.xsd
diff --git a/util/src/main/resources/xsd/ebics_H004.xsd
b/common/src/main/resources/xsd/ebics_H004.xsd
similarity index 100%
copy from util/src/main/resources/xsd/ebics_H004.xsd
copy to common/src/main/resources/xsd/ebics_H004.xsd
diff --git a/util/src/main/resources/xsd/ebics_H005.xsd
b/common/src/main/resources/xsd/ebics_H005.xsd
similarity index 100%
copy from util/src/main/resources/xsd/ebics_H005.xsd
copy to common/src/main/resources/xsd/ebics_H005.xsd
diff --git a/util/src/main/resources/xsd/ebics_hev.xsd
b/common/src/main/resources/xsd/ebics_hev.xsd
similarity index 100%
copy from util/src/main/resources/xsd/ebics_hev.xsd
copy to common/src/main/resources/xsd/ebics_hev.xsd
diff --git a/util/src/main/resources/xsd/ebics_keymgmt_request_H004.xsd
b/common/src/main/resources/xsd/ebics_keymgmt_request_H004.xsd
similarity index 100%
copy from util/src/main/resources/xsd/ebics_keymgmt_request_H004.xsd
copy to common/src/main/resources/xsd/ebics_keymgmt_request_H004.xsd
diff --git a/util/src/main/resources/xsd/ebics_keymgmt_request_H005.xsd
b/common/src/main/resources/xsd/ebics_keymgmt_request_H005.xsd
similarity index 100%
copy from util/src/main/resources/xsd/ebics_keymgmt_request_H005.xsd
copy to common/src/main/resources/xsd/ebics_keymgmt_request_H005.xsd
diff --git a/util/src/main/resources/xsd/ebics_keymgmt_response_H004.xsd
b/common/src/main/resources/xsd/ebics_keymgmt_response_H004.xsd
similarity index 100%
copy from util/src/main/resources/xsd/ebics_keymgmt_response_H004.xsd
copy to common/src/main/resources/xsd/ebics_keymgmt_response_H004.xsd
diff --git a/util/src/main/resources/xsd/ebics_keymgmt_response_H005.xsd
b/common/src/main/resources/xsd/ebics_keymgmt_response_H005.xsd
similarity index 100%
copy from util/src/main/resources/xsd/ebics_keymgmt_response_H005.xsd
copy to common/src/main/resources/xsd/ebics_keymgmt_response_H005.xsd
diff --git a/util/src/main/resources/xsd/ebics_orders_H004.xsd
b/common/src/main/resources/xsd/ebics_orders_H004.xsd
similarity index 100%
copy from util/src/main/resources/xsd/ebics_orders_H004.xsd
copy to common/src/main/resources/xsd/ebics_orders_H004.xsd
diff --git a/util/src/main/resources/xsd/ebics_orders_H005.xsd
b/common/src/main/resources/xsd/ebics_orders_H005.xsd
similarity index 100%
copy from util/src/main/resources/xsd/ebics_orders_H005.xsd
copy to common/src/main/resources/xsd/ebics_orders_H005.xsd
diff --git a/util/src/main/resources/xsd/ebics_request_H004.xsd
b/common/src/main/resources/xsd/ebics_request_H004.xsd
similarity index 100%
copy from util/src/main/resources/xsd/ebics_request_H004.xsd
copy to common/src/main/resources/xsd/ebics_request_H004.xsd
diff --git a/util/src/main/resources/xsd/ebics_request_H005.xsd
b/common/src/main/resources/xsd/ebics_request_H005.xsd
similarity index 100%
copy from util/src/main/resources/xsd/ebics_request_H005.xsd
copy to common/src/main/resources/xsd/ebics_request_H005.xsd
diff --git a/util/src/main/resources/xsd/ebics_response_H004.xsd
b/common/src/main/resources/xsd/ebics_response_H004.xsd
similarity index 100%
copy from util/src/main/resources/xsd/ebics_response_H004.xsd
copy to common/src/main/resources/xsd/ebics_response_H004.xsd
diff --git a/util/src/main/resources/xsd/ebics_response_H005.xsd
b/common/src/main/resources/xsd/ebics_response_H005.xsd
similarity index 100%
copy from util/src/main/resources/xsd/ebics_response_H005.xsd
copy to common/src/main/resources/xsd/ebics_response_H005.xsd
diff --git a/util/src/main/resources/xsd/ebics_signature_S002.xsd
b/common/src/main/resources/xsd/ebics_signature_S002.xsd
similarity index 100%
copy from util/src/main/resources/xsd/ebics_signature_S002.xsd
copy to common/src/main/resources/xsd/ebics_signature_S002.xsd
diff --git a/util/src/main/resources/xsd/ebics_signatures.xsd
b/common/src/main/resources/xsd/ebics_signatures.xsd
similarity index 100%
copy from util/src/main/resources/xsd/ebics_signatures.xsd
copy to common/src/main/resources/xsd/ebics_signatures.xsd
diff --git a/util/src/main/resources/xsd/ebics_types_H004.xsd
b/common/src/main/resources/xsd/ebics_types_H004.xsd
similarity index 100%
copy from util/src/main/resources/xsd/ebics_types_H004.xsd
copy to common/src/main/resources/xsd/ebics_types_H004.xsd
diff --git a/util/src/main/resources/xsd/ebics_types_H005.xsd
b/common/src/main/resources/xsd/ebics_types_H005.xsd
similarity index 100%
copy from util/src/main/resources/xsd/ebics_types_H005.xsd
copy to common/src/main/resources/xsd/ebics_types_H005.xsd
diff --git a/util/src/main/resources/xsd/pain.001.001.03.ch.02.xsd
b/common/src/main/resources/xsd/pain.001.001.03.ch.02.xsd
similarity index 100%
copy from util/src/main/resources/xsd/pain.001.001.03.ch.02.xsd
copy to common/src/main/resources/xsd/pain.001.001.03.ch.02.xsd
diff --git a/util/src/main/resources/xsd/pain.001.001.03.xsd
b/common/src/main/resources/xsd/pain.001.001.03.xsd
similarity index 100%
copy from util/src/main/resources/xsd/pain.001.001.03.xsd
copy to common/src/main/resources/xsd/pain.001.001.03.xsd
diff --git a/util/src/main/resources/xsd/pain.001.001.09.ch.03.xsd
b/common/src/main/resources/xsd/pain.001.001.09.ch.03.xsd
similarity index 100%
copy from util/src/main/resources/xsd/pain.001.001.09.ch.03.xsd
copy to common/src/main/resources/xsd/pain.001.001.09.ch.03.xsd
diff --git a/util/src/main/resources/xsd/pain.002.001.13.xsd
b/common/src/main/resources/xsd/pain.002.001.13.xsd
similarity index 100%
copy from util/src/main/resources/xsd/pain.002.001.13.xsd
copy to common/src/main/resources/xsd/pain.002.001.13.xsd
diff --git a/util/src/main/resources/xsd/xmldsig-core-schema.xsd
b/common/src/main/resources/xsd/xmldsig-core-schema.xsd
similarity index 100%
copy from util/src/main/resources/xsd/xmldsig-core-schema.xsd
copy to common/src/main/resources/xsd/xmldsig-core-schema.xsd
diff --git a/common/src/test/kotlin/AmountTest.kt
b/common/src/test/kotlin/AmountTest.kt
new file mode 100644
index 00000000..ccd836aa
--- /dev/null
+++ b/common/src/test/kotlin/AmountTest.kt
@@ -0,0 +1,62 @@
+/*
+ * This file is part of LibEuFin.
+ * Copyright (C) 2024 Taler Systems S.A.
+
+ * LibEuFin is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3, or
+ * (at your option) any later version.
+
+ * LibEuFin 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 LibEuFin; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>
+ */
+
+import java.time.Instant
+import java.util.*
+import kotlin.test.*
+import org.junit.Test
+import tech.libeufin.common.*
+
+class AmountTest {
+ @Test
+ fun parse() {
+ assertEquals(TalerAmount("EUR:4"), TalerAmount(4L, 0, "EUR"))
+ assertEquals(TalerAmount("EUR:0.02"), TalerAmount(0L, 2000000, "EUR"))
+ assertEquals(TalerAmount("EUR:4.12"), TalerAmount(4L, 12000000, "EUR"))
+ assertEquals(TalerAmount("LOCAL:4444.1000"), TalerAmount(4444L,
10000000, "LOCAL"))
+ assertEquals(TalerAmount("EUR:${TalerAmount.MAX_VALUE}.99999999"),
TalerAmount(TalerAmount.MAX_VALUE, 99999999, "EUR"))
+
+ assertException("Invalid amount format") {TalerAmount("")}
+ assertException("Invalid amount format") {TalerAmount("EUR")}
+ assertException("Invalid amount format") {TalerAmount("eur:12")}
+ assertException("Invalid amount format") {TalerAmount(" EUR:12")}
+ assertException("Invalid amount format") {TalerAmount("EUR:1.")}
+ assertException("Invalid amount format") {TalerAmount("EUR:.1")}
+ assertException("Invalid amount format")
{TalerAmount("AZERTYUIOPQSD:12")}
+ assertException("Value specified in amount is too large")
{TalerAmount("EUR:${Long.MAX_VALUE}")}
+ assertException("Invalid amount format")
{TalerAmount("EUR:4.000000000")}
+ assertException("Invalid amount format") {TalerAmount("EUR:4.4a")}
+ }
+
+ @Test
+ fun parseRoundTrip() {
+ for (amount in listOf("EUR:4", "EUR:0.02", "EUR:4.12")) {
+ assertEquals(amount, TalerAmount(amount).toString())
+ }
+ }
+
+ fun assertException(msg: String, lambda: () -> Unit) {
+ try {
+ lambda()
+ throw Exception("Expected failure")
+ } catch (e: Exception) {
+ assert(e.message!!.startsWith(msg)) { "${e.message}" }
+ }
+ }
+}
\ No newline at end of file
diff --git a/util/src/test/kotlin/CryptoUtilTest.kt
b/common/src/test/kotlin/CryptoUtilTest.kt
similarity index 99%
rename from util/src/test/kotlin/CryptoUtilTest.kt
rename to common/src/test/kotlin/CryptoUtilTest.kt
index d29a9fa9..09f17fca 100644
--- a/util/src/test/kotlin/CryptoUtilTest.kt
+++ b/common/src/test/kotlin/CryptoUtilTest.kt
@@ -17,10 +17,9 @@
* <http://www.gnu.org/licenses/>
*/
-import net.taler.wallet.crypto.Base32Crockford
import org.junit.Ignore
import org.junit.Test
-import tech.libeufin.util.*
+import tech.libeufin.common.*
import java.io.File
import java.security.KeyPairGenerator
import java.security.interfaces.RSAPrivateCrtKey
diff --git a/common/src/test/kotlin/PaytoTest.kt
b/common/src/test/kotlin/PaytoTest.kt
new file mode 100644
index 00000000..e1a6b976
--- /dev/null
+++ b/common/src/test/kotlin/PaytoTest.kt
@@ -0,0 +1,80 @@
+/*
+ * This file is part of LibEuFin.
+ * Copyright (C) 2024 Taler Systems S.A.
+
+ * LibEuFin is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3, or
+ * (at your option) any later version.
+
+ * LibEuFin 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 LibEuFin; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>
+ */
+
+import org.junit.Test
+import tech.libeufin.common.*
+import kotlin.test.*
+
+class PaytoTest {
+ @Test
+ fun wrongCases() {
+ assertFailsWith<CommonError.IbanPayto> {
IbanPayto("http://iban/BIC123/IBAN123?receiver-name=The%20Name") }
+ assertFailsWith<CommonError.IbanPayto> {
IbanPayto("payto:iban/BIC123/IBAN123?receiver-name=The%20Name&address=house") }
+ assertFailsWith<CommonError.IbanPayto> {
IbanPayto("payto://wrong/BIC123/IBAN123?sender-name=Foo&receiver-name=Foo") }
+ }
+
+ @Test
+ fun parsePaytoTest() {
+ val withBic =
IbanPayto("payto://iban/BIC123/CH9300762011623852957?receiver-name=The%20Name")
+ assertEquals(withBic.iban, "CH9300762011623852957")
+ assertEquals(withBic.receiverName, "The Name")
+ val complete =
IbanPayto("payto://iban/BIC123/CH9300762011623852957?sender-name=The%20Name&amount=EUR:1&message=donation")
+ assertEquals(withBic.iban, "CH9300762011623852957")
+ assertEquals(withBic.receiverName, "The Name")
+ assertEquals(complete.message, "donation")
+ assertEquals(complete.amount.toString(), "EUR:1")
+ val withoutOptionals = IbanPayto("payto://iban/CH9300762011623852957")
+ assertNull(withoutOptionals.message)
+ assertNull(withoutOptionals.receiverName)
+ assertNull(withoutOptionals.amount)
+ }
+
+ @Test
+ fun normalization() {
+ val canonical = "payto://iban/CH9300762011623852957"
+ val inputs = listOf(
+ "payto://iban/BIC/CH9300762011623852957?receiver-name=NotGiven",
+ "payto://iban/CH9300762011623852957?receiver-name=Grothoff%20Hans",
+ "payto://iban/ch%209300-7620-1162-3852-957",
+ )
+ val names = listOf(
+ "NotGiven", "Grothoff Hans", null
+ )
+ val full = listOf(
+ "payto://iban/CH9300762011623852957?receiver-name=NotGiven",
+ "payto://iban/CH9300762011623852957?receiver-name=Grothoff%20Hans",
+ canonical
+ )
+ for ((i, input) in inputs.withIndex()) {
+ val payto = IbanPayto(input)
+ assertEquals(canonical, payto.canonical)
+ assertEquals(full[i], payto.maybeFull()?.full ?: payto.canonical)
+ assertEquals(names[i], payto.receiverName)
+ }
+
+ assertEquals(
+ "payto://iban/CH9300762011623852957?receiver-name=Grothoff%20Hans",
+
IbanPayto("payto://iban/CH9300762011623852957?receiver-name=Grothoff%20Hans").full("Santa
Claus").full
+ )
+ assertEquals(
+ "payto://iban/CH9300762011623852957?receiver-name=Santa%20Claus",
+ IbanPayto("payto://iban/CH9300762011623852957").full("Santa
Claus").full
+ )
+ }
+}
\ No newline at end of file
diff --git a/util/src/test/kotlin/TalerConfigTest.kt
b/common/src/test/kotlin/TalerConfigTest.kt
similarity index 98%
rename from util/src/test/kotlin/TalerConfigTest.kt
rename to common/src/test/kotlin/TalerConfigTest.kt
index 7e51076d..024ca460 100644
--- a/util/src/test/kotlin/TalerConfigTest.kt
+++ b/common/src/test/kotlin/TalerConfigTest.kt
@@ -19,6 +19,7 @@
import org.junit.Test
import kotlin.test.assertEquals
+import tech.libeufin.common.*
class TalerConfigTest {
diff --git a/util/src/test/kotlin/TimeTest.kt
b/common/src/test/kotlin/TimeTest.kt
similarity index 95%
rename from util/src/test/kotlin/TimeTest.kt
rename to common/src/test/kotlin/TimeTest.kt
index 284e46d4..090843af 100644
--- a/util/src/test/kotlin/TimeTest.kt
+++ b/common/src/test/kotlin/TimeTest.kt
@@ -18,8 +18,8 @@
*/
import org.junit.Test
-import tech.libeufin.util.maxTimestamp
-import tech.libeufin.util.minTimestamp
+import tech.libeufin.common.maxTimestamp
+import tech.libeufin.common.minTimestamp
import java.time.Instant
import java.time.temporal.ChronoUnit
import kotlin.test.assertEquals
diff --git a/util/src/test/resources/ebics_hev.xml
b/common/src/test/resources/ebics_hev.xml
similarity index 100%
copy from util/src/test/resources/ebics_hev.xml
copy to common/src/test/resources/ebics_hev.xml
diff --git a/util/src/test/resources/ebics_ini_inner_key.xml
b/common/src/test/resources/ebics_ini_inner_key.xml
similarity index 100%
copy from util/src/test/resources/ebics_ini_inner_key.xml
copy to common/src/test/resources/ebics_ini_inner_key.xml
diff --git a/util/src/test/resources/ebics_ini_request_sample.xml
b/common/src/test/resources/ebics_ini_request_sample.xml
similarity index 100%
copy from util/src/test/resources/ebics_ini_request_sample.xml
copy to common/src/test/resources/ebics_ini_request_sample.xml
diff --git a/util/src/test/resources/hia_request.xml
b/common/src/test/resources/hia_request.xml
similarity index 100%
copy from util/src/test/resources/hia_request.xml
copy to common/src/test/resources/hia_request.xml
diff --git a/util/src/test/resources/hia_request_order_data.xml
b/common/src/test/resources/hia_request_order_data.xml
similarity index 100%
copy from util/src/test/resources/hia_request_order_data.xml
copy to common/src/test/resources/hia_request_order_data.xml
diff --git a/util/src/test/resources/hpb_request.xml
b/common/src/test/resources/hpb_request.xml
similarity index 100%
copy from util/src/test/resources/hpb_request.xml
copy to common/src/test/resources/hpb_request.xml
diff --git a/util/src/test/resources/signature1/doc.xml
b/common/src/test/resources/signature1/doc.xml
similarity index 100%
copy from util/src/test/resources/signature1/doc.xml
copy to common/src/test/resources/signature1/doc.xml
diff --git a/util/src/test/resources/signature1/public_key.txt
b/common/src/test/resources/signature1/public_key.txt
similarity index 100%
copy from util/src/test/resources/signature1/public_key.txt
copy to common/src/test/resources/signature1/public_key.txt
diff --git a/util/build.gradle b/ebics/build.gradle
similarity index 61%
rename from util/build.gradle
rename to ebics/build.gradle
index 0bd9b551..dbd9b36a 100644
--- a/util/build.gradle
+++ b/ebics/build.gradle
@@ -1,5 +1,3 @@
-import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
-
plugins {
id("java")
id("kotlin")
@@ -18,18 +16,14 @@ compileTestKotlin.kotlinOptions.jvmTarget = "17"
sourceSets.main.java.srcDirs = ["src/main/kotlin"]
dependencies {
+ implementation(project(":common"))
+
implementation("ch.qos.logback:logback-classic:1.4.5")
// XML Stuff
implementation("javax.xml.bind:jaxb-api:2.3.1")
implementation("org.glassfish.jaxb:jaxb-runtime:2.3.1")
implementation("org.apache.santuario:xmlsec:2.2.2")
- // Crypto
- implementation("org.bouncycastle:bcprov-jdk15on:1.69")
- // Database helper
- implementation("org.postgresql:postgresql:$postgres_version")
- implementation("io.ktor:ktor-serialization-kotlinx-json:$ktor_version")
- implementation("io.ktor:ktor-server-test-host:$ktor_version")
+ implementation("io.ktor:ktor-http:$ktor_version")
implementation("org.jetbrains.kotlin:kotlin-test:$kotlin_version")
- implementation("com.github.ajalt.clikt:clikt:$clikt_version")
}
\ No newline at end of file
diff --git a/util/import.py b/ebics/import.py
similarity index 98%
rename from util/import.py
rename to ebics/import.py
index e1389052..f9e90e10 100644
--- a/util/import.py
+++ b/ebics/import.py
@@ -56,7 +56,7 @@ kt = f"""/*
// THIS FILE IS GENERATED, DO NOT EDIT
-package tech.libeufin.util
+package tech.libeufin.ebics
{extractCodeSet("ExternalStatusReason1Code", "ExternalStatusReasonCode")}
diff --git a/util/src/main/kotlin/Ebics.kt b/ebics/src/main/kotlin/Ebics.kt
similarity index 96%
rename from util/src/main/kotlin/Ebics.kt
rename to ebics/src/main/kotlin/Ebics.kt
index b0b45197..558ceaee 100644
--- a/util/src/main/kotlin/Ebics.kt
+++ b/ebics/src/main/kotlin/Ebics.kt
@@ -22,12 +22,13 @@
* used to implement both an EBICS server and EBICS client.
*/
-package tech.libeufin.util
+package tech.libeufin.ebics
+import tech.libeufin.common.CryptoUtil
import io.ktor.http.HttpStatusCode
-import tech.libeufin.util.ebics_h004.*
-import tech.libeufin.util.ebics_h005.Ebics3Response
-import tech.libeufin.util.ebics_s001.UserSignatureData
+import tech.libeufin.ebics.ebics_h004.*
+import tech.libeufin.ebics.ebics_h005.Ebics3Response
+import tech.libeufin.ebics.ebics_s001.UserSignatureData
import java.security.SecureRandom
import java.security.interfaces.RSAPrivateCrtKey
import java.security.interfaces.RSAPublicKey
@@ -173,14 +174,14 @@ fun signOrderEbics3(
signKey: RSAPrivateCrtKey,
partnerId: String,
userId: String
-): tech.libeufin.util.ebics_s002.UserSignatureDataEbics3 {
+): tech.libeufin.ebics.ebics_s002.UserSignatureDataEbics3 {
val ES_signature = CryptoUtil.signEbicsA006(
CryptoUtil.digestEbicsOrderA006(orderBlob),
signKey
)
- val userSignatureData =
tech.libeufin.util.ebics_s002.UserSignatureDataEbics3().apply {
+ val userSignatureData =
tech.libeufin.ebics.ebics_s002.UserSignatureDataEbics3().apply {
orderSignatureList = listOf(
-
tech.libeufin.util.ebics_s002.UserSignatureDataEbics3.OrderSignatureData().apply
{
+
tech.libeufin.ebics.ebics_s002.UserSignatureDataEbics3.OrderSignatureData().apply
{
signatureVersion = "A006"
signatureValue = ES_signature
partnerID = partnerId
diff --git a/util/src/main/kotlin/EbicsCodeSets.kt
b/ebics/src/main/kotlin/EbicsCodeSets.kt
similarity index 99%
rename from util/src/main/kotlin/EbicsCodeSets.kt
rename to ebics/src/main/kotlin/EbicsCodeSets.kt
index 4e0f95da..5f8b2b08 100644
--- a/util/src/main/kotlin/EbicsCodeSets.kt
+++ b/ebics/src/main/kotlin/EbicsCodeSets.kt
@@ -19,7 +19,7 @@
// THIS FILE IS GENERATED, DO NOT EDIT
-package tech.libeufin.util
+package tech.libeufin.ebics
enum class ExternalStatusReasonCode(val isoCode: String, val description:
String) {
AB01("AbortedClearingTimeout", "Clearing process aborted due to
timeout."),
diff --git a/util/src/main/kotlin/EbicsOrderUtil.kt
b/ebics/src/main/kotlin/EbicsOrderUtil.kt
similarity index 97%
rename from util/src/main/kotlin/EbicsOrderUtil.kt
rename to ebics/src/main/kotlin/EbicsOrderUtil.kt
index a7090295..ef7ed1f7 100644
--- a/util/src/main/kotlin/EbicsOrderUtil.kt
+++ b/ebics/src/main/kotlin/EbicsOrderUtil.kt
@@ -17,7 +17,7 @@
* <http://www.gnu.org/licenses/>
*/
-package tech.libeufin.util
+package tech.libeufin.ebics
import java.lang.IllegalArgumentException
import java.security.SecureRandom
@@ -50,6 +50,7 @@ object EbicsOrderUtil {
}
}
+ @kotlin.ExperimentalStdlibApi
fun generateTransactionId(): String {
val rng = SecureRandom()
val res = ByteArray(16)
diff --git a/util/src/main/kotlin/XMLUtil.kt b/ebics/src/main/kotlin/XMLUtil.kt
similarity index 99%
rename from util/src/main/kotlin/XMLUtil.kt
rename to ebics/src/main/kotlin/XMLUtil.kt
index c0fe0638..c294b7ef 100644
--- a/util/src/main/kotlin/XMLUtil.kt
+++ b/ebics/src/main/kotlin/XMLUtil.kt
@@ -17,7 +17,7 @@
* <http://www.gnu.org/licenses/>
*/
-package tech.libeufin.util
+package tech.libeufin.ebics
import com.sun.xml.bind.marshaller.NamespacePrefixMapper
import io.ktor.http.*
@@ -32,7 +32,7 @@ import org.xml.sax.ErrorHandler
import org.xml.sax.InputSource
import org.xml.sax.SAXException
import org.xml.sax.SAXParseException
-import tech.libeufin.util.ebics_h004.EbicsResponse
+import tech.libeufin.ebics.ebics_h004.EbicsResponse
import java.io.*
import java.security.PrivateKey
import java.security.PublicKey
diff --git a/util/src/main/kotlin/XmlCombinators.kt
b/ebics/src/main/kotlin/XmlCombinators.kt
similarity index 99%
rename from util/src/main/kotlin/XmlCombinators.kt
rename to ebics/src/main/kotlin/XmlCombinators.kt
index 3d154e96..d9cc77b2 100644
--- a/util/src/main/kotlin/XmlCombinators.kt
+++ b/ebics/src/main/kotlin/XmlCombinators.kt
@@ -17,7 +17,7 @@
* <http://www.gnu.org/licenses/>
*/
-package tech.libeufin.util
+package tech.libeufin.ebics
import com.sun.xml.txw2.output.IndentingXMLStreamWriter
import org.w3c.dom.Document
diff --git a/util/src/main/kotlin/ebics_h004/EbicsKeyManagementResponse.kt
b/ebics/src/main/kotlin/ebics_h004/EbicsKeyManagementResponse.kt
similarity index 98%
rename from util/src/main/kotlin/ebics_h004/EbicsKeyManagementResponse.kt
rename to ebics/src/main/kotlin/ebics_h004/EbicsKeyManagementResponse.kt
index 6db6eab4..74d99c94 100644
--- a/util/src/main/kotlin/ebics_h004/EbicsKeyManagementResponse.kt
+++ b/ebics/src/main/kotlin/ebics_h004/EbicsKeyManagementResponse.kt
@@ -1,4 +1,4 @@
-package tech.libeufin.util.ebics_h004
+package tech.libeufin.ebics.ebics_h004
import javax.xml.bind.annotation.*
import javax.xml.bind.annotation.adapters.CollapsedStringAdapter
diff --git a/util/src/main/kotlin/ebics_h004/EbicsNpkdRequest.kt
b/ebics/src/main/kotlin/ebics_h004/EbicsNpkdRequest.kt
similarity index 99%
rename from util/src/main/kotlin/ebics_h004/EbicsNpkdRequest.kt
rename to ebics/src/main/kotlin/ebics_h004/EbicsNpkdRequest.kt
index 34bfc8b2..2330ca0b 100644
--- a/util/src/main/kotlin/ebics_h004/EbicsNpkdRequest.kt
+++ b/ebics/src/main/kotlin/ebics_h004/EbicsNpkdRequest.kt
@@ -1,4 +1,4 @@
-package tech.libeufin.util.ebics_h004
+package tech.libeufin.ebics.ebics_h004
import org.apache.xml.security.binding.xmldsig.SignatureType
import javax.xml.bind.annotation.*
diff --git a/util/src/main/kotlin/ebics_h004/EbicsRequest.kt
b/ebics/src/main/kotlin/ebics_h004/EbicsRequest.kt
similarity index 99%
rename from util/src/main/kotlin/ebics_h004/EbicsRequest.kt
rename to ebics/src/main/kotlin/ebics_h004/EbicsRequest.kt
index e221a502..263fb71a 100644
--- a/util/src/main/kotlin/ebics_h004/EbicsRequest.kt
+++ b/ebics/src/main/kotlin/ebics_h004/EbicsRequest.kt
@@ -1,7 +1,7 @@
-package tech.libeufin.util.ebics_h004
+package tech.libeufin.ebics.ebics_h004
import org.apache.xml.security.binding.xmldsig.SignatureType
-import tech.libeufin.util.CryptoUtil
+import tech.libeufin.common.CryptoUtil
import java.math.BigInteger
import java.security.interfaces.RSAPublicKey
import java.util.*
diff --git a/util/src/main/kotlin/ebics_h004/EbicsResponse.kt
b/ebics/src/main/kotlin/ebics_h004/EbicsResponse.kt
similarity index 99%
rename from util/src/main/kotlin/ebics_h004/EbicsResponse.kt
rename to ebics/src/main/kotlin/ebics_h004/EbicsResponse.kt
index d0a88ae5..57841e28 100644
--- a/util/src/main/kotlin/ebics_h004/EbicsResponse.kt
+++ b/ebics/src/main/kotlin/ebics_h004/EbicsResponse.kt
@@ -1,9 +1,9 @@
-package tech.libeufin.util.ebics_h004
+package tech.libeufin.ebics.ebics_h004
import org.apache.xml.security.binding.xmldsig.SignatureType
import org.apache.xml.security.binding.xmldsig.SignedInfoType
-import tech.libeufin.util.CryptoUtil
-import tech.libeufin.util.XMLUtil
+import tech.libeufin.common.CryptoUtil
+import tech.libeufin.ebics.XMLUtil
import java.math.BigInteger
import javax.xml.bind.annotation.*
import javax.xml.bind.annotation.adapters.CollapsedStringAdapter
diff --git a/util/src/main/kotlin/ebics_h004/EbicsTypes.kt
b/ebics/src/main/kotlin/ebics_h004/EbicsTypes.kt
similarity index 99%
rename from util/src/main/kotlin/ebics_h004/EbicsTypes.kt
rename to ebics/src/main/kotlin/ebics_h004/EbicsTypes.kt
index 1713684a..7451607f 100644
--- a/util/src/main/kotlin/ebics_h004/EbicsTypes.kt
+++ b/ebics/src/main/kotlin/ebics_h004/EbicsTypes.kt
@@ -17,7 +17,7 @@
* <http://www.gnu.org/licenses/>
*/
-package tech.libeufin.util.ebics_h004
+package tech.libeufin.ebics.ebics_h004
import org.apache.xml.security.binding.xmldsig.RSAKeyValueType
import org.w3c.dom.Element
diff --git a/util/src/main/kotlin/ebics_h004/EbicsUnsecuredRequest.kt
b/ebics/src/main/kotlin/ebics_h004/EbicsUnsecuredRequest.kt
similarity index 98%
rename from util/src/main/kotlin/ebics_h004/EbicsUnsecuredRequest.kt
rename to ebics/src/main/kotlin/ebics_h004/EbicsUnsecuredRequest.kt
index efef020c..fbb60acd 100644
--- a/util/src/main/kotlin/ebics_h004/EbicsUnsecuredRequest.kt
+++ b/ebics/src/main/kotlin/ebics_h004/EbicsUnsecuredRequest.kt
@@ -1,8 +1,8 @@
-package tech.libeufin.util.ebics_h004
+package tech.libeufin.ebics.ebics_h004
import org.apache.xml.security.binding.xmldsig.RSAKeyValueType
-import tech.libeufin.util.EbicsOrderUtil
-import tech.libeufin.util.ebics_s001.SignatureTypes
+import tech.libeufin.ebics.EbicsOrderUtil
+import tech.libeufin.ebics.ebics_s001.SignatureTypes
import java.security.interfaces.RSAPrivateCrtKey
import javax.xml.bind.annotation.*
import javax.xml.bind.annotation.adapters.CollapsedStringAdapter
diff --git a/util/src/main/kotlin/ebics_h004/HIARequestOrderData.kt
b/ebics/src/main/kotlin/ebics_h004/HIARequestOrderData.kt
similarity index 96%
rename from util/src/main/kotlin/ebics_h004/HIARequestOrderData.kt
rename to ebics/src/main/kotlin/ebics_h004/HIARequestOrderData.kt
index 95bd2b18..6268099b 100644
--- a/util/src/main/kotlin/ebics_h004/HIARequestOrderData.kt
+++ b/ebics/src/main/kotlin/ebics_h004/HIARequestOrderData.kt
@@ -1,4 +1,4 @@
-package tech.libeufin.util.ebics_h004
+package tech.libeufin.ebics.ebics_h004
import javax.xml.bind.annotation.*
import javax.xml.bind.annotation.adapters.CollapsedStringAdapter
diff --git a/util/src/main/kotlin/ebics_h004/HKDResponseOrderData.kt
b/ebics/src/main/kotlin/ebics_h004/HKDResponseOrderData.kt
similarity index 92%
rename from util/src/main/kotlin/ebics_h004/HKDResponseOrderData.kt
rename to ebics/src/main/kotlin/ebics_h004/HKDResponseOrderData.kt
index 999fe94c..c3e4b706 100644
--- a/util/src/main/kotlin/ebics_h004/HKDResponseOrderData.kt
+++ b/ebics/src/main/kotlin/ebics_h004/HKDResponseOrderData.kt
@@ -1,4 +1,4 @@
-package tech.libeufin.util.ebics_h004
+package tech.libeufin.ebics.ebics_h004
import java.security.Permission
import javax.xml.bind.annotation.*
diff --git a/util/src/main/kotlin/ebics_h004/HPBResponseOrderData.kt
b/ebics/src/main/kotlin/ebics_h004/HPBResponseOrderData.kt
similarity index 95%
rename from util/src/main/kotlin/ebics_h004/HPBResponseOrderData.kt
rename to ebics/src/main/kotlin/ebics_h004/HPBResponseOrderData.kt
index 9c380478..65b4098b 100644
--- a/util/src/main/kotlin/ebics_h004/HPBResponseOrderData.kt
+++ b/ebics/src/main/kotlin/ebics_h004/HPBResponseOrderData.kt
@@ -1,4 +1,4 @@
-package tech.libeufin.util.ebics_h004
+package tech.libeufin.ebics.ebics_h004
import javax.xml.bind.annotation.*
import javax.xml.bind.annotation.adapters.CollapsedStringAdapter
diff --git a/util/src/main/kotlin/ebics_h004/HTDResponseOrderData.kt
b/ebics/src/main/kotlin/ebics_h004/HTDResponseOrderData.kt
similarity index 91%
rename from util/src/main/kotlin/ebics_h004/HTDResponseOrderData.kt
rename to ebics/src/main/kotlin/ebics_h004/HTDResponseOrderData.kt
index 4162379b..46954355 100644
--- a/util/src/main/kotlin/ebics_h004/HTDResponseOrderData.kt
+++ b/ebics/src/main/kotlin/ebics_h004/HTDResponseOrderData.kt
@@ -1,4 +1,4 @@
-package tech.libeufin.util.ebics_h004
+package tech.libeufin.ebics.ebics_h004
import javax.xml.bind.annotation.*
diff --git a/util/src/main/kotlin/ebics_h004/package-info.java
b/ebics/src/main/kotlin/ebics_h004/package-info.java
similarity index 76%
rename from util/src/main/kotlin/ebics_h004/package-info.java
rename to ebics/src/main/kotlin/ebics_h004/package-info.java
index 662a1605..d12a4727 100644
--- a/util/src/main/kotlin/ebics_h004/package-info.java
+++ b/ebics/src/main/kotlin/ebics_h004/package-info.java
@@ -7,6 +7,6 @@
namespace = "urn:org:ebics:H004",
elementFormDefault = XmlNsForm.QUALIFIED
)
-package tech.libeufin.util.ebics_h004;
+package tech.libeufin.ebics.ebics_h004;
import javax.xml.bind.annotation.XmlSchema;
import javax.xml.bind.annotation.XmlNsForm;
\ No newline at end of file
diff --git a/util/src/main/kotlin/ebics_h005/Ebics3Request.kt
b/ebics/src/main/kotlin/ebics_h005/Ebics3Request.kt
similarity index 99%
rename from util/src/main/kotlin/ebics_h005/Ebics3Request.kt
rename to ebics/src/main/kotlin/ebics_h005/Ebics3Request.kt
index f46c38f1..54987c8b 100644
--- a/util/src/main/kotlin/ebics_h005/Ebics3Request.kt
+++ b/ebics/src/main/kotlin/ebics_h005/Ebics3Request.kt
@@ -1,7 +1,7 @@
-package tech.libeufin.util.ebics_h005
+package tech.libeufin.ebics.ebics_h005
import org.apache.xml.security.binding.xmldsig.SignatureType
-import tech.libeufin.util.CryptoUtil
+import tech.libeufin.common.CryptoUtil
import java.math.BigInteger
import java.security.interfaces.RSAPublicKey
import java.util.*
diff --git a/util/src/main/kotlin/ebics_h005/Ebics3Response.kt
b/ebics/src/main/kotlin/ebics_h005/Ebics3Response.kt
similarity index 98%
rename from util/src/main/kotlin/ebics_h005/Ebics3Response.kt
rename to ebics/src/main/kotlin/ebics_h005/Ebics3Response.kt
index f22c0b85..12bf8a11 100644
--- a/util/src/main/kotlin/ebics_h005/Ebics3Response.kt
+++ b/ebics/src/main/kotlin/ebics_h005/Ebics3Response.kt
@@ -1,10 +1,10 @@
-package tech.libeufin.util.ebics_h005
+package tech.libeufin.ebics.ebics_h005
import org.apache.xml.security.binding.xmldsig.SignatureType
import org.apache.xml.security.binding.xmldsig.SignedInfoType
-import tech.libeufin.util.CryptoUtil
-import tech.libeufin.util.XMLUtil
-import tech.libeufin.util.ebics_h004.EbicsTypes
+import tech.libeufin.common.CryptoUtil
+import tech.libeufin.ebics.XMLUtil
+import tech.libeufin.ebics.ebics_h004.EbicsTypes
import java.math.BigInteger
import javax.xml.bind.annotation.*
import javax.xml.bind.annotation.adapters.CollapsedStringAdapter
diff --git a/util/src/main/kotlin/ebics_h005/Ebics3Types.kt
b/ebics/src/main/kotlin/ebics_h005/Ebics3Types.kt
similarity index 99%
rename from util/src/main/kotlin/ebics_h005/Ebics3Types.kt
rename to ebics/src/main/kotlin/ebics_h005/Ebics3Types.kt
index 2bb0659a..298dc655 100644
--- a/util/src/main/kotlin/ebics_h005/Ebics3Types.kt
+++ b/ebics/src/main/kotlin/ebics_h005/Ebics3Types.kt
@@ -17,7 +17,7 @@
* <http://www.gnu.org/licenses/>
*/
-package tech.libeufin.util.ebics_h005
+package tech.libeufin.ebics.ebics_h005
import org.apache.xml.security.binding.xmldsig.RSAKeyValueType
import org.w3c.dom.Element
diff --git a/util/src/main/kotlin/ebics_h005/package-info.java
b/ebics/src/main/kotlin/ebics_h005/package-info.java
similarity index 78%
rename from util/src/main/kotlin/ebics_h005/package-info.java
rename to ebics/src/main/kotlin/ebics_h005/package-info.java
index 6f65a4b2..42b565b7 100644
--- a/util/src/main/kotlin/ebics_h005/package-info.java
+++ b/ebics/src/main/kotlin/ebics_h005/package-info.java
@@ -7,7 +7,7 @@
namespace = "urn:org:ebics:H005",
elementFormDefault = XmlNsForm.QUALIFIED
)
-package tech.libeufin.util.ebics_h005;
+package tech.libeufin.ebics.ebics_h005;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
\ No newline at end of file
diff --git a/util/src/main/kotlin/ebics_hev/EbicsMessages.kt
b/ebics/src/main/kotlin/ebics_hev/EbicsMessages.kt
similarity index 98%
rename from util/src/main/kotlin/ebics_hev/EbicsMessages.kt
rename to ebics/src/main/kotlin/ebics_hev/EbicsMessages.kt
index 0d4302b3..506ba9fa 100644
--- a/util/src/main/kotlin/ebics_hev/EbicsMessages.kt
+++ b/ebics/src/main/kotlin/ebics_hev/EbicsMessages.kt
@@ -17,7 +17,7 @@
* <http://www.gnu.org/licenses/>
*/
-package tech.libeufin.util.ebics_hev
+package tech.libeufin.ebics.ebics_hev
import java.util.*
import javax.xml.bind.annotation.*
diff --git a/util/src/main/kotlin/ebics_hev/package-info.java
b/ebics/src/main/kotlin/ebics_hev/package-info.java
similarity index 89%
rename from util/src/main/kotlin/ebics_hev/package-info.java
rename to ebics/src/main/kotlin/ebics_hev/package-info.java
index ad7de333..8d2c7b54 100644
--- a/util/src/main/kotlin/ebics_hev/package-info.java
+++ b/ebics/src/main/kotlin/ebics_hev/package-info.java
@@ -7,7 +7,7 @@
namespace = "http://www.ebics.org/H000",
elementFormDefault = XmlNsForm.QUALIFIED
)
-package tech.libeufin.util.ebics_hev;
+package tech.libeufin.ebics.ebics_hev;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
diff --git a/util/src/main/kotlin/ebics_s001/SignatureTypes.kt
b/ebics/src/main/kotlin/ebics_s001/SignatureTypes.kt
similarity index 98%
rename from util/src/main/kotlin/ebics_s001/SignatureTypes.kt
rename to ebics/src/main/kotlin/ebics_s001/SignatureTypes.kt
index ea072527..4781ba26 100644
--- a/util/src/main/kotlin/ebics_s001/SignatureTypes.kt
+++ b/ebics/src/main/kotlin/ebics_s001/SignatureTypes.kt
@@ -17,7 +17,7 @@
* <http://www.gnu.org/licenses/>
*/
-package tech.libeufin.util.ebics_s001
+package tech.libeufin.ebics.ebics_s001
import org.apache.xml.security.binding.xmldsig.RSAKeyValueType
import org.apache.xml.security.binding.xmldsig.X509DataType
diff --git a/util/src/main/kotlin/ebics_s001/UserSignatureData.kt
b/ebics/src/main/kotlin/ebics_s001/UserSignatureData.kt
similarity index 95%
rename from util/src/main/kotlin/ebics_s001/UserSignatureData.kt
rename to ebics/src/main/kotlin/ebics_s001/UserSignatureData.kt
index cbb9ce6c..7eb5e0ed 100644
--- a/util/src/main/kotlin/ebics_s001/UserSignatureData.kt
+++ b/ebics/src/main/kotlin/ebics_s001/UserSignatureData.kt
@@ -1,4 +1,4 @@
-package tech.libeufin.util.ebics_s001
+package tech.libeufin.ebics.ebics_s001
import javax.xml.bind.annotation.*
diff --git a/util/src/main/kotlin/ebics_s001/package-info.java
b/ebics/src/main/kotlin/ebics_s001/package-info.java
similarity index 76%
rename from util/src/main/kotlin/ebics_s001/package-info.java
rename to ebics/src/main/kotlin/ebics_s001/package-info.java
index 0a2af713..adda5875 100644
--- a/util/src/main/kotlin/ebics_s001/package-info.java
+++ b/ebics/src/main/kotlin/ebics_s001/package-info.java
@@ -7,7 +7,7 @@
namespace = "http://www.ebics.org/S001",
elementFormDefault = XmlNsForm.QUALIFIED
)
-package tech.libeufin.util.ebics_s001;
+package tech.libeufin.ebics.ebics_s001;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
\ No newline at end of file
diff --git a/util/src/main/kotlin/ebics_s002/SignatureTypes.kt
b/ebics/src/main/kotlin/ebics_s002/SignatureTypes.kt
similarity index 98%
rename from util/src/main/kotlin/ebics_s002/SignatureTypes.kt
rename to ebics/src/main/kotlin/ebics_s002/SignatureTypes.kt
index 9e367fc9..c1d48e9b 100644
--- a/util/src/main/kotlin/ebics_s002/SignatureTypes.kt
+++ b/ebics/src/main/kotlin/ebics_s002/SignatureTypes.kt
@@ -17,7 +17,7 @@
* <http://www.gnu.org/licenses/>
*/
-package tech.libeufin.util.ebics_s002
+package tech.libeufin.ebics.ebics_s002
import org.apache.xml.security.binding.xmldsig.RSAKeyValueType
import org.apache.xml.security.binding.xmldsig.X509DataType
diff --git a/util/src/main/kotlin/ebics_s002/UserSignatureDataEbics3.kt
b/ebics/src/main/kotlin/ebics_s002/UserSignatureDataEbics3.kt
similarity index 95%
rename from util/src/main/kotlin/ebics_s002/UserSignatureDataEbics3.kt
rename to ebics/src/main/kotlin/ebics_s002/UserSignatureDataEbics3.kt
index 6d7012a1..082d0681 100644
--- a/util/src/main/kotlin/ebics_s002/UserSignatureDataEbics3.kt
+++ b/ebics/src/main/kotlin/ebics_s002/UserSignatureDataEbics3.kt
@@ -1,4 +1,4 @@
-package tech.libeufin.util.ebics_s002
+package tech.libeufin.ebics.ebics_s002
import javax.xml.bind.annotation.*
diff --git a/util/src/main/kotlin/ebics_s002/package-info.java
b/ebics/src/main/kotlin/ebics_s002/package-info.java
similarity index 76%
rename from util/src/main/kotlin/ebics_s002/package-info.java
rename to ebics/src/main/kotlin/ebics_s002/package-info.java
index a9f7729a..5ddb1f77 100644
--- a/util/src/main/kotlin/ebics_s002/package-info.java
+++ b/ebics/src/main/kotlin/ebics_s002/package-info.java
@@ -7,7 +7,7 @@
namespace = "http://www.ebics.org/S002",
elementFormDefault = XmlNsForm.QUALIFIED
)
-package tech.libeufin.util.ebics_s002;
+package tech.libeufin.ebics.ebics_s002;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
\ No newline at end of file
diff --git a/ebics/src/main/resources/version.txt
b/ebics/src/main/resources/version.txt
new file mode 100644
index 00000000..359d0539
--- /dev/null
+++ b/ebics/src/main/resources/version.txt
@@ -0,0 +1 @@
+v0.9.4-git-8aeffb3f
\ No newline at end of file
diff --git a/util/src/main/resources/xsd/camt.052.001.02.xsd
b/ebics/src/main/resources/xsd/camt.052.001.02.xsd
similarity index 100%
rename from util/src/main/resources/xsd/camt.052.001.02.xsd
rename to ebics/src/main/resources/xsd/camt.052.001.02.xsd
diff --git a/util/src/main/resources/xsd/camt.053.001.02.xsd
b/ebics/src/main/resources/xsd/camt.053.001.02.xsd
similarity index 100%
rename from util/src/main/resources/xsd/camt.053.001.02.xsd
rename to ebics/src/main/resources/xsd/camt.053.001.02.xsd
diff --git a/util/src/main/resources/xsd/camt.054.001.02.xsd
b/ebics/src/main/resources/xsd/camt.054.001.02.xsd
similarity index 100%
rename from util/src/main/resources/xsd/camt.054.001.02.xsd
rename to ebics/src/main/resources/xsd/camt.054.001.02.xsd
diff --git a/util/src/main/resources/xsd/ebics_H004.xsd
b/ebics/src/main/resources/xsd/ebics_H004.xsd
similarity index 100%
rename from util/src/main/resources/xsd/ebics_H004.xsd
rename to ebics/src/main/resources/xsd/ebics_H004.xsd
diff --git a/util/src/main/resources/xsd/ebics_H005.xsd
b/ebics/src/main/resources/xsd/ebics_H005.xsd
similarity index 100%
rename from util/src/main/resources/xsd/ebics_H005.xsd
rename to ebics/src/main/resources/xsd/ebics_H005.xsd
diff --git a/util/src/main/resources/xsd/ebics_hev.xsd
b/ebics/src/main/resources/xsd/ebics_hev.xsd
similarity index 100%
rename from util/src/main/resources/xsd/ebics_hev.xsd
rename to ebics/src/main/resources/xsd/ebics_hev.xsd
diff --git a/util/src/main/resources/xsd/ebics_keymgmt_request_H004.xsd
b/ebics/src/main/resources/xsd/ebics_keymgmt_request_H004.xsd
similarity index 100%
rename from util/src/main/resources/xsd/ebics_keymgmt_request_H004.xsd
rename to ebics/src/main/resources/xsd/ebics_keymgmt_request_H004.xsd
diff --git a/util/src/main/resources/xsd/ebics_keymgmt_request_H005.xsd
b/ebics/src/main/resources/xsd/ebics_keymgmt_request_H005.xsd
similarity index 100%
rename from util/src/main/resources/xsd/ebics_keymgmt_request_H005.xsd
rename to ebics/src/main/resources/xsd/ebics_keymgmt_request_H005.xsd
diff --git a/util/src/main/resources/xsd/ebics_keymgmt_response_H004.xsd
b/ebics/src/main/resources/xsd/ebics_keymgmt_response_H004.xsd
similarity index 100%
rename from util/src/main/resources/xsd/ebics_keymgmt_response_H004.xsd
rename to ebics/src/main/resources/xsd/ebics_keymgmt_response_H004.xsd
diff --git a/util/src/main/resources/xsd/ebics_keymgmt_response_H005.xsd
b/ebics/src/main/resources/xsd/ebics_keymgmt_response_H005.xsd
similarity index 100%
rename from util/src/main/resources/xsd/ebics_keymgmt_response_H005.xsd
rename to ebics/src/main/resources/xsd/ebics_keymgmt_response_H005.xsd
diff --git a/util/src/main/resources/xsd/ebics_orders_H004.xsd
b/ebics/src/main/resources/xsd/ebics_orders_H004.xsd
similarity index 100%
rename from util/src/main/resources/xsd/ebics_orders_H004.xsd
rename to ebics/src/main/resources/xsd/ebics_orders_H004.xsd
diff --git a/util/src/main/resources/xsd/ebics_orders_H005.xsd
b/ebics/src/main/resources/xsd/ebics_orders_H005.xsd
similarity index 100%
rename from util/src/main/resources/xsd/ebics_orders_H005.xsd
rename to ebics/src/main/resources/xsd/ebics_orders_H005.xsd
diff --git a/util/src/main/resources/xsd/ebics_request_H004.xsd
b/ebics/src/main/resources/xsd/ebics_request_H004.xsd
similarity index 100%
rename from util/src/main/resources/xsd/ebics_request_H004.xsd
rename to ebics/src/main/resources/xsd/ebics_request_H004.xsd
diff --git a/util/src/main/resources/xsd/ebics_request_H005.xsd
b/ebics/src/main/resources/xsd/ebics_request_H005.xsd
similarity index 100%
rename from util/src/main/resources/xsd/ebics_request_H005.xsd
rename to ebics/src/main/resources/xsd/ebics_request_H005.xsd
diff --git a/util/src/main/resources/xsd/ebics_response_H004.xsd
b/ebics/src/main/resources/xsd/ebics_response_H004.xsd
similarity index 100%
rename from util/src/main/resources/xsd/ebics_response_H004.xsd
rename to ebics/src/main/resources/xsd/ebics_response_H004.xsd
diff --git a/util/src/main/resources/xsd/ebics_response_H005.xsd
b/ebics/src/main/resources/xsd/ebics_response_H005.xsd
similarity index 100%
rename from util/src/main/resources/xsd/ebics_response_H005.xsd
rename to ebics/src/main/resources/xsd/ebics_response_H005.xsd
diff --git a/util/src/main/resources/xsd/ebics_signature_S002.xsd
b/ebics/src/main/resources/xsd/ebics_signature_S002.xsd
similarity index 100%
rename from util/src/main/resources/xsd/ebics_signature_S002.xsd
rename to ebics/src/main/resources/xsd/ebics_signature_S002.xsd
diff --git a/util/src/main/resources/xsd/ebics_signatures.xsd
b/ebics/src/main/resources/xsd/ebics_signatures.xsd
similarity index 100%
rename from util/src/main/resources/xsd/ebics_signatures.xsd
rename to ebics/src/main/resources/xsd/ebics_signatures.xsd
diff --git a/util/src/main/resources/xsd/ebics_types_H004.xsd
b/ebics/src/main/resources/xsd/ebics_types_H004.xsd
similarity index 100%
rename from util/src/main/resources/xsd/ebics_types_H004.xsd
rename to ebics/src/main/resources/xsd/ebics_types_H004.xsd
diff --git a/util/src/main/resources/xsd/ebics_types_H005.xsd
b/ebics/src/main/resources/xsd/ebics_types_H005.xsd
similarity index 100%
rename from util/src/main/resources/xsd/ebics_types_H005.xsd
rename to ebics/src/main/resources/xsd/ebics_types_H005.xsd
diff --git a/util/src/main/resources/xsd/pain.001.001.03.ch.02.xsd
b/ebics/src/main/resources/xsd/pain.001.001.03.ch.02.xsd
similarity index 100%
rename from util/src/main/resources/xsd/pain.001.001.03.ch.02.xsd
rename to ebics/src/main/resources/xsd/pain.001.001.03.ch.02.xsd
diff --git a/util/src/main/resources/xsd/pain.001.001.03.xsd
b/ebics/src/main/resources/xsd/pain.001.001.03.xsd
similarity index 100%
rename from util/src/main/resources/xsd/pain.001.001.03.xsd
rename to ebics/src/main/resources/xsd/pain.001.001.03.xsd
diff --git a/util/src/main/resources/xsd/pain.001.001.09.ch.03.xsd
b/ebics/src/main/resources/xsd/pain.001.001.09.ch.03.xsd
similarity index 100%
rename from util/src/main/resources/xsd/pain.001.001.09.ch.03.xsd
rename to ebics/src/main/resources/xsd/pain.001.001.09.ch.03.xsd
diff --git a/util/src/main/resources/xsd/pain.002.001.13.xsd
b/ebics/src/main/resources/xsd/pain.002.001.13.xsd
similarity index 100%
rename from util/src/main/resources/xsd/pain.002.001.13.xsd
rename to ebics/src/main/resources/xsd/pain.002.001.13.xsd
diff --git a/util/src/main/resources/xsd/xmldsig-core-schema.xsd
b/ebics/src/main/resources/xsd/xmldsig-core-schema.xsd
similarity index 100%
rename from util/src/main/resources/xsd/xmldsig-core-schema.xsd
rename to ebics/src/main/resources/xsd/xmldsig-core-schema.xsd
diff --git a/util/src/test/kotlin/EbicsMessagesTest.kt
b/ebics/src/test/kotlin/EbicsMessagesTest.kt
similarity index 98%
rename from util/src/test/kotlin/EbicsMessagesTest.kt
rename to ebics/src/test/kotlin/EbicsMessagesTest.kt
index c426d8fb..5d0f8f5d 100644
--- a/util/src/test/kotlin/EbicsMessagesTest.kt
+++ b/ebics/src/test/kotlin/EbicsMessagesTest.kt
@@ -23,12 +23,12 @@ import junit.framework.TestCase.assertEquals
import org.apache.xml.security.binding.xmldsig.SignatureType
import org.junit.Test
import org.w3c.dom.Element
-import tech.libeufin.util.ebics_h004.*
-import tech.libeufin.util.ebics_hev.HEVResponse
-import tech.libeufin.util.ebics_hev.SystemReturnCodeType
-import tech.libeufin.util.ebics_s001.SignatureTypes
-import tech.libeufin.util.CryptoUtil
-import tech.libeufin.util.XMLUtil
+import tech.libeufin.ebics.ebics_h004.*
+import tech.libeufin.ebics.ebics_hev.HEVResponse
+import tech.libeufin.ebics.ebics_hev.SystemReturnCodeType
+import tech.libeufin.ebics.ebics_s001.SignatureTypes
+import tech.libeufin.common.CryptoUtil
+import tech.libeufin.ebics.XMLUtil
import javax.xml.datatype.DatatypeFactory
import kotlin.test.assertNotNull
import kotlin.test.assertTrue
diff --git a/util/src/test/kotlin/EbicsOrderUtilTest.kt
b/ebics/src/test/kotlin/EbicsOrderUtilTest.kt
similarity index 99%
rename from util/src/test/kotlin/EbicsOrderUtilTest.kt
rename to ebics/src/test/kotlin/EbicsOrderUtilTest.kt
index 4a772ab5..05f7f72d 100644
--- a/util/src/test/kotlin/EbicsOrderUtilTest.kt
+++ b/ebics/src/test/kotlin/EbicsOrderUtilTest.kt
@@ -18,9 +18,9 @@
*/
import org.junit.Test
-import tech.libeufin.util.EbicsOrderUtil
-import tech.libeufin.util.XMLUtil
-import tech.libeufin.util.ebics_h004.HTDResponseOrderData
+import tech.libeufin.ebics.EbicsOrderUtil
+import tech.libeufin.ebics.XMLUtil
+import tech.libeufin.ebics.ebics_h004.HTDResponseOrderData
import kotlin.test.assertEquals
diff --git a/util/src/test/kotlin/SignatureDataTest.kt
b/ebics/src/test/kotlin/SignatureDataTest.kt
similarity index 95%
rename from util/src/test/kotlin/SignatureDataTest.kt
rename to ebics/src/test/kotlin/SignatureDataTest.kt
index 936ea91b..1a429ade 100644
--- a/util/src/test/kotlin/SignatureDataTest.kt
+++ b/ebics/src/test/kotlin/SignatureDataTest.kt
@@ -19,10 +19,10 @@
import org.apache.xml.security.binding.xmldsig.SignatureType
import org.junit.Test
-import tech.libeufin.util.CryptoUtil
-import tech.libeufin.util.XMLUtil
-import tech.libeufin.util.ebics_h004.EbicsRequest
-import tech.libeufin.util.ebics_h004.EbicsTypes
+import tech.libeufin.common.CryptoUtil
+import tech.libeufin.ebics.XMLUtil
+import tech.libeufin.ebics.ebics_h004.EbicsRequest
+import tech.libeufin.ebics.ebics_h004.EbicsTypes
import java.math.BigInteger
import java.util.*
import javax.xml.datatype.DatatypeFactory
diff --git a/util/src/test/kotlin/XmlCombinatorsTest.kt
b/ebics/src/test/kotlin/XmlCombinatorsTest.kt
similarity index 96%
rename from util/src/test/kotlin/XmlCombinatorsTest.kt
rename to ebics/src/test/kotlin/XmlCombinatorsTest.kt
index 4ecaa622..c261187a 100644
--- a/util/src/test/kotlin/XmlCombinatorsTest.kt
+++ b/ebics/src/test/kotlin/XmlCombinatorsTest.kt
@@ -18,8 +18,8 @@
*/
import org.junit.Test
-import tech.libeufin.util.XmlElementBuilder
-import tech.libeufin.util.constructXml
+import tech.libeufin.ebics.XmlElementBuilder
+import tech.libeufin.ebics.constructXml
class XmlCombinatorsTest {
diff --git a/util/src/test/kotlin/XmlUtilTest.kt
b/ebics/src/test/kotlin/XmlUtilTest.kt
similarity index 95%
rename from util/src/test/kotlin/XmlUtilTest.kt
rename to ebics/src/test/kotlin/XmlUtilTest.kt
index e059c78e..b8639d7a 100644
--- a/util/src/test/kotlin/XmlUtilTest.kt
+++ b/ebics/src/test/kotlin/XmlUtilTest.kt
@@ -22,16 +22,16 @@ import org.junit.Test
import org.junit.Assert.*
import org.slf4j.Logger
import org.slf4j.LoggerFactory
-import tech.libeufin.util.ebics_h004.EbicsKeyManagementResponse
-import tech.libeufin.util.ebics_h004.EbicsResponse
-import tech.libeufin.util.ebics_h004.EbicsTypes
-import tech.libeufin.util.ebics_h004.HTDResponseOrderData
-import tech.libeufin.util.CryptoUtil
-import tech.libeufin.util.XMLUtil
+import tech.libeufin.ebics.ebics_h004.EbicsKeyManagementResponse
+import tech.libeufin.ebics.ebics_h004.EbicsResponse
+import tech.libeufin.ebics.ebics_h004.EbicsTypes
+import tech.libeufin.ebics.ebics_h004.HTDResponseOrderData
+import tech.libeufin.common.CryptoUtil
+import tech.libeufin.ebics.XMLUtil
import java.security.KeyPairGenerator
import java.util.*
import javax.xml.transform.stream.StreamSource
-import tech.libeufin.util.XMLUtil.Companion.signEbicsResponse
+import tech.libeufin.ebics.XMLUtil.Companion.signEbicsResponse
class XmlUtilTest {
diff --git a/util/src/test/resources/ebics_hev.xml
b/ebics/src/test/resources/ebics_hev.xml
similarity index 100%
rename from util/src/test/resources/ebics_hev.xml
rename to ebics/src/test/resources/ebics_hev.xml
diff --git a/util/src/test/resources/ebics_ini_inner_key.xml
b/ebics/src/test/resources/ebics_ini_inner_key.xml
similarity index 100%
rename from util/src/test/resources/ebics_ini_inner_key.xml
rename to ebics/src/test/resources/ebics_ini_inner_key.xml
diff --git a/util/src/test/resources/ebics_ini_request_sample.xml
b/ebics/src/test/resources/ebics_ini_request_sample.xml
similarity index 100%
rename from util/src/test/resources/ebics_ini_request_sample.xml
rename to ebics/src/test/resources/ebics_ini_request_sample.xml
diff --git a/util/src/test/resources/hia_request.xml
b/ebics/src/test/resources/hia_request.xml
similarity index 100%
rename from util/src/test/resources/hia_request.xml
rename to ebics/src/test/resources/hia_request.xml
diff --git a/util/src/test/resources/hia_request_order_data.xml
b/ebics/src/test/resources/hia_request_order_data.xml
similarity index 100%
rename from util/src/test/resources/hia_request_order_data.xml
rename to ebics/src/test/resources/hia_request_order_data.xml
diff --git a/util/src/test/resources/hpb_request.xml
b/ebics/src/test/resources/hpb_request.xml
similarity index 100%
rename from util/src/test/resources/hpb_request.xml
rename to ebics/src/test/resources/hpb_request.xml
diff --git a/util/src/test/resources/signature1/doc.xml
b/ebics/src/test/resources/signature1/doc.xml
similarity index 100%
rename from util/src/test/resources/signature1/doc.xml
rename to ebics/src/test/resources/signature1/doc.xml
diff --git a/util/src/test/resources/signature1/public_key.txt
b/ebics/src/test/resources/signature1/public_key.txt
similarity index 100%
rename from util/src/test/resources/signature1/public_key.txt
rename to ebics/src/test/resources/signature1/public_key.txt
diff --git a/nexus/build.gradle b/nexus/build.gradle
index 75491bb3..5c082385 100644
--- a/nexus/build.gradle
+++ b/nexus/build.gradle
@@ -21,8 +21,8 @@ dependencies {
// Core language libraries
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version")
- // LibEuFin util library
- implementation(project(":util"))
+ implementation(project(":common"))
+ implementation(project(":ebics"))
// XML parsing/binding and encryption
implementation("javax.xml.bind:jaxb-api:2.3.0")
@@ -35,7 +35,6 @@ dependencies {
// Command line parsing
implementation("com.github.ajalt.clikt:clikt:$clikt_version")
implementation("org.postgresql:postgresql:$postgres_version")
- implementation("com.zaxxer:HikariCP:5.0.1")
// Ktor client library
implementation("io.ktor:ktor-client-apache:$ktor_version")
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Database.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/Database.kt
index 430d5d83..82d493e8 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Database.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Database.kt
@@ -22,8 +22,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.postgresql.jdbc.PgConnection
import org.postgresql.util.PSQLState
-import com.zaxxer.hikari.*
-import tech.libeufin.util.*
+import tech.libeufin.common.*
import java.sql.PreparedStatement
import java.sql.SQLException
import java.time.Instant
@@ -40,24 +39,6 @@ fun Instant.fmtDateTime(): String {
return formatter.format(Date.from(this))
}
-
-// Remove this once TalerAmount from the bank
-// module gets moved to the 'util' module (#7987).
-data class TalerAmount(
- val value: Long,
- val fraction: Int, // has at most 8 digits.
- val currency: String
-) {
- override fun toString(): String {
- if (fraction == 0) {
- return "$currency:$value"
- } else {
- return "$currency:$value.${fraction.toString().padStart(8, '0')}"
- .dropLastWhile { it == '0' } // Trim useless fractional
trailing 0
- }
- }
-}
-
// INCOMING PAYMENTS STRUCTS
/**
@@ -107,7 +88,7 @@ enum class DatabaseSubmissionState {
data class InitiatedPayment(
val amount: TalerAmount,
val wireTransferSubject: String,
- val creditPaytoUri: String,
+ val creditPaytoUri: FullIbanPayto,
val initiationTime: Instant,
val requestUid: String
)
@@ -117,16 +98,6 @@ data class InitiatedPayment(
* into the database.
*/
enum class PaymentInitiationOutcome {
- /**
- * The Payto address to send the payment to was invalid.
- */
- BAD_CREDIT_PAYTO,
-
- /**
- * The receiver payto address lacks the name, that would
- * cause the bank to reject the pain.001.
- */
- RECEIVER_NAME_MISSING,
/**
* The row contains a client_request_uid that exists
@@ -198,39 +169,7 @@ private fun PreparedStatement.maybeUpdate(): Boolean {
/**
* Collects database connection steps and any operation on the Nexus tables.
*/
-class Database(dbConfig: String): java.io.Closeable {
- val dbPool: HikariDataSource
-
- init {
- val pgSource = pgDataSource(dbConfig)
- val config = HikariConfig();
- config.dataSource = pgSource
- config.connectionInitSql = "SET search_path TO libeufin_nexus;"
- config.validate()
- dbPool = HikariDataSource(config);
- }
-
- /**
- * Closes the database connection.
- */
- override fun close() {
- dbPool.close()
- }
-
- /**
- * Moves the database operations where they can block, without
- * blocking the whole process.
- *
- * @param lambda actual statement preparation and execution logic.
- * @return what lambda returns.
- */
- suspend fun <R> runConn(lambda: suspend (PgConnection) -> R): R {
- // Use a coroutine dispatcher that we can block as JDBC API is blocking
- return withContext(Dispatchers.IO) {
- val conn = dbPool.getConnection()
- conn.use { it -> lambda(it.unwrap(PgConnection::class.java)) }
- }
- }
+class Database(dbConfig: String): DbPool(dbConfig, "libeufin_nexus") {
// OUTGOING PAYMENTS METHODS
@@ -241,7 +180,7 @@ class Database(dbConfig: String): java.io.Closeable {
* @param paymentData information about the outgoing payment.
* @return operation outcome enum.
*/
- suspend fun registerOutgoing(paymentData: OutgoingPayment):
OutgoingRegistrationResult = runConn {
+ suspend fun registerOutgoing(paymentData: OutgoingPayment):
OutgoingRegistrationResult = conn {
val stmt = it.prepareStatement("""
SELECT out_tx_id, out_initiated, out_found
FROM register_outgoing(
@@ -255,7 +194,7 @@ class Database(dbConfig: String): java.io.Closeable {
val executionTime = paymentData.executionTime.toDbMicros()
?: throw Exception("Could not convert outgoing payment
execution_time to microseconds")
stmt.setLong(1, paymentData.amount.value)
- stmt.setInt(2, paymentData.amount.fraction)
+ stmt.setInt(2, paymentData.amount.frac)
stmt.setString(3, paymentData.wireTransferSubject)
stmt.setLong(4, executionTime)
stmt.setString(5, paymentData.creditPaytoUri)
@@ -289,7 +228,7 @@ class Database(dbConfig: String): java.io.Closeable {
paymentData: IncomingPayment,
bounceAmount: TalerAmount,
now: Instant
- ): IncomingBounceRegistrationResult = runConn {
+ ): IncomingBounceRegistrationResult = conn {
val stmt = it.prepareStatement("""
SELECT out_found, out_tx_id, out_bounce_id
FROM register_incoming_and_bounce(
@@ -307,13 +246,13 @@ class Database(dbConfig: String): java.io.Closeable {
val executionTime = paymentData.executionTime.toDbMicros()
?: throw Exception("Could not convert payment execution time from
Instant to microseconds.")
stmt.setLong(1, paymentData.amount.value)
- stmt.setInt(2, paymentData.amount.fraction)
+ stmt.setInt(2, paymentData.amount.frac)
stmt.setString(3, paymentData.wireTransferSubject)
stmt.setLong(4, executionTime)
stmt.setString(5, paymentData.debitPaytoUri)
stmt.setString(6, paymentData.bankId)
stmt.setLong(7, bounceAmount.value)
- stmt.setInt(8, bounceAmount.fraction)
+ stmt.setInt(8, bounceAmount.frac)
stmt.setLong(9, refundTimestamp)
stmt.executeQuery().use {
when {
@@ -337,7 +276,7 @@ class Database(dbConfig: String): java.io.Closeable {
suspend fun registerTalerableIncoming(
paymentData: IncomingPayment,
reservePub: ByteArray
- ): IncomingRegistrationResult = runConn { conn ->
+ ): IncomingRegistrationResult = conn { conn ->
val stmt = conn.prepareStatement("""
SELECT out_found, out_tx_id
FROM register_incoming_and_talerable(
@@ -352,7 +291,7 @@ class Database(dbConfig: String): java.io.Closeable {
val executionTime = paymentData.executionTime.toDbMicros()
?: throw Exception("Could not convert payment execution time from
Instant to microseconds.")
stmt.setLong(1, paymentData.amount.value)
- stmt.setInt(2, paymentData.amount.fraction)
+ stmt.setInt(2, paymentData.amount.frac)
stmt.setString(3, paymentData.wireTransferSubject)
stmt.setLong(4, executionTime)
stmt.setString(5, paymentData.debitPaytoUri)
@@ -374,15 +313,15 @@ class Database(dbConfig: String): java.io.Closeable {
*
* @return [Instant] or null if no results were found
*/
- suspend fun outgoingPaymentLastExecTime(): Instant? = runConn { conn ->
+ suspend fun outgoingPaymentLastExecTime(): Instant? = conn { conn ->
val stmt = conn.prepareStatement(
"SELECT MAX(execution_time) as latest_execution_time FROM
outgoing_transactions"
)
stmt.executeQuery().use {
- if (!it.next()) return@runConn null
+ if (!it.next()) return@conn null
val timestamp = it.getLong("latest_execution_time")
- if (timestamp == 0L) return@runConn null
- return@runConn timestamp.microsToJavaInstant()
+ if (timestamp == 0L) return@conn null
+ return@conn timestamp.microsToJavaInstant()
?: throw Exception("Could not convert latest_execution_time to
Instant")
}
}
@@ -392,15 +331,15 @@ class Database(dbConfig: String): java.io.Closeable {
*
* @return [Instant] or null if no results were found
*/
- suspend fun incomingPaymentLastExecTime(): Instant? = runConn { conn ->
+ suspend fun incomingPaymentLastExecTime(): Instant? = conn { conn ->
val stmt = conn.prepareStatement(
"SELECT MAX(execution_time) as latest_execution_time FROM
incoming_transactions"
)
stmt.executeQuery().use {
- if (!it.next()) return@runConn null
+ if (!it.next()) return@conn null
val timestamp = it.getLong("latest_execution_time")
- if (timestamp == 0L) return@runConn null
- return@runConn timestamp.microsToJavaInstant()
+ if (timestamp == 0L) return@conn null
+ return@conn timestamp.microsToJavaInstant()
?: throw Exception("Could not convert latest_execution_time to
Instant")
}
}
@@ -411,7 +350,7 @@ class Database(dbConfig: String): java.io.Closeable {
* @param maybeReservePub reserve public key to look up
* @return true if found, false otherwise
*/
- suspend fun isReservePubFound(maybeReservePub: ByteArray): Boolean =
runConn { conn ->
+ suspend fun isReservePubFound(maybeReservePub: ByteArray): Boolean = conn
{ conn ->
val stmt = conn.prepareStatement("""
SELECT 1
FROM talerable_incoming_transactions
@@ -420,7 +359,7 @@ class Database(dbConfig: String): java.io.Closeable {
stmt.setBytes(1, maybeReservePub)
val res = stmt.executeQuery()
res.use {
- return@runConn it.next()
+ return@conn it.next()
}
}
@@ -445,7 +384,7 @@ class Database(dbConfig: String): java.io.Closeable {
suspend fun initiatedPaymentSetSubmittedState(
rowId: Long,
submissionState: DatabaseSubmissionState
- ): Boolean = runConn { conn ->
+ ): Boolean = conn { conn ->
val stmt = conn.prepareStatement("""
UPDATE initiated_outgoing_transactions
SET submitted = submission_state(?),
last_submission_time = ?
@@ -458,7 +397,7 @@ class Database(dbConfig: String): java.io.Closeable {
throw Exception("Submission time could not be converted to
microseconds for the database.")
})
stmt.setLong(3, rowId)
- return@runConn stmt.maybeUpdate()
+ return@conn stmt.maybeUpdate()
}
/**
@@ -468,7 +407,7 @@ class Database(dbConfig: String): java.io.Closeable {
* @param failureMessage error associated to this initiated payment.
* @return true on success, false if no payment was affected.
*/
- suspend fun initiatedPaymentSetFailureMessage(rowId: Long, failureMessage:
String): Boolean = runConn { conn ->
+ suspend fun initiatedPaymentSetFailureMessage(rowId: Long, failureMessage:
String): Boolean = conn { conn ->
val stmt = conn.prepareStatement("""
UPDATE initiated_outgoing_transactions
SET failure_message = ?
@@ -477,7 +416,7 @@ class Database(dbConfig: String): java.io.Closeable {
)
stmt.setString(1, failureMessage)
stmt.setLong(2, rowId)
- return@runConn stmt.maybeUpdate()
+ return@conn stmt.maybeUpdate()
}
/**
@@ -487,7 +426,7 @@ class Database(dbConfig: String): java.io.Closeable {
* @param currency in which currency should the payment be submitted to
the bank.
* @return [Map] of the initiated payment row ID and [InitiatedPayment]
*/
- suspend fun initiatedPaymentsSubmittableGet(currency: String): Map<Long,
InitiatedPayment> = runConn { conn ->
+ suspend fun initiatedPaymentsSubmittableGet(currency: String): Map<Long,
InitiatedPayment> = conn { conn ->
val stmt = conn.prepareStatement("""
SELECT
initiated_outgoing_transaction_id
@@ -511,19 +450,15 @@ class Database(dbConfig: String): java.io.Closeable {
throw Exception("Found invalid timestamp at initiated
payment with ID: $rowId")
}
maybeMap[rowId] = InitiatedPayment(
- amount = TalerAmount(
- value = it.getLong("amount_val"),
- fraction = it.getInt("amount_frac"),
- currency = currency
- ),
- creditPaytoUri = it.getString("credit_payto_uri"),
+ amount = it.getAmount("amount", currency),
+ creditPaytoUri =
IbanPayto(it.getString("credit_payto_uri")).requireFull(),
wireTransferSubject =
it.getString("wire_transfer_subject"),
initiationTime = initiationTime,
requestUid = it.getString("request_uid")
)
} while (it.next())
}
- return@runConn maybeMap
+ return@conn maybeMap
}
/**
* Initiate a payment in the database. The "submit"
@@ -533,7 +468,7 @@ class Database(dbConfig: String): java.io.Closeable {
* @param paymentData any data that's used to prepare the payment.
* @return true if the insertion went through, false in case of errors.
*/
- suspend fun initiatedPaymentCreate(paymentData: InitiatedPayment):
PaymentInitiationOutcome = runConn { conn ->
+ suspend fun initiatedPaymentCreate(paymentData: InitiatedPayment):
PaymentInitiationOutcome = conn { conn ->
val stmt = conn.prepareStatement("""
INSERT INTO initiated_outgoing_transactions (
amount
@@ -550,25 +485,21 @@ class Database(dbConfig: String): java.io.Closeable {
)
""")
stmt.setLong(1, paymentData.amount.value)
- stmt.setInt(2, paymentData.amount.fraction)
+ stmt.setInt(2, paymentData.amount.frac)
stmt.setString(3, paymentData.wireTransferSubject)
- parsePayto(paymentData.creditPaytoUri).apply {
- if (this == null) return@runConn
PaymentInitiationOutcome.BAD_CREDIT_PAYTO
- if (this.receiverName == null) return@runConn
PaymentInitiationOutcome.RECEIVER_NAME_MISSING
- }
- stmt.setString(4, paymentData.creditPaytoUri)
+ stmt.setString(4, paymentData.creditPaytoUri.full)
val initiationTime = paymentData.initiationTime.toDbMicros() ?: run {
throw Exception("Initiation time could not be converted to
microseconds for the database.")
}
stmt.setLong(5, initiationTime)
stmt.setString(6, paymentData.requestUid) // can be null.
if (stmt.maybeUpdate())
- return@runConn PaymentInitiationOutcome.SUCCESS
+ return@conn PaymentInitiationOutcome.SUCCESS
/**
* _very_ likely, Nexus didn't check the request idempotency,
* as the row ID would never fall into the following problem.
*/
- return@runConn PaymentInitiationOutcome.UNIQUE_CONSTRAINT_VIOLATION
+ return@conn PaymentInitiationOutcome.UNIQUE_CONSTRAINT_VIOLATION
}
/**
@@ -583,7 +514,7 @@ class Database(dbConfig: String): java.io.Closeable {
* null gets returned even when the initiated payment exists,
* *but* it was NOT flagged as submitted.
*/
- suspend fun initiatedPaymentGetFromUid(uid: String): Long? = runConn {
conn ->
+ suspend fun initiatedPaymentGetFromUid(uid: String): Long? = conn { conn ->
val stmt = conn.prepareStatement("""
SELECT initiated_outgoing_transaction_id
FROM initiated_outgoing_transactions
@@ -592,8 +523,8 @@ class Database(dbConfig: String): java.io.Closeable {
stmt.setString(1, uid)
val res = stmt.executeQuery()
res.use {
- if (!it.next()) return@runConn null
- return@runConn it.getLong("initiated_outgoing_transaction_id")
+ if (!it.next()) return@conn null
+ return@conn it.getLong("initiated_outgoing_transaction_id")
}
}
}
\ No newline at end of file
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/DbInit.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/DbInit.kt
index 95b532b3..a05d781a 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/DbInit.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/DbInit.kt
@@ -21,7 +21,7 @@ package tech.libeufin.nexus
import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.parameters.options.*
import com.github.ajalt.clikt.parameters.groups.*
-import tech.libeufin.util.*
+import tech.libeufin.common.*
/**
* This subcommand tries to load the SQL files that define
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt
index 294a8f51..55a3e401 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt
@@ -23,11 +23,9 @@ import com.github.ajalt.clikt.parameters.options.*
import com.github.ajalt.clikt.parameters.groups.*
import io.ktor.client.*
import kotlinx.coroutines.*
-import net.taler.wallet.crypto.Base32Crockford
-import net.taler.wallet.crypto.EncodingException
import tech.libeufin.nexus.ebics.*
-import tech.libeufin.util.*
-import tech.libeufin.util.ebics_h005.Ebics3Request
+import tech.libeufin.common.*
+import tech.libeufin.ebics.ebics_h005.Ebics3Request
import java.io.File
import java.io.IOException
import java.nio.file.Path
@@ -145,37 +143,6 @@ private fun makeTalerFrac(bankFrac: String): Int {
return buf
}
-/**
- * Gets Taler amount from a currency-agnostic value.
- *
- * @param noCurrencyAmount currency-agnostic value coming from the bank.
- * @param currency currency to set to the result.
- * @return [TalerAmount]
- */
-fun getTalerAmount(
- noCurrencyAmount: String,
- currency: String,
- errorMessagePrefix: String = ""
-): TalerAmount {
- if (currency.isEmpty()) throw Exception("Wrong helper invocation: currency
is empty")
- val split = noCurrencyAmount.split(".")
- // only 1 (no fraction) or 2 (with fraction) sizes allowed.
- if (split.size != 1 && split.size != 2)
- throw Exception("${errorMessagePrefix}invalid amount:
$noCurrencyAmount")
- val value = split[0].toLongOrNull()
- ?: throw Exception("${errorMessagePrefix}value part '${split[0]}' not
a long")
- if (split.size == 1) return TalerAmount(
- value = value,
- fraction = 0,
- currency = currency
- )
- return TalerAmount(
- value = value,
- fraction = makeTalerFrac(split[1]),
- currency = currency
- )
-}
-
/**
* Converts valid reserve pubs to its binary representation.
*
@@ -293,25 +260,6 @@ suspend fun ingestIncomingPayment(
}
}
-/**
- * Compares amounts.
- *
- * @param a first argument
- * @param b second argument
- * @return true if the first argument
- * is less than the second
- */
-fun firstLessThanSecond(
- a: TalerAmount,
- b: TalerAmount
-): Boolean {
- if (a.currency != b.currency)
- throw Exception("different currencies: ${a.currency} vs.
${b.currency}")
- if (a.value == b.value)
- return a.fraction < b.fraction
- return a.value < b.value
-}
-
private fun ingestDocument(
db: Database,
currency: String,
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSetup.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSetup.kt
index 8c2d9c2e..5278afc1 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSetup.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSetup.kt
@@ -24,13 +24,13 @@ import com.github.ajalt.clikt.parameters.options.*
import com.github.ajalt.clikt.parameters.groups.*
import io.ktor.client.*
import kotlinx.coroutines.runBlocking
-import tech.libeufin.util.ebics_h004.EbicsTypes
+import tech.libeufin.ebics.ebics_h004.EbicsTypes
import java.io.File
-import TalerConfigError
import kotlinx.serialization.encodeToString
import tech.libeufin.nexus.ebics.*
-import tech.libeufin.util.*
-import tech.libeufin.util.ebics_h004.HTDResponseOrderData
+import tech.libeufin.common.*
+import tech.libeufin.ebics.*
+import tech.libeufin.ebics.ebics_h004.HTDResponseOrderData
import java.time.Instant
import kotlin.reflect.typeOf
import java.nio.file.Files
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSubmit.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSubmit.kt
index 6e8607e3..dbd178b3 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSubmit.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSubmit.kt
@@ -28,7 +28,7 @@ import tech.libeufin.nexus.ebics.EbicsSideError
import tech.libeufin.nexus.ebics.EbicsSideException
import tech.libeufin.nexus.ebics.EbicsUploadException
import tech.libeufin.nexus.ebics.submitPain001
-import tech.libeufin.util.*
+import tech.libeufin.common.*
import java.io.File
import java.nio.file.Path
import java.time.Instant
@@ -97,18 +97,12 @@ class NexusSubmitException(
private suspend fun submitInitiatedPayment(
ctx: SubmissionContext,
initiatedPayment: InitiatedPayment
-) {
- val creditor = parsePayto(initiatedPayment.creditPaytoUri)
- if (creditor?.receiverName == null)
- throw NexusSubmitException(
- "Won't create pain.001 without the receiver name",
- stage = NexusSubmissionStage.pain
- )
+) {
val xml = createPain001(
requestUid = initiatedPayment.requestUid,
initiationTimestamp = initiatedPayment.initiationTime,
amount = initiatedPayment.amount,
- creditAccount = creditor,
+ creditAccount = initiatedPayment.creditPaytoUri,
debitAccount = ctx.cfg.myIbanAccount,
wireTransferSubject = initiatedPayment.wireTransferSubject
)
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt
index 0617e12a..005b010d 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt
@@ -18,7 +18,8 @@
*/
package tech.libeufin.nexus
-import tech.libeufin.util.*
+import tech.libeufin.common.*
+import tech.libeufin.ebics.*
import java.net.URLEncoder
import java.time.Instant
import java.time.ZoneId
@@ -44,12 +45,10 @@ data class Pain001Namespaces(
* @return [String] of the amount number without the currency.
*/
fun getAmountNoCurrency(amount: TalerAmount): String {
- if (amount.fraction.toString().length > 8)
- throw Exception("Taler amount must have at most 8 fractional digits")
- if (amount.fraction == 0) {
+ if (amount.frac == 0) {
return amount.value.toString()
} else {
- val fractionFormat = amount.fraction.toString().padStart(8,
'0').dropLastWhile { it == '0' }
+ val fractionFormat = amount.frac.toString().padStart(8,
'0').dropLastWhile { it == '0' }
if (fractionFormat.length > 2) throw Exception("Sub-cent amounts not
supported")
return "${amount.value}.${fractionFormat}"
}
@@ -78,7 +77,7 @@ fun createPain001(
debitAccount: IbanAccountMetadata,
amount: TalerAmount,
wireTransferSubject: String,
- creditAccount: IbanPayto
+ creditAccount: FullIbanPayto
): String {
val namespace = Pain001Namespaces(
fullNamespace = "urn:iso:std:iso:20022:tech:xsd:pain.001.001.09",
@@ -86,11 +85,6 @@ fun createPain001(
)
val zonedTimestamp = ZonedDateTime.ofInstant(initiationTimestamp,
ZoneId.of("UTC"))
val amountWithoutCurrency: String = getAmountNoCurrency(amount)
- val creditorName: String = creditAccount.receiverName
- ?: throw NexusSubmitException(
- "Cannot operate without the creditor name",
- stage=NexusSubmissionStage.pain
- )
return constructXml {
root("Document") {
attribute(
@@ -158,10 +152,10 @@ fun createPain001(
text(amountWithoutCurrency)
}
element("Cdtr/Nm") {
- text(creditorName)
+ text(creditAccount.receiverName)
}
element("CdtrAcct/Id/IBAN") {
- text(creditAccount.iban)
+ text(creditAccount.payto.iban)
}
element("RmtInf/Ustrd") {
text(wireTransferSubject)
@@ -332,7 +326,7 @@ fun parseTxNotif(
* FIXME: test by sending non-CHF to PoFi and see which currency
gets here.
*/
if (currency != acceptedCurrency) throw Exception("Currency
$currency not supported")
- getTalerAmount(focusElement.textContent, currency)
+ TalerAmount("$currency:${focusElement.textContent}")
}
when (kind) {
"CRDT" -> {
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Log.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/Log.kt
index 25ed95af..e59b65f4 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Log.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Log.kt
@@ -20,7 +20,7 @@
package tech.libeufin.nexus
import tech.libeufin.nexus.ebics.unzipForEach
-import tech.libeufin.util.*
+import tech.libeufin.common.*
import java.io.*
import java.nio.file.*
import kotlin.io.path.*
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
index da6e6237..699af965 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
@@ -23,8 +23,7 @@
* kept in their respective files.
*/
package tech.libeufin.nexus
-import ConfigSource
-import TalerConfig
+
import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.core.subcommands
import com.github.ajalt.clikt.parameters.options.versionOption
@@ -43,9 +42,8 @@ import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.Json
import kotlinx.serialization.modules.SerializersModule
-import net.taler.wallet.crypto.Base32Crockford
import tech.libeufin.nexus.ebics.*
-import tech.libeufin.util.*
+import tech.libeufin.common.*
import java.security.interfaces.RSAPrivateCrtKey
import java.security.interfaces.RSAPublicKey
import java.io.FileNotFoundException
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/Ebics2.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/Ebics2.kt
index 19fe88e6..ff59fa7e 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/Ebics2.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/Ebics2.kt
@@ -30,9 +30,9 @@ import org.slf4j.LoggerFactory
import tech.libeufin.nexus.BankPublicKeysFile
import tech.libeufin.nexus.ClientPrivateKeysFile
import tech.libeufin.nexus.EbicsSetupConfig
-import tech.libeufin.util.*
-import tech.libeufin.util.ebics_h004.*
-import tech.libeufin.util.ebics_h005.Ebics3Request
+import tech.libeufin.ebics.*
+import tech.libeufin.ebics.ebics_h004.*
+import tech.libeufin.ebics.ebics_h005.Ebics3Request
import java.security.interfaces.RSAPrivateCrtKey
import java.time.Instant
import java.time.ZoneId
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/Ebics3.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/Ebics3.kt
index 647aca74..16e5daba 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/Ebics3.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/Ebics3.kt
@@ -23,11 +23,11 @@ import tech.libeufin.nexus.BankPublicKeysFile
import tech.libeufin.nexus.ClientPrivateKeysFile
import tech.libeufin.nexus.EbicsSetupConfig
import tech.libeufin.nexus.logger
-import tech.libeufin.util.PreparedUploadData
-import tech.libeufin.util.XMLUtil
-import tech.libeufin.util.ebics_h005.Ebics3Request
-import tech.libeufin.util.getNonce
-import tech.libeufin.util.getXmlDate
+import tech.libeufin.ebics.PreparedUploadData
+import tech.libeufin.ebics.XMLUtil
+import tech.libeufin.ebics.ebics_h005.Ebics3Request
+import tech.libeufin.ebics.getNonce
+import tech.libeufin.ebics.getXmlDate
import java.math.BigInteger
import java.time.Instant
import java.util.*
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsCommon.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsCommon.kt
index 642b60ca..167954d0 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsCommon.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsCommon.kt
@@ -47,8 +47,9 @@ import
org.apache.commons.compress.utils.SeekableInMemoryByteChannel
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import tech.libeufin.nexus.*
-import tech.libeufin.util.*
-import tech.libeufin.util.ebics_h005.Ebics3Request
+import tech.libeufin.common.*
+import tech.libeufin.ebics.*
+import tech.libeufin.ebics.ebics_h005.Ebics3Request
import java.io.ByteArrayOutputStream
import java.security.interfaces.RSAPrivateCrtKey
import java.time.LocalDateTime
diff --git a/nexus/src/test/kotlin/CliTest.kt b/nexus/src/test/kotlin/CliTest.kt
index 9ad737e3..a57088c7 100644
--- a/nexus/src/test/kotlin/CliTest.kt
+++ b/nexus/src/test/kotlin/CliTest.kt
@@ -24,7 +24,7 @@ import kotlin.test.*
import java.io.*
import java.nio.file.*
import kotlin.io.path.*
-import tech.libeufin.util.*
+import tech.libeufin.common.*
val nexusCmd = LibeufinNexusCommand()
diff --git a/nexus/src/test/kotlin/Common.kt b/nexus/src/test/kotlin/Common.kt
index 5adbf157..f5c2f07e 100644
--- a/nexus/src/test/kotlin/Common.kt
+++ b/nexus/src/test/kotlin/Common.kt
@@ -23,7 +23,7 @@ import io.ktor.client.request.*
import kotlinx.serialization.json.Json
import kotlinx.serialization.modules.SerializersModule
import tech.libeufin.nexus.*
-import tech.libeufin.util.*
+import tech.libeufin.common.*
import java.security.interfaces.RSAPrivateCrtKey
import java.time.Instant
@@ -103,7 +103,7 @@ fun genInitPay(
) =
InitiatedPayment(
amount = TalerAmount(44, 0, "KUDOS"),
- creditPaytoUri = "payto://iban/TEST-IBAN?receiver-name=Test",
+ creditPaytoUri =
IbanPayto("payto://iban/CH9300762011623852957?receiver-name=Test").requireFull(),
wireTransferSubject = subject,
initiationTime = Instant.now(),
requestUid = requestUid
@@ -123,7 +123,7 @@ fun genInPay(subject: String) =
fun genOutPay(subject: String, messageId: String) =
OutgoingPayment(
amount = TalerAmount(44, 0, "KUDOS"),
- creditPaytoUri = "payto://iban/TEST-IBAN?receiver-name=Test",
+ creditPaytoUri =
"payto://iban/CH9300762011623852957?receiver-name=Test",
wireTransferSubject = subject,
executionTime = Instant.now(),
messageId = messageId
diff --git a/nexus/src/test/kotlin/ConfigLoading.kt
b/nexus/src/test/kotlin/ConfigLoading.kt
index bd636f6a..cb9159b0 100644
--- a/nexus/src/test/kotlin/ConfigLoading.kt
+++ b/nexus/src/test/kotlin/ConfigLoading.kt
@@ -24,6 +24,7 @@ import tech.libeufin.nexus.NEXUS_CONFIG_SOURCE
import tech.libeufin.nexus.getFrequencyInSeconds
import kotlin.test.assertEquals
import kotlin.test.assertNull
+import tech.libeufin.common.*
class ConfigLoading {
/**
@@ -43,7 +44,6 @@ class ConfigLoading {
val handle = TalerConfig(NEXUS_CONFIG_SOURCE)
handle.load()
val cfg = EbicsSetupConfig(handle)
- cfg.config.requirePath("nexus-fetch", "statement_log_directory")
}
diff --git a/nexus/src/test/kotlin/DatabaseTest.kt
b/nexus/src/test/kotlin/DatabaseTest.kt
index ed46598f..58fa9735 100644
--- a/nexus/src/test/kotlin/DatabaseTest.kt
+++ b/nexus/src/test/kotlin/DatabaseTest.kt
@@ -20,6 +20,7 @@
import kotlinx.coroutines.runBlocking
import org.junit.Test
import tech.libeufin.nexus.*
+import tech.libeufin.common.*
import java.time.Instant
import kotlin.random.Random
import kotlin.test.*
@@ -70,19 +71,19 @@ class IncomingPaymentsTest {
val payment = genInPay("incoming and bounced")
db.registerMalformedIncoming(
payment,
- TalerAmount(2, 53000000, "KUDOS"),
+ TalerAmount("KUDOS:2.53"),
Instant.now()
).run {
assertTrue(new)
}
db.registerMalformedIncoming(
payment,
- TalerAmount(2, 53000000, "KUDOS"),
+ TalerAmount("KUDOS:2.53"),
Instant.now()
).run {
assertFalse(new)
}
- db.runConn {
+ db.conn {
// Checking one incoming got created
val checkIncoming = it.prepareStatement("""
SELECT (amount).val as amount_value, (amount).frac as
amount_frac
@@ -90,7 +91,7 @@ class IncomingPaymentsTest {
""").executeQuery()
assertTrue(checkIncoming.next())
assertEquals(payment.amount.value,
checkIncoming.getLong("amount_value"))
- assertEquals(payment.amount.fraction,
checkIncoming.getInt("amount_frac"))
+ assertEquals(payment.amount.frac,
checkIncoming.getInt("amount_frac"))
// Checking the bounced table got its row.
val checkBounced = it.prepareStatement("""
SELECT 1 FROM bounced_transactions
@@ -150,7 +151,7 @@ class PaymentInitiationsTest {
assertFalse(db.initiatedPaymentSetFailureMessage(3, "3 not
existing"))
assertTrue(db.initiatedPaymentSetFailureMessage(1, "expired"))
// Checking the value from the database.
- db.runConn { conn ->
+ db.conn { conn ->
val idOne = conn.execSQLQuery("""
SELECT failure_message
FROM initiated_outgoing_transactions
@@ -178,7 +179,7 @@ class PaymentInitiationsTest {
db.initiatedPaymentCreate(genInitPay("not submitted, has row
ID == 1")),
)
// Asserting on the false default submitted state.
- db.runConn { conn ->
+ db.conn { conn ->
val isSubmitted = conn.execSQLQuery(getRowOne)
assertTrue(isSubmitted.next())
assertEquals("unsubmitted", isSubmitted.getString("submitted"))
@@ -186,7 +187,7 @@ class PaymentInitiationsTest {
// Switching the submitted state to success.
assertTrue(db.initiatedPaymentSetSubmittedState(1,
DatabaseSubmissionState.success))
// Asserting on the submitted state being TRUE now.
- db.runConn { conn ->
+ db.conn { conn ->
val isSubmitted = conn.execSQLQuery(getRowOne)
assertTrue(isSubmitted.next())
assertEquals("success", isSubmitted.getString("submitted"))
@@ -205,7 +206,7 @@ class PaymentInitiationsTest {
}
val initPay = InitiatedPayment(
amount = TalerAmount(44, 0, "KUDOS"),
- creditPaytoUri = "payto://iban/TEST-IBAN?receiver-name=Test",
+ creditPaytoUri =
IbanPayto("payto://iban/CH9300762011623852957?receiver-name=Test").requireFull(),
wireTransferSubject = "test",
requestUid = "unique",
initiationTime = Instant.now()
@@ -275,7 +276,7 @@ class PaymentInitiationsTest {
assertEquals(db.initiatedPaymentCreate(genInitPay("#4",
"unique4")), PaymentInitiationOutcome.SUCCESS)
// Marking one as submitted, hence not expecting it in the results.
- db.runConn { conn ->
+ db.conn { conn ->
conn.execSQLUpdate("""
UPDATE initiated_outgoing_transactions
SET submitted='success'
diff --git a/nexus/src/test/kotlin/Ebics.kt b/nexus/src/test/kotlin/Ebics.kt
index 44978095..5f3a3782 100644
--- a/nexus/src/test/kotlin/Ebics.kt
+++ b/nexus/src/test/kotlin/Ebics.kt
@@ -25,8 +25,8 @@ import org.junit.Ignore
import org.junit.Test
import tech.libeufin.nexus.*
import tech.libeufin.nexus.ebics.*
-import tech.libeufin.util.XMLUtil
-import tech.libeufin.util.ebics_h004.EbicsUnsecuredRequest
+import tech.libeufin.ebics.XMLUtil
+import tech.libeufin.ebics.ebics_h004.EbicsUnsecuredRequest
import java.io.File
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
diff --git a/nexus/src/test/kotlin/Keys.kt b/nexus/src/test/kotlin/Keys.kt
index 189de0db..41b6b11f 100644
--- a/nexus/src/test/kotlin/Keys.kt
+++ b/nexus/src/test/kotlin/Keys.kt
@@ -19,7 +19,7 @@
import org.junit.Test
import tech.libeufin.nexus.*
-import tech.libeufin.util.CryptoUtil
+import tech.libeufin.common.CryptoUtil
import java.io.File
import kotlin.test.*
diff --git a/nexus/src/test/kotlin/MySerializers.kt
b/nexus/src/test/kotlin/MySerializers.kt
index 0076dd55..2c109fd7 100644
--- a/nexus/src/test/kotlin/MySerializers.kt
+++ b/nexus/src/test/kotlin/MySerializers.kt
@@ -20,13 +20,13 @@
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import kotlinx.serialization.modules.SerializersModule
-import net.taler.wallet.crypto.Base32Crockford
import org.junit.Test
import tech.libeufin.nexus.ClientPrivateKeysFile
import tech.libeufin.nexus.RSAPrivateCrtKeySerializer
-import tech.libeufin.util.CryptoUtil
+import tech.libeufin.common.CryptoUtil
import java.security.interfaces.RSAPrivateCrtKey
import kotlin.test.assertEquals
+import tech.libeufin.common.*
class MySerializers {
// Testing deserialization of RSA private keys.
diff --git a/nexus/src/test/kotlin/Parsing.kt b/nexus/src/test/kotlin/Parsing.kt
index 4196f3cc..d71f42b2 100644
--- a/nexus/src/test/kotlin/Parsing.kt
+++ b/nexus/src/test/kotlin/Parsing.kt
@@ -20,8 +20,9 @@
import org.junit.Test
import org.junit.jupiter.api.assertThrows
import tech.libeufin.nexus.*
-import tech.libeufin.util.parseBookDate
-import tech.libeufin.util.parseCamtTime
+import tech.libeufin.common.*
+import tech.libeufin.common.parseBookDate
+import tech.libeufin.common.parseCamtTime
import java.lang.StringBuilder
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
@@ -30,18 +31,6 @@ import kotlin.test.assertTrue
class Parsing {
- @Test // move eventually to util (#7987)
- fun amountComparison() {
- val one = TalerAmount(1, 0, "KUDOS")
- val two = TalerAmount(2, 0, "KUDOS")
- val moreFrac = TalerAmount(2, 4, "KUDOS")
- val lessFrac = TalerAmount(2, 3, "KUDOS")
- val zeroMoreFrac = TalerAmount(0, 4, "KUDOS")
- val zeroLessFrac = TalerAmount(0, 3, "KUDOS")
- assertTrue(firstLessThanSecond(one, two))
- assertTrue(firstLessThanSecond(lessFrac, moreFrac))
- assertTrue(firstLessThanSecond(zeroLessFrac, zeroMoreFrac))
- }
@Test
fun gregorianTime() {
parseCamtTime("2023-11-06T20:00:00")
@@ -119,50 +108,6 @@ class Parsing {
getAmountNoCurrency(TalerAmount(0, 10000000, "KUDOS"))
)
}
- @Test // parses amounts as found in the camt.05x documents.
- fun parseCurrencyAgnosticAmount() {
- assertTrue {
- getTalerAmount("1.00", "KUDOS").run {
- this.value == 1L && this.fraction == 0 && this.currency ==
"KUDOS"
- }
- }
- assertTrue {
- getTalerAmount("1", "KUDOS").run {
- this.value == 1L && this.fraction == 0 && this.currency ==
"KUDOS"
- }
- }
- assertTrue {
- getTalerAmount("0.99", "KUDOS").run {
- this.value == 0L && this.fraction == 99000000 && this.currency
== "KUDOS"
- }
- }
- assertTrue {
- getTalerAmount("0.01", "KUDOS").run {
- this.value == 0L && this.fraction == 1000000 && this.currency
== "KUDOS"
- }
- }
- assertThrows<Exception> {
- getTalerAmount("", "")
- }
- assertThrows<Exception> {
- getTalerAmount(".1", "KUDOS")
- }
- assertThrows<Exception> {
- getTalerAmount("1.", "KUDOS")
- }
- assertThrows<Exception> {
- getTalerAmount("0.123", "KUDOS")
- }
- assertThrows<Exception> {
- getTalerAmount("noise", "KUDOS")
- }
- assertThrows<Exception> {
- getTalerAmount("1.noise", "KUDOS")
- }
- assertThrows<Exception> {
- getTalerAmount("5", "")
- }
- }
// Checks that the input decodes to a 32-bytes value.
@Test
diff --git a/settings.gradle b/settings.gradle
index b3b8fcad..48e088f8 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,5 +1,6 @@
rootProject.name = 'libeufin'
include("bank")
include("nexus")
-include("util")
-include("integration")
+include("common")
+include("testbench")
+include("ebics")
\ No newline at end of file
diff --git a/integration/build.gradle b/testbench/build.gradle
similarity index 86%
rename from integration/build.gradle
rename to testbench/build.gradle
index 7c366e4c..93fb6a46 100644
--- a/integration/build.gradle
+++ b/testbench/build.gradle
@@ -16,7 +16,7 @@ sourceSets.main.java.srcDirs = ["src/main/kotlin"]
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version")
- implementation(project(":util"))
+ implementation(project(":common"))
implementation(project(":bank"))
implementation(project(":nexus"))
@@ -30,8 +30,8 @@ dependencies {
}
application {
- mainClass = "tech.libeufin.integration.MainKt"
- applicationName = "libeufin-integration-test"
+ mainClass = "tech.libeufin.testbench.MainKt"
+ applicationName = "libeufin-testbench-test"
}
run {
diff --git a/integration/conf/integration.conf b/testbench/conf/integration.conf
similarity index 100%
rename from integration/conf/integration.conf
rename to testbench/conf/integration.conf
diff --git a/integration/conf/mini.conf b/testbench/conf/mini.conf
similarity index 100%
rename from integration/conf/mini.conf
rename to testbench/conf/mini.conf
diff --git a/integration/conf/netzbon.conf b/testbench/conf/netzbon.conf
similarity index 100%
rename from integration/conf/netzbon.conf
rename to testbench/conf/netzbon.conf
diff --git a/integration/conf/postfinance.conf b/testbench/conf/postfinance.conf
similarity index 100%
rename from integration/conf/postfinance.conf
rename to testbench/conf/postfinance.conf
diff --git a/integration/src/main/kotlin/Main.kt
b/testbench/src/main/kotlin/Main.kt
similarity index 92%
rename from integration/src/main/kotlin/Main.kt
rename to testbench/src/main/kotlin/Main.kt
index 854b8c45..fef935b9 100644
--- a/integration/src/main/kotlin/Main.kt
+++ b/testbench/src/main/kotlin/Main.kt
@@ -17,13 +17,12 @@
* <http://www.gnu.org/licenses/>
*/
-package tech.libeufin.integration
+package tech.libeufin.testbench
import tech.libeufin.nexus.Database as NexusDb
-import tech.libeufin.nexus.TalerAmount as NexusAmount
import tech.libeufin.nexus.*
import tech.libeufin.bank.*
-import tech.libeufin.util.*
+import tech.libeufin.common.*
import com.github.ajalt.clikt.core.*
import com.github.ajalt.clikt.parameters.arguments.*
import com.github.ajalt.clikt.parameters.types.*
@@ -36,7 +35,6 @@ import java.nio.file.*
import java.time.Instant
import kotlinx.coroutines.runBlocking
import io.ktor.client.request.*
-import net.taler.wallet.crypto.Base32Crockford
import kotlin.io.path.*
fun randBytes(lenght: Int): ByteArray {
@@ -125,7 +123,7 @@ class Cli : CliktCommand("Run integration tests on banks
provider") {
val payto =
"payto://iban/CH2989144971918294289?receiver-name=Test"
step("Test fetch transactions")
- nexusCmd.test("ebics-fetch $ebicsFlag --pinned-start
2022-01-01").assertOk()
+ nexusCmd.test("ebics-fetch $ebicsFlags --pinned-start
2022-01-01").assertOk()
while (true) {
when (ask("Run 'fetch', 'submit', 'tx', 'txs', 'logs',
'ack' or 'exit'>")) {
@@ -136,8 +134,8 @@ class Cli : CliktCommand("Run integration tests on banks
provider") {
"tx" -> {
step("Test submit one transaction")
nexusDb.initiatedPaymentCreate(InitiatedPayment(
- amount = NexusAmount(42L, 0, "CFH"),
- creditPaytoUri = payto,
+ amount = TalerAmount("CFH:42"),
+ creditPaytoUri =
IbanPayto(payto).requireFull(),
wireTransferSubject = "single transaction
test",
initiationTime = Instant.now(),
requestUid =
Base32Crockford.encode(randBytes(16))
@@ -148,8 +146,8 @@ class Cli : CliktCommand("Run integration tests on banks
provider") {
step("Test submit many transaction")
repeat(4) {
nexusDb.initiatedPaymentCreate(InitiatedPayment(
- amount = NexusAmount(100L + it, 0,
"CFH"),
- creditPaytoUri = payto,
+ amount = TalerAmount("CFH:${100L+it}"),
+ creditPaytoUri =
IbanPayto(payto).requireFull(),
wireTransferSubject = "multi
transaction test $it",
initiationTime = Instant.now(),
requestUid =
Base32Crockford.encode(randBytes(16))
@@ -199,8 +197,8 @@ class Cli : CliktCommand("Run integration tests on banks
provider") {
step("Submit new transaction")
// TODO interactive payment editor
nexusDb.initiatedPaymentCreate(InitiatedPayment(
- amount = getTalerAmount("1.1", "CFH"),
- creditPaytoUri =
"payto://iban/CH6208704048981247126?receiver-name=Grothoff%20Hans",
+ amount = TalerAmount("CFH:1.1"),
+ creditPaytoUri =
IbanPayto("payto://iban/CH6208704048981247126?receiver-name=Grothoff%20Hans").requireFull(),
wireTransferSubject = "single transaction
test",
initiationTime = Instant.now(),
requestUid =
Base32Crockford.encode(randBytes(16))
diff --git a/integration/src/test/kotlin/IntegrationTest.kt
b/testbench/src/test/kotlin/IntegrationTest.kt
similarity index 84%
rename from integration/src/test/kotlin/IntegrationTest.kt
rename to testbench/src/test/kotlin/IntegrationTest.kt
index a1fb79b6..dd4023aa 100644
--- a/integration/src/test/kotlin/IntegrationTest.kt
+++ b/testbench/src/test/kotlin/IntegrationTest.kt
@@ -18,14 +18,11 @@
*/
import org.junit.Test
-import net.taler.wallet.crypto.Base32Crockford
import tech.libeufin.bank.*
-import tech.libeufin.bank.TalerAmount as BankAmount
import tech.libeufin.nexus.*
import tech.libeufin.nexus.Database as NexusDb
-import tech.libeufin.nexus.TalerAmount as NexusAmount
import tech.libeufin.bank.db.AccountDAO.*
-import tech.libeufin.util.*
+import tech.libeufin.common.*
import java.io.File
import java.time.Instant
import java.util.Arrays
@@ -104,12 +101,13 @@ class IntegrationTest {
@Test
fun mini() {
- bankCmd.run("dbinit -c conf/mini.conf -r")
- bankCmd.run("passwd admin password -c conf/mini.conf")
- bankCmd.run("dbinit -c conf/mini.conf") // Indempotent
+ val flags = "-c conf/mini.conf -L DEBUG"
+ bankCmd.run("dbinit $flags -r")
+ bankCmd.run("passwd admin password $flags")
+ bankCmd.run("dbinit $flags") // Indempotent
server {
- bankCmd.run("serve -c conf/mini.conf")
+ bankCmd.run("serve $flags")
}
setup { _ ->
@@ -120,12 +118,13 @@ class IntegrationTest {
@Test
fun errors() {
- nexusCmd.run("dbinit -c conf/integration.conf -r")
- bankCmd.run("dbinit -c conf/integration.conf -r")
- bankCmd.run("passwd admin password -c conf/integration.conf")
+ val flags = "-c conf/integration.conf -L DEBUG"
+ nexusCmd.run("dbinit $flags -r")
+ bankCmd.run("dbinit $flags -r")
+ bankCmd.run("passwd admin password $flags")
suspend fun checkCount(db: NexusDb, nbIncoming: Int, nbBounce: Int,
nbTalerable: Int) {
- db.runConn { conn ->
+ db.conn { conn ->
conn.prepareStatement("SELECT count(*) FROM
incoming_transactions").oneOrNull {
assertEquals(nbIncoming, it.getInt(1))
}
@@ -139,19 +138,19 @@ class IntegrationTest {
}
setup { db ->
- val userPayTo = IbanPayTo(genIbanPaytoUri())
- val fiatPayTo = IbanPayTo(genIbanPaytoUri())
+ val userPayTo = IbanPayto(genIbanPaytoUri())
+ val fiatPayTo = IbanPayto(genIbanPaytoUri())
// Load conversion setup manually as the server would refuse to
start without an exchange account
val sqlProcedures =
File("../database-versioning/libeufin-conversion-setup.sql")
- db.runConn {
+ db.conn {
it.execSQLUpdate(sqlProcedures.readText())
it.execSQLUpdate("SET search_path TO libeufin_nexus;")
}
val reservePub = randBytes(32)
val payment = IncomingPayment(
- amount = NexusAmount(10, 0, "EUR"),
+ amount = TalerAmount("EUR:10"),
debitPaytoUri = userPayTo.canonical,
wireTransferSubject = "Error test
${Base32Crockford.encode(reservePub)}",
executionTime = Instant.now(),
@@ -163,7 +162,7 @@ class IntegrationTest {
}
// Create exchange account
- bankCmd.run("create-account -c conf/integration.conf -u exchange
-p password --name 'Mr Money' --exchange")
+ bankCmd.run("create-account $flags -u exchange -p password --name
'Mr Money' --exchange")
assertException("ERROR: cashin currency conversion failed: missing
conversion rates") {
ingestIncomingPayment(db, payment)
@@ -171,7 +170,7 @@ class IntegrationTest {
// Start server
server {
- bankCmd.run("serve -c conf/integration.conf")
+ bankCmd.run("serve $flags")
}
// Set conversion rates
@@ -196,12 +195,12 @@ class IntegrationTest {
}
// Allow admin debt
- bankCmd.run("edit-account admin --debit_threshold KUDOS:100 -c
conf/integration.conf")
+ bankCmd.run("edit-account admin --debit_threshold KUDOS:100
$flags")
// Too small amount
checkCount(db, 0, 0, 0)
ingestIncomingPayment(db, payment.copy(
- amount = NexusAmount(0, 10, "EUR"),
+ amount = TalerAmount("EUR:0.01"),
))
checkCount(db, 1, 1, 0)
client.get("http://0.0.0.0:8080/accounts/exchange/transactions") {
@@ -210,7 +209,7 @@ class IntegrationTest {
// Check success
ingestIncomingPayment(db, IncomingPayment(
- amount = NexusAmount(10, 0, "EUR"),
+ amount = TalerAmount("EUR:10"),
debitPaytoUri = userPayTo.canonical,
wireTransferSubject = "Success
${Base32Crockford.encode(randBytes(32))}",
executionTime = Instant.now(),
@@ -227,21 +226,22 @@ class IntegrationTest {
@Test
fun conversion() {
- nexusCmd.run("dbinit -c conf/integration.conf -r")
- bankCmd.run("dbinit -c conf/integration.conf -r")
- bankCmd.run("passwd admin password -c conf/integration.conf")
- bankCmd.run("edit-account admin --debit_threshold KUDOS:1000 -c
conf/integration.conf")
- bankCmd.run("create-account -c conf/integration.conf -u exchange -p
password --name 'Mr Money' --exchange")
- nexusCmd.run("dbinit -c conf/integration.conf") // Idempotent
- bankCmd.run("dbinit -c conf/integration.conf") // Idempotent
+ val flags = "-c conf/integration.conf -L DEBUG"
+ nexusCmd.run("dbinit $flags -r")
+ bankCmd.run("dbinit $flags -r")
+ bankCmd.run("passwd admin password $flags")
+ bankCmd.run("edit-account admin --debit_threshold KUDOS:1000 $flags")
+ bankCmd.run("create-account $flags -u exchange -p password --name 'Mr
Money' --exchange")
+ nexusCmd.run("dbinit $flags") // Idempotent
+ bankCmd.run("dbinit $flags") // Idempotent
server {
- bankCmd.run("serve -c conf/integration.conf")
+ bankCmd.run("serve $flags")
}
setup { db ->
- val userPayTo = IbanPayTo(genIbanPaytoUri())
- val fiatPayTo = IbanPayTo(genIbanPaytoUri())
+ val userPayTo = IbanPayto(genIbanPaytoUri())
+ val fiatPayTo = IbanPayto(genIbanPaytoUri())
// Create user
client.post("http://0.0.0.0:8080/accounts") {
@@ -279,7 +279,7 @@ class IntegrationTest {
// Cashin
repeat(3) { i ->
val reservePub = randBytes(32);
- val amount = NexusAmount(20L + i, 0, "EUR")
+ val amount = TalerAmount("EUR:${20+i}")
val subject = "cashin test $i:
${Base32Crockford.encode(reservePub)}"
ingestIncomingPayment(db,
IncomingPayment(
@@ -311,7 +311,7 @@ class IntegrationTest {
// Cashout
repeat(3) { i ->
val requestUid = randBytes(32);
- val amount = BankAmount("KUDOS:${10+i}")
+ val amount = TalerAmount("KUDOS:${10+i}")
val convert =
client.get("http://0.0.0.0:8080/conversion-info/cashout-rate?amount_debit=$amount")
.assertOkJson<ConversionResponse>().amount_credit;
client.post("http://0.0.0.0:8080/accounts/customer/cashouts") {
diff --git a/util/src/main/kotlin/IbanPayto.kt
b/util/src/main/kotlin/IbanPayto.kt
deleted file mode 100644
index b1712258..00000000
--- a/util/src/main/kotlin/IbanPayto.kt
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * This file is part of LibEuFin.
- * Copyright (C) 2024 Taler Systems S.A.
-
- * LibEuFin is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation; either version 3, or
- * (at your option) any later version.
-
- * LibEuFin 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 LibEuFin; see the file COPYING. If not, see
- * <http://www.gnu.org/licenses/>
- */
-
-package tech.libeufin.util
-
-import org.slf4j.Logger
-import org.slf4j.LoggerFactory
-import java.net.URI
-import java.net.URLDecoder
-
-private val logger: Logger = LoggerFactory.getLogger("libeufin-common")
-
-// Payto information.
-data class IbanPayto(
- // represent query param "sender-name" or "receiver-name".
- val receiverName: String?,
- val iban: String,
- val bic: String?,
- // Typically, a wire transfer's subject.
- val message: String?,
- val amount: String?
-)
-
-// Return the value of query string parameter 'name', or null if not found.
-// 'params' is the list of key-value elements of all the query parameters
found in the URI.
-private fun getQueryParamOrNull(name: String, params: List<Pair<String,
String>>?): String? {
- if (params == null) return null
- return params.firstNotNullOfOrNull { pair ->
- URLDecoder.decode(pair.second, Charsets.UTF_8).takeIf { pair.first ==
name }
- }
-}
-
-// Parses a Payto URI, returning null if the input is invalid.
-fun parsePayto(payto: String): IbanPayto? {
- /**
- * This check is due because URIs having a "payto:" prefix without
- * slashes are correctly parsed by the Java 'URI' class. 'mailto'
- * for example lacks the double-slash part.
- */
- if (!payto.startsWith("payto://")) {
- logger.error("Invalid payto URI: $payto")
- return null
- }
-
- val javaParsedUri = try {
- URI(payto)
- } catch (e: java.lang.Exception) {
- logger.error("'${payto}' is not a valid URI")
- return null
- }
- if (javaParsedUri.scheme != "payto") {
- logger.error("'${payto}' is not payto")
- return null
- }
- val wireMethod = javaParsedUri.host
- if (wireMethod != "iban") {
- logger.error("Only 'iban' is supported, not '$wireMethod'")
- return null
- }
- val splitPath = javaParsedUri.path.split("/").filter { it.isNotEmpty() }
- if (splitPath.size > 2) {
- logger.error("too many path segments in iban payto URI: $payto")
- return null
- }
- val (iban, bic) = if (splitPath.size == 1) {
- Pair(splitPath[0], null)
- } else Pair(splitPath[1], splitPath[0])
-
- val params: List<Pair<String, String>>? = if (javaParsedUri.query != null)
{
- val queryString: List<String> = javaParsedUri.query.split("&")
- queryString.map {
- val split = it.split("=");
- if (split.size != 2) {
- logger.error("parameter '$it' was malformed")
- return null
- }
- Pair(split[0], split[1])
- }
- } else null
-
- return IbanPayto(
- iban = iban,
- bic = bic,
- amount = getQueryParamOrNull("amount", params),
- message = getQueryParamOrNull("message", params),
- receiverName = getQueryParamOrNull("receiver-name", params)
- )
-}
\ No newline at end of file
diff --git a/util/src/test/kotlin/PaytoTest.kt
b/util/src/test/kotlin/PaytoTest.kt
deleted file mode 100644
index ff075b58..00000000
--- a/util/src/test/kotlin/PaytoTest.kt
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * This file is part of LibEuFin.
- * Copyright (C) 2024 Taler Systems S.A.
-
- * LibEuFin is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation; either version 3, or
- * (at your option) any later version.
-
- * LibEuFin 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 LibEuFin; see the file COPYING. If not, see
- * <http://www.gnu.org/licenses/>
- */
-
-import org.junit.Test
-import tech.libeufin.util.IbanPayto
-import tech.libeufin.util.parsePayto
-
-class PaytoTest {
-
- @Test
- fun wrongCases() {
-
assert(parsePayto("http://iban/BIC123/IBAN123?receiver-name=The%20Name") ==
null)
-
assert(parsePayto("payto:iban/BIC123/IBAN123?receiver-name=The%20Name&address=house")
== null)
-
assert(parsePayto("payto://wrong/BIC123/IBAN123?sender-name=Foo&receiver-name=Foo")
== null)
- }
-
- @Test
- fun parsePaytoTest() {
- val withBic: IbanPayto =
parsePayto("payto://iban/BIC123/IBAN123?receiver-name=The%20Name")!!
- assert(withBic.iban == "IBAN123")
- assert(withBic.bic == "BIC123")
- assert(withBic.receiverName == "The Name")
- val complete =
parsePayto("payto://iban/BIC123/IBAN123?sender-name=The%20Name&amount=EUR:1&message=donation")!!
- assert(withBic.iban == "IBAN123")
- assert(withBic.bic == "BIC123")
- assert(withBic.receiverName == "The Name")
- assert(complete.message == "donation")
- assert(complete.amount == "EUR:1")
- val withoutOptionals = parsePayto("payto://iban/IBAN123")!!
- assert(withoutOptionals.bic == null)
- assert(withoutOptionals.message == null)
- assert(withoutOptionals.receiverName == null)
- assert(withoutOptionals.amount == null)
- }
-}
\ No newline at end of file
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [libeufin] branch master updated (ad7171c9 -> 51300a1a),
gnunet <=