[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libeufin] branch master updated: mandatory, stringified bank transactio
From: |
gnunet |
Subject: |
[libeufin] branch master updated: mandatory, stringified bank transaction code, even for GBIC rulebook |
Date: |
Tue, 07 Jul 2020 11:11:12 +0200 |
This is an automated email from the git hooks/post-receive script.
dold pushed a commit to branch master
in repository libeufin.
The following commit(s) were added to refs/heads/master by this push:
new f801adf mandatory, stringified bank transaction code, even for GBIC
rulebook
f801adf is described below
commit f801adf2769c29b65a67d6a9f626617c597bd611
Author: Florian Dold <florian.dold@gmail.com>
AuthorDate: Tue Jul 7 14:41:05 2020 +0530
mandatory, stringified bank transaction code, even for GBIC rulebook
---
.../tech/libeufin/nexus/iso20022/GbicRules.kt | 285 +++++++++++++++++++++
.../tech/libeufin/nexus/iso20022/Iso20022.kt | 55 ++--
nexus/src/test/kotlin/Iso20022Test.kt | 6 +-
3 files changed, 318 insertions(+), 28 deletions(-)
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/GbicRules.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/GbicRules.kt
new file mode 100644
index 0000000..df6fc4a
--- /dev/null
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/GbicRules.kt
@@ -0,0 +1,285 @@
+/*
+ * This file is part of LibEuFin.
+ * Copyright (C) 2020 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.nexus.iso20022
+
+/**
+ * Extra rules for German Banking Industry Committee (GBIC) for ISO 20022.
+ */
+object GbicRules {
+ /**
+ * Map credit/debit indicator and the German GVC code to a ISO 20022 bank
transaction code.
+ * When multiple alternatives are available, we always choose the least
specific one.
+ *
+ * Mapping taken from "Anhang1 zu Anlage 3 - Datenformatstandards-Version
3.3 Final Version-2019-04-11"
+ */
+ @Suppress("SpellCheckingInspection")
+ fun getBtcFromGvc(c: CreditDebitIndicator, s: String): String {
+ val cd = when (c) {
+ CreditDebitIndicator.CRDT -> "C"
+ CreditDebitIndicator.DBIT -> "D"
+ }
+ return when ("${cd}-${s}") {
+ "D-006" -> "PMNT-CCRD-POSC"
+ "C-058" -> "PMNT-RCDT-FICT"
+ "C-072" -> "PMNT-DRFT-STLR"
+ "D-073" -> "PMNT-DRFT-STAM"
+ "C-079" -> "PMNT-MCOP-OTHR"
+ "D-079" -> "PMNT-MDOP-OTHR"
+ "C-082" -> "PMNT-CNTR-CDPT"
+ "D-083" -> "PMNT-CNTR-CWDL"
+ "D-084" -> "PMNT-RDDT-OODD"
+ "D-087" -> "PMNT-ICDT-SDVA"
+ "C-088" -> "PMNT-RCDT-SDVA"
+ "C-093" -> "PMNT-DRFT-DDFT"
+ "C-095" -> "TRAD-GUAR-OTHR"
+ "D-095" -> "TRAD-GUAR-OTHR"
+ "C-098" -> "PMNT-MCRD-SMCD"
+ "D-101" -> "PMNT-ICHQ-CCHQ"
+ "D-102" -> "PMNT-ICHQ-ORCQ"
+ "D-103" -> "PMNT-ICHQ-CCHQ"
+ "D-104" -> "PMNT-RDDT-BBDD"
+ "D-105" -> "PMNT-RDDT-ESDD"
+ // Alternatives:
+ // "D-106" -> "PMNT-CCRD-CWDL"
+ // "D-106" -> "PMNT-CCRD-SMRT"
+ // "D-106" -> "PMNT-CCRD-POSD"
+ // "D-106" -> "PMNT-MCRD-CHRG"
+ "D-106" -> "PMNT-CCRD-OTHR"
+ "D-107" -> "PMNT-CCRD-OTHR"
+ "D-108" -> "PMNT-IDDT-UPDD"
+ "D-109" -> "PMNT-IDDT-UPDD"
+ "D-110" -> "PMNT-MCRD-UPCT"
+ "D-111" -> "PMNT-ICHQ-UPCQ"
+ "D-112" -> "PMNT-ICHQ-OTHR"
+ "C-112" -> "PMNT-RCHQ-OTHR"
+ "D-116" -> "PMNT-ICDT-ESCT"
+ "D-118" -> "PMNT-IRCT-ESCT"
+ "D-117" -> "PMNT-ICDT-STDO"
+ "D-119" -> "PMNT-ICDT-ESCT"
+ "D-122" -> "PMNT-ICHQ-CCHQ"
+ "C-152" -> "PMNT-RCDT-STDO"
+ "C-153" -> "PMNT-RCDT-SALA"
+ "C-154" -> "PMNT-RCDT-ESCT"
+ "C-155" -> "PMNT-RCDT-ESCT"
+ "C-156" -> "PMNT-RCDT-ESCT"
+ "C-157" -> "PMNT-RRCT-SALA"
+ "C-159" -> "PMNT-ICDT-RRTN"
+ "D-159" -> "PMNT-RCDT-RRTN"
+ "C-160" -> "PMNT-IRCT-RRTN"
+ "D-160" -> "PMNT-RRCT-RRTN"
+ "C-161" -> "PMNT-RRCT-ESCT"
+ "C-162" -> "PMNT-RRCT-ESCT"
+ "C-163" -> "PMNT-RRCT-ESCT"
+ "C-164" -> "PMNT-RRCT-ESCT"
+ "C-165" -> "PMNT-RRCT-ESCT"
+ "C-166" -> "PMNT-RCDT-ESCT"
+ "C-167" -> "PMNT-RCDT-ESCT"
+ "C-168" -> "PMNT-RRCT-ESCT"
+ "C-169" -> "PMNT-RCDT-ESCT"
+ "C-170" -> "PMNT-RCHQ-URCQ"
+ "C-171" -> "PMNT-IDDT-ESDD"
+ "C-174" -> "PMNT-IDDT-BBDD"
+ "D-177" -> "PMNT-ICDT-ESCT"
+ "C-181" -> "PMNT-RDDT-UPDD"
+ "C-182" -> "PMNT-CCRD-RIMB"
+ "C-183" -> "PMNT-RCHQ-UPCQ"
+ "C-184" -> "PMNT-RDDT-UPDD"
+ "D-185" -> "PMNT-ICHQ-CCHQ"
+ "D-188" -> "PMNT-IRCT-ESCT"
+ "C-189" -> "PMNT-RRCT-ESCT"
+ "D-190" -> "PMNT-CCRD-OTHR"
+ "D-191" -> "PMNT-ICDT-ESCT"
+ "C-192" -> "PMNT-IDDT-ESDD"
+ "D-193" -> "PMNT-IDDT-RCDD"
+ "C-194" -> "PMNT-RCDT-ESCT"
+ "D-195" -> "PMNT-RDDT-ESDD"
+ "C-196" -> "PMNT-IDDT-BBDD"
+ "D-197" -> "PMNT-RDDT-BBDD"
+ "C-198" -> "PMNT-MCRD-POSP"
+ "D-199" -> "PMNT-MCRD-DAJT"
+ "D-201" -> "PMNT-ICDT-XBCT"
+ "C-202" -> "PMNT-RCDT-XBCT"
+ "C-203" -> "TRAD-CLNC-OTHR"
+ "D-203" -> "TRAD-CLNC-OTHR"
+ "C-204" -> "TRAD-DCCT-OTHR"
+ "D-204" -> "TRAD-DCCT-OTHR"
+ "C-205" -> "TRAD-GUAR-OTHR"
+ "D-205" -> "TRAD-GUAR-OTHR"
+ "C-206" -> "PMNT-RCDT-XBCT"
+ "C-208" -> "TRAD-MCOP-OTHR"
+ "D-208" -> "TRAD-MDOP-OTHR"
+ "D-209" -> "PMNT-ICHQ-XBCQ"
+ "D-210" -> "PMNT-ICDT-XBCT"
+ "C-211" -> "PMNT-RCDT-XBCT"
+ "D-212" -> "PMNT-ICDT-XBST"
+ "D-213" -> "PMNT-RDDT-XBDD"
+ "D-214" -> "TRAD-DOCC-OTHR"
+ "C-215" -> "TRAD-DOCC-OTHR"
+ "D-216" -> "PMNT-DRFT-STAM"
+ "C-217" -> "PMNT-DRFT-STAM"
+ // Alternative:
+ // "C-217" -> "PMNT-DRFT-STLR"
+ "D-218" -> "TRAD-DCCT-OTHR"
+ "C-219" -> "TRAD-DCCT-OTHR"
+ "C-220" -> "PMNT-RCHQ-XRCQ"
+ "C-221" -> "PMNT-RCHQ-XBCQ"
+ "D-222" -> "PMNT-ICHQ-XBCQ"
+ "D-223" -> "PMNT-ICHQ-XBCQ"
+ "C-224" -> "PMNT-CNTR-FCDP"
+ "D-225" -> "PMNT-CNTR-FCWD"
+ "C-301" -> "SECU-CUST-REDM"
+ "C-302" -> "SECU-CUST-DVCA"
+ "C-303" -> "SECU-SETT-TRAD"
+ "D-303" -> "SECU-SETT-TRAD"
+ "C-304" -> "SECU-OTHR-OTHR"
+ "D-304" -> "SECU-OTHR-OTHR"
+ "D-305" -> "SECU-OTHR-OTHR"
+ "D-306" -> "SECU-OTHR-OTHR"
+ "D-307" -> "SECU-SETT-SUBS"
+ "C-308" -> "SECU-CORP-EXWA"
+ "D-308" -> "SECU-CORP-EXWA"
+ "C-309" -> "SECU-CORP-BONU"
+ "D-309" -> "SECU-CORP-BONU"
+ "C-310" -> "SECU-MCOP-OTHR"
+ "D-310" -> "SECU-MDOP-OTHR"
+ "C-311" -> "DERV-OTHR-OTHR"
+ "D-311" -> "DERV-OTHR-OTHR"
+ "D-320" -> "SECU-CASH-TRFE"
+ "D-321" -> "SECU-CUST-CHRG"
+ "C-321" -> "SECU-CUST-CHRG"
+ "C-330" -> "SECU-CUST-INTR"
+ "C-340" -> "SECU-CUST-REDM"
+ "C-399" -> "ACMT-ACOP-PSTE"
+ "D-399" -> "ACMT-ADOP-PSTE"
+ "C-401" -> "FORX-SPOT-OTHR"
+ "D-401" -> "FORX-SPOT-OTHR"
+ "C-402" -> "FORX-FWRD-OTHR"
+ "D-402" -> "FORX-FWRD-OTHR"
+ "D-403" -> "FORX-MDOP-OTHR"
+ "D-404" -> "FORX-OTHR-OTHR"
+ "D-405" -> "FORX-OTHR-OTHR"
+ "C-406" -> "FORX-SPOT-OTHR"
+ "D-406" -> "FORX-SPOT-OTHR"
+ "C-407" -> "FORX-OTHR-OTHR"
+ "D-407" -> "FORX-OTHR-OTHR"
+ "C-408" -> "FORX-OTHR-OTHR"
+ "C-409" -> "FORX-OTHR-OTHR"
+ "D-411" -> "FORX-SPOT-OTHR"
+ "C-412" -> "FORX-SPOT-OTHR"
+ "D-413" -> "FORX-FWRD-OTHR"
+ "C-414" -> "FORX-FWRD-OTHR"
+ "D-415" -> "FORX-OTHR-OTHR"
+ "C-416" -> "FORX-OTHR-OTHR"
+ "D-417" -> "FORX-OTHR-OTHR"
+ "C-418" -> "FORX-OTHR-OTHR"
+ "D-419" -> "FORX-OTHR-OTHR"
+ "C-420" -> "FORX-OTHR-OTHR"
+ "C-421" -> "FORX-OTHR-OTHR"
+ "D-421" -> "FORX-OTHR-OTHR"
+ "C-422" -> "FORX-SWAP-OTHR"
+ "D-422" -> "FORX-SWAP-OTHR"
+ "C-423" -> "PMET-SPOT-OTHR"
+ "D-424" -> "PMET-SPOT-OTHR"
+ "D-601" -> "LDAS-FTLN-OTHR"
+ "C-602" -> "LDAS-FTLN-OTHR"
+ "D-603" -> "LDAS-FTLN-PPAY"
+ "D-604" -> "LDAS-MDOP-INTR"
+ "D-605" -> "LDAS-MDOP-INTR"
+ "C-606" -> "LDAS-FTLN-DDWN"
+ "D-606" -> "LDAS-FTLN-DDWN"
+ "D-607" -> "LDAS-OTHR-OTHR"
+ "D-801" -> "ACMT-MDOP-CHRG"
+ "D-802" -> "ACMT-MDOP-CHRG"
+ "D-803" -> "SECU-CUST-CHRG"
+ "D-804" -> "PMNT-MDOP-CHRG"
+ "C-804" -> "PMNT-MCOP-CHRG"
+ "C-805" -> "ACMT-OPCL-ACCC"
+ "D-805" -> "ACMT-OPCL-ACCC"
+ "C-806" -> "ACMT-MCOP-CHRG"
+ "D-806" -> "ACMT-MDOP-CHRG"
+ "C-807" -> "ACMT-MCOP-CHRG"
+ "D-807" -> "ACMT-MDOP-CHRG"
+ "C-808" -> "PMNT-MCOP-CHRG"
+ "D-808" -> "PMNT-MDOP-CHRG"
+ // Alternatives:
+ // "C-808" -> "TRAD-MCOP-CHRG"
+ // "D-808" -> "TRAD-MDOP-CHRG"
+ // "C-808" -> "ACMT-MCOP-CHRG"
+ // "D-808" -> "ACMT-MDOP-CHRG"
+ "D-809" -> "PMNT-MDOP-COMM"
+ "C-809" -> "PMNT-MCOP-COMM"
+ // Alternatives:
+ // "D-809" -> "ACMT-MDOP-COMM"
+ // "C-809" -> "ACMT-MCOP-COMM"
+ // "D-809" -> "TRAD-MDOP-COMM"
+ // "C-809" -> "TRAD-MCOP-COMM"
+ // "D-809" -> "LDAS-MDOP-COMM"
+ // "C-809" -> "LDAS-MCOP-COMM"
+ "D-810" -> "ACMT-MDOP-CHRG"
+ "C-810" -> "ACMT-MCOP-CHRG"
+ "D-811" -> "LDAS-MDOP-CHRG"
+ "C-811" -> "LDAS-MCOP-CHRG"
+ "D-812" -> "LDAS-MDOP-INTR"
+ "C-812" -> "LDAS-MCOP-INTR"
+ "D-813" -> "LDAS-MDOP-INTR"
+ "C-814" -> "ACMT-MCOP-INTR"
+ "D-814" -> "ACMT-MDOP-INTR"
+ "C-815" -> "ACMT-OTHR-OTHR"
+ "C-816" -> "ACMT-OTHR-OTHR"
+ "C-817" -> "ACMT-OTHR-OTHR"
+ "D-818" -> "PMNT-OTHR-OTHR"
+ "C-819" -> "PMNT-OTHR-OTHR"
+ "C-820" -> "PMNT-RCDT-BOOK"
+ "D-820" -> "PMNT-ICDT-BOOK"
+ "D-821" -> "PMNT-OTHR-OTHR"
+ "C-822" -> "PMNT-OTHR-OTHR"
+ "C-823" -> "LDAS-FTDP-RPMT"
+ "D-823" -> "LDAS-FTDP-DPST"
+ "D-824" -> "LDAS-OTHR-OTHR"
+ "D-825" -> "LDAS-OTHR-OTHR"
+ "D-826" -> "LDAS-OTHR-OTHR"
+ "D-827" -> "LDAS-OTHR-OTHR"
+ "C-828" -> "LDAS-FTDP-RPMT"
+ "D-828" -> "LDAS-FTDP-DPST"
+ "C-829" -> "LDAS-FTDP-RPMT"
+ "D-829" -> "LDAS-FTDP-DPST"
+ "C-830" -> "LDAS-FTDP-INTR"
+ "D-831" -> "XTND-NTAV-NTAV"
+ "D-832" -> "LDAS-OTHR-OTHR"
+ "C-833" -> "CAMT-ACCB-OTHR"
+ "D-833" -> "CAMT-ACCB-OTHR"
+ "C-834" -> "CAMT-ACCB-OTHR"
+ "D-834" -> "CAMT-ACCB-OTHR"
+ "C-835" -> "XTND-NTAV-NTAV"
+ "D-835" -> "XTND-NTAV-NTAV"
+ "C-836" -> "ACMT-MCOP-ADJT"
+ "D-836" -> "ACMT-MDOP-ADJT"
+ "D-837" -> "ACMT-MDOP-TAXE"
+ "C-888" -> "XTND-NTAV-NTAV"
+ "D-888" -> "XTND-NTAV-NTAV"
+ "C-899" -> "ACMT-ACOP-PSTE"
+ "D-899" -> "ACMT-ADOP-PSTE"
+ "D-997" -> "XTND-NTAV-NTAV"
+ "C-999" -> "XTND-NTAV-NTAV"
+ "D-999" -> "XTND-NTAV-NTAV"
+ else -> "XTND-NTAV-NTAV"
+ }
+ }
+}
\ No newline at end of file
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/Iso20022.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/Iso20022.kt
index 556bb6b..2a9fda8 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/Iso20022.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/Iso20022.kt
@@ -186,7 +186,7 @@ data class TransactionInfo(
@JsonInclude(JsonInclude.Include.NON_NULL)
data class ReturnInfo(
- val originalBankTransactionCode: BankTransactionCode?,
+ val originalBankTransactionCode: String?,
val originator: PartyIdentification?,
val reason: String?,
val proprietaryReason: String?,
@@ -213,7 +213,7 @@ data class CamtBankAccountEntry(
* in more detail
*/
- val bankTransactionCode: BankTransactionCode,
+ val bankTransactionCode: String,
/**
* Transaction details, if this entry contains a single transaction.
*/
@@ -224,14 +224,6 @@ data class CamtBankAccountEntry(
val entryRef: String?
)
-@JsonInclude(JsonInclude.Include.NON_NULL)
-data class BankTransactionCode(
- val domain: String?,
- val family: String?,
- val subfamily: String?,
- val proprietaryCode: String?,
- val proprietaryIssuer: String?
-)
class CamtParsingError(msg: String) : Exception(msg)
@@ -587,7 +579,11 @@ private fun XmlElementDestructor.extractTransactionInfos(
returnInfo = maybeUniqueChildNamed("RtrInf") {
ReturnInfo(
originalBankTransactionCode =
maybeUniqueChildNamed("OrgnlBkTxCd") {
- extractInnerBkTxCd()
+ extractInnerBkTxCd(
+ when (creditDebitIndicator) {
+ CreditDebitIndicator.DBIT ->
CreditDebitIndicator.CRDT
+ CreditDebitIndicator.CRDT ->
CreditDebitIndicator.DBIT
+ })
},
originator = maybeUniqueChildNamed("Orgtr") {
extractParty() },
reason = maybeUniqueChildNamed("Rsn") {
maybeUniqueChildNamed("Cd") { it.textContent } },
@@ -600,26 +596,39 @@ private fun XmlElementDestructor.extractTransactionInfos(
}
}
-private fun XmlElementDestructor.extractInnerBkTxCd(): BankTransactionCode {
- return BankTransactionCode(
- domain = maybeUniqueChildNamed("Domn") { maybeUniqueChildNamed("Cd") {
it.textContent } },
- family = maybeUniqueChildNamed("Domn") {
+private fun XmlElementDestructor.extractInnerBkTxCd(creditDebitIndicator:
CreditDebitIndicator): String {
+
+ val domain = maybeUniqueChildNamed("Domn") { maybeUniqueChildNamed("Cd") {
it.textContent } }
+ val family = maybeUniqueChildNamed("Domn") {
maybeUniqueChildNamed("Fmly") {
maybeUniqueChildNamed("Cd") { it.textContent }
}
- },
- subfamily = maybeUniqueChildNamed("Domn") {
+ }
+ val subfamily = maybeUniqueChildNamed("Domn") {
maybeUniqueChildNamed("Fmly") {
maybeUniqueChildNamed("SubFmlyCd") { it.textContent }
}
- },
- proprietaryCode = maybeUniqueChildNamed("Prtry") {
+ }
+ val proprietaryCode = maybeUniqueChildNamed("Prtry") {
maybeUniqueChildNamed("Cd") { it.textContent }
- },
- proprietaryIssuer = maybeUniqueChildNamed("Prtry") {
+ }
+ val proprietaryIssuer = maybeUniqueChildNamed("Prtry") {
maybeUniqueChildNamed("Issr") { it.textContent }
}
- )
+
+ if (domain != null && family != null && subfamily != null) {
+ return "$domain-$family-$subfamily"
+ }
+ if (proprietaryIssuer == "DK" && proprietaryCode != null) {
+ val components = proprietaryCode.split("+")
+ if (components.size == 1) {
+ return GbicRules.getBtcFromGvc(creditDebitIndicator, components[0])
+ } else {
+ return GbicRules.getBtcFromGvc(creditDebitIndicator, components[1])
+ }
+ }
+ // FIXME: log/raise this somewhere?
+ return "XTND-NTAV-NTAV"
}
private fun XmlElementDestructor.extractInnerTransactions(): CamtReport {
@@ -633,7 +642,7 @@ private fun
XmlElementDestructor.extractInnerTransactions(): CamtReport {
CreditDebitIndicator.valueOf(it)
}
val btc = requireUniqueChildNamed("BkTxCd") {
- extractInnerBkTxCd()
+ extractInnerBkTxCd(creditDebitIndicator)
}
val acctSvcrRef = maybeUniqueChildNamed("AcctSvcrRef") {
it.textContent }
val entryRef = maybeUniqueChildNamed("NtryRef") { it.textContent }
diff --git a/nexus/src/test/kotlin/Iso20022Test.kt
b/nexus/src/test/kotlin/Iso20022Test.kt
index 2477950..78c2f14 100644
--- a/nexus/src/test/kotlin/Iso20022Test.kt
+++ b/nexus/src/test/kotlin/Iso20022Test.kt
@@ -34,11 +34,7 @@ class Iso20022Test {
assertEquals(EntryStatus.BOOK, r.reports[0].entries[0].status)
assertEquals(null, r.reports[0].entries[0].entryRef)
assertEquals("acctsvcrref-001",
r.reports[0].entries[0].accountServicerRef)
- assertEquals("PMNT",
r.reports[0].entries[0].bankTransactionCode.domain)
- assertEquals("RCDT",
r.reports[0].entries[0].bankTransactionCode.family)
- assertEquals("ESCT",
r.reports[0].entries[0].bankTransactionCode.subfamily)
- assertEquals("166",
r.reports[0].entries[0].bankTransactionCode.proprietaryCode)
- assertEquals("DK",
r.reports[0].entries[0].bankTransactionCode.proprietaryIssuer)
+ assertEquals("PMNT-RCDT-ESCT",
r.reports[0].entries[0].bankTransactionCode)
assertEquals(1, r.reports[0].entries[0].transactionInfos.size)
assertEquals("EUR",
r.reports[0].entries[0].transactionInfos[0].amount.currency)
assertTrue(BigDecimal(100).compareTo(r.reports[0].entries[0].transactionInfos[0].amount.value)
== 0)
--
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: mandatory, stringified bank transaction code, even for GBIC rulebook,
gnunet <=