gnunet-svn
[Top][All Lists]
Advanced

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

[libeufin] branch master updated (dcc9d141 -> f5995b84)


From: gnunet
Subject: [libeufin] branch master updated (dcc9d141 -> f5995b84)
Date: Fri, 06 Jan 2023 19:09:41 +0100

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

ms pushed a change to branch master
in repository libeufin.

    from dcc9d141 Fix response status code.
     new 870d3e29 Nexus error handling.
     new 3365e7da address compiler warnings
     new f5995b84 Amount representation.

The 3 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:
 nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt    |  2 +-
 .../tech/libeufin/nexus/bankaccount/BankAccount.kt |  2 +-
 .../tech/libeufin/nexus/ebics/EbicsClient.kt       |  6 ++--
 .../tech/libeufin/nexus/iso20022/Iso20022.kt       |  6 ++--
 .../main/kotlin/tech/libeufin/nexus/server/JSON.kt | 11 ++++----
 .../tech/libeufin/nexus/server/NexusServer.kt      |  2 +-
 nexus/src/test/kotlin/DownloadAndSubmit.kt         |  6 ++--
 nexus/src/test/kotlin/Iso20022Test.kt              |  2 +-
 nexus/src/test/kotlin/SandboxCircuitApiTest.kt     |  4 +--
 .../kotlin/tech/libeufin/sandbox/CircuitApi.kt     | 16 ++++++-----
 .../src/main/kotlin/tech/libeufin/sandbox/Main.kt  | 14 +++-------
 .../kotlin/tech/libeufin/sandbox/bankAccount.kt    | 18 +++++++-----
 util/src/main/kotlin/Ebics.kt                      |  6 +++-
 util/src/main/kotlin/amounts.kt                    | 31 ++++++---------------
 util/src/main/kotlin/strings.kt                    |  2 +-
 util/src/test/kotlin/AmountTest.kt                 | 32 ++++++++++++++++------
 16 files changed, 83 insertions(+), 77 deletions(-)

diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
index a120da7b..9e0798e0 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
@@ -201,7 +201,7 @@ object PaymentInitiationsTable : LongIdTable() {
     val bankAccount = reference("bankAccount", NexusBankAccountsTable)
     val preparationDate = long("preparationDate")
     val submissionDate = long("submissionDate").nullable()
-    val sum = amount("sum")
+    val sum = text("sum") // the amount to transfer.
     val currency = text("currency")
     val endToEndId = text("endToEndId")
     val paymentInformationId = text("paymentInformationId")
diff --git 
a/nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt
index fa8064d5..6cd21c62 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt
@@ -249,7 +249,7 @@ fun processCamtMessage(
             val rawEntity = NexusBankTransactionEntity.new {
                 bankAccount = acct
                 accountTransactionId = "AcctSvcrRef:$acctSvcrRef"
-                amount = 
singletonBatchedTransaction.amount.value.toPlainString()
+                amount = singletonBatchedTransaction.amount.value
                 currency = singletonBatchedTransaction.amount.currency
                 transactionJson = 
jacksonObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(entry)
                 creditDebitIndicator = 
singletonBatchedTransaction.creditDebitIndicator.name
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsClient.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsClient.kt
index 6d2ce4de..136bf7e8 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsClient.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsClient.kt
@@ -255,9 +255,9 @@ suspend fun doEbicsUploadTransaction(
                  * bank rejecting the operation instead of it
                  * detecting the problem.
                  */
-                HttpStatusCode.InternalServerError,
-                "Unexpected EBICS technical return code: 
${txResp.technicalReturnCode}",
-                txResp.technicalReturnCode
+                httpStatusCode = HttpStatusCode.InternalServerError,
+                reason = txResp.reportText,
+                ebicsTechnicalCode = txResp.technicalReturnCode
             )
         }
     }
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 12045f50..98e92a46 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/Iso20022.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/Iso20022.kt
@@ -632,7 +632,7 @@ private fun XmlElementDestructor.extractParty(): 
PartyIdentification {
 
 private fun XmlElementDestructor.extractCurrencyAmount(): CurrencyAmount {
     return CurrencyAmount(
-        value = BigDecimal(requireUniqueChildNamed("Amt") { 
focusElement.textContent }),
+        value = requireUniqueChildNamed("Amt") { focusElement.textContent },
         currency = requireUniqueChildNamed("Amt") { 
focusElement.getAttribute("Ccy") }
     )
 }
@@ -641,7 +641,7 @@ private fun 
XmlElementDestructor.maybeExtractCurrencyAmount(): CurrencyAmount? {
     return maybeUniqueChildNamed("Amt") {
         CurrencyAmount(
             focusElement.getAttribute("Ccy"),
-            BigDecimal(focusElement.textContent)
+            focusElement.textContent
         )
     }
 }
@@ -667,7 +667,7 @@ private fun XmlElementDestructor.extractBatches(
     if (mapEachChildNamed("NtryDtls") {}.size != 1) throw CamtParsingError(
         "This money movement (AcctSvcrRef: $acctSvcrRef) is not a singleton #0"
     )
-    var txs = requireUniqueChildNamed("NtryDtls") {
+    val txs = requireUniqueChildNamed("NtryDtls") {
         if (mapEachChildNamed("TxDtls") {}.size != 1) {
             throw CamtParsingError("This money movement (AcctSvcrRef: 
$acctSvcrRef) is not a singleton #1")
         }
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/server/JSON.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/server/JSON.kt
index 17db9166..8f87c0e2 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/server/JSON.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/server/JSON.kt
@@ -381,7 +381,7 @@ data class Pain001Data(
     val creditorIban: String,
     val creditorBic: String?,
     val creditorName: String,
-    val sum: Amount,
+    val sum: String,
     val currency: String,
     val subject: String
 )
@@ -418,7 +418,7 @@ class CurrencyAmountDeserializer(jc: Class<*> = 
CurrencyAmount::class.java) : St
         val s = p.valueAsString
         val components = s.split(":")
         // FIXME: error handling!
-        return CurrencyAmount(components[0], BigDecimal(components[1]))
+        return CurrencyAmount(components[0], components[1])
     }
 }
 
@@ -430,19 +430,20 @@ class CurrencyAmountSerializer(jc: Class<CurrencyAmount> 
= CurrencyAmount::class
         if (value == null) {
             gen.writeNull()
         } else {
-            gen.writeString("${value.currency}:${value.value.toPlainString()}")
+            gen.writeString("${value.currency}:${value.value}")
         }
     }
 }
 
+// FIXME: this type duplicates AmountWithCurrency.
 @JsonDeserialize(using = CurrencyAmountDeserializer::class)
 @JsonSerialize(using = CurrencyAmountSerializer::class)
 data class CurrencyAmount(
     val currency: String,
-    val value: BigDecimal // allows calculations
+    val value: String // allows calculations
 )
 fun CurrencyAmount.toPlainString(): String {
-    return "${this.currency}:${this.value.toPlainString()}"
+    return "${this.currency}:${this.value}"
 }
 
 data class InitiatedPayments(
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt
index b39c72ec..23df07a5 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt
@@ -208,7 +208,7 @@ val nexusApp: Application.() -> Unit = {
                 cause.httpStatusCode,
                 message = ErrorResponse(
                     code = 
TalerErrorCode.TALER_EC_LIBEUFIN_NEXUS_GENERIC_ERROR.code,
-                    hint = "EBICS protocol error",
+                    hint = "The EBICS communication with the bank failed: 
${cause.ebicsTechnicalCode}",
                     detail = cause.reason,
                 )
             )
diff --git a/nexus/src/test/kotlin/DownloadAndSubmit.kt 
b/nexus/src/test/kotlin/DownloadAndSubmit.kt
index 0da30b28..3d51dc45 100644
--- a/nexus/src/test/kotlin/DownloadAndSubmit.kt
+++ b/nexus/src/test/kotlin/DownloadAndSubmit.kt
@@ -151,7 +151,7 @@ class DownloadAndSubmit {
                             creditorBic = "SANDBOXX",
                             creditorName = "Tester",
                             subject = "test payment",
-                            sum = Amount(1),
+                            sum = "1",
                             currency = "TESTKUDOS"
                         ),
                         transaction {
@@ -246,7 +246,7 @@ class DownloadAndSubmit {
                             creditorBic = "not-a-BIC",
                             creditorName = "Tester",
                             subject = "test payment",
-                            sum = Amount(1),
+                            sum = "1",
                             currency = "TESTKUDOS"
                         ),
                         transaction {
@@ -282,7 +282,7 @@ class DownloadAndSubmit {
                             creditorBic = "SANDBOXX",
                             creditorName = "Tester",
                             subject = "test payment",
-                            sum = Amount(1),
+                            sum = "1",
                             currency = "EUR"
                         ),
                         transaction {
diff --git a/nexus/src/test/kotlin/Iso20022Test.kt 
b/nexus/src/test/kotlin/Iso20022Test.kt
index b639aff6..c14b564b 100644
--- a/nexus/src/test/kotlin/Iso20022Test.kt
+++ b/nexus/src/test/kotlin/Iso20022Test.kt
@@ -54,7 +54,7 @@ class Iso20022Test {
         assertEquals(1, r.reports.size)
 
         // First Entry
-        
assertTrue(BigDecimal(100).compareTo(r.reports[0].entries[0].amount.value) == 0)
+        assertTrue("100" == r.reports[0].entries[0].amount.value)
         assertEquals("EUR", r.reports[0].entries[0].amount.currency)
         assertEquals(CreditDebitIndicator.CRDT, 
r.reports[0].entries[0].creditDebitIndicator)
         assertEquals(EntryStatus.BOOK, r.reports[0].entries[0].status)
diff --git a/nexus/src/test/kotlin/SandboxCircuitApiTest.kt 
b/nexus/src/test/kotlin/SandboxCircuitApiTest.kt
index 11ca7f14..15f88961 100644
--- a/nexus/src/test/kotlin/SandboxCircuitApiTest.kt
+++ b/nexus/src/test/kotlin/SandboxCircuitApiTest.kt
@@ -52,7 +52,7 @@ class SandboxCircuitApiTest {
             testApplication {
                 application(sandboxApp)
                 // Register a new account.
-                var R = client.post("/demobanks/default/circuit-api/accounts") 
{
+                client.post("/demobanks/default/circuit-api/accounts") {
                     expectSuccess = true
                     contentType(ContentType.Application.Json)
                     basicAuth("admin", "foo")
@@ -77,7 +77,7 @@ class SandboxCircuitApiTest {
                     amount = initialBalance
                 )
                 // Check the balance before cashing out.
-                R = client.get("/demobanks/default/access-api/accounts/shop") {
+                var R = 
client.get("/demobanks/default/access-api/accounts/shop") {
                     basicAuth("shop", "secret")
                 }
                 val mapper = ObjectMapper()
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/CircuitApi.kt 
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/CircuitApi.kt
index e02bdfb3..1742dc4b 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/CircuitApi.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/CircuitApi.kt
@@ -113,8 +113,8 @@ fun generateCashoutSubject(
     amountCredit: AmountWithCurrency,
     amountDebit: AmountWithCurrency
 ): String {
-    return "Cash-out of 
${amountDebit.currency}:${amountDebit.amount.toPlainString()}" +
-            " to 
${amountCredit.currency}:${amountCredit.amount.toPlainString()}"
+    return "Cash-out of ${amountDebit.currency}:${amountDebit.amount}" +
+            " to ${amountCredit.currency}:${amountCredit.amount}"
 }
 
 /**
@@ -295,18 +295,20 @@ fun circuitApi(circuitRoute: Route) {
         // check rates correctness
         val sellRatio = BigDecimal(ratiosAndFees.sell_at_ratio.toString())
         val sellFee = BigDecimal(ratiosAndFees.sell_out_fee.toString())
-        val amountCreditCheck = (amountDebit.amount * sellRatio) - sellFee
+        val amountDebitAsNumber = BigDecimal(amountDebit.amount)
+        val expectedAmountCredit = (amountDebitAsNumber * sellRatio) - sellFee
         val commonRounding = MathContext(2) // ensures both amounts end with 
".XY"
-        if (amountCreditCheck.round(commonRounding) != 
amountCredit.amount.round(commonRounding)) {
+        val amountCreditAsNumber = BigDecimal(amountCredit.amount)
+        if (expectedAmountCredit.round(commonRounding) != 
amountCreditAsNumber.round(commonRounding)) {
             val msg = "Rates application are incorrect." +
-                    "  The expected amount to credit is: 
${amountCreditCheck}," +
-                    " but ${amountCredit.amount.toPlainString()} was 
specified."
+                    "  The expected amount to credit is: 
${expectedAmountCredit}," +
+                    " but ${amountCredit.amount} was specified."
             logger.info(msg)
             throw badRequest(msg)
         }
         // check that the balance is sufficient
         val balance = getBalance(user, withPending = true)
-        val balanceCheck = balance - amountDebit.amount
+        val balanceCheck = balance - amountDebitAsNumber
         if (balanceCheck < BigDecimal.ZERO && balanceCheck.abs() > 
BigDecimal(demobank.usersDebtLimit)) {
             val msg = "Cash-out not possible due to insufficient funds.  
Balance ${balance.toPlainString()} would reach ${balanceCheck.toPlainString()}"
             logger.info(msg)
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt 
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
index d1f88b43..ca4cb8ff 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
@@ -720,16 +720,9 @@ val sandboxApp: Application.() -> Unit = {
                     "invalid BIC"
                 )
             }
-            val (amount, currency) = parseAmountAsString(body.amount)
+            val amount = parseAmount(body.amount)
             transaction {
                 val demobank = getDefaultDemobank()
-                /**
-                 * This API needs compatibility with the currency-less format.
-                 */
-                if (currency != null) {
-                    if (currency != demobank.currency)
-                        throw SandboxError(HttpStatusCode.BadRequest, 
"Currency ${currency} not supported.")
-                }
                 val account = getBankAccountFromLabel(
                     accountLabel, demobank
                 )
@@ -743,7 +736,7 @@ val sandboxApp: Application.() -> Unit = {
                     debtorBic = reqDebtorBic
                     debtorName = body.debtorName
                     subject = body.subject
-                    this.amount = amount
+                    this.amount = amount.amount
                     date = getUTCnow().toInstant().toEpochMilli()
                     accountServicerReference = "sandbox-$randId"
                     this.account = account
@@ -1316,7 +1309,8 @@ val sandboxApp: Application.() -> Unit = {
                     val maxDebt = if (username == "admin") {
                         demobank.bankDebtLimit
                     } else demobank.usersDebtLimit
-                    if ((pendingBalance - amount.amount).abs() > 
BigDecimal.valueOf(maxDebt.toLong())) {
+                    val amountAsNumber = BigDecimal(amount.amount)
+                    if ((pendingBalance - amountAsNumber).abs() > 
BigDecimal.valueOf(maxDebt.toLong())) {
                         logger.info("User $username would surpass user debit " 
+
                                 "threshold of ${demobank.usersDebtLimit}.  
Rollback Taler withdrawal"
                         )
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/bankAccount.kt 
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/bankAccount.kt
index 33c565cc..eacae3c3 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/bankAccount.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/bankAccount.kt
@@ -108,11 +108,15 @@ fun wireTransfer(
     amount: String, // $currency:$value
     pmtInfId: String? = null
 ): String {
-    val checkAmount = parseAmount(amount)
-    if (checkAmount.amount == BigDecimal.ZERO)
+    val parsedAmount = parseAmount(amount)
+    val amountAsNumber = BigDecimal(parsedAmount.amount)
+    if (amountAsNumber == BigDecimal.ZERO)
         throw badRequest("Wire transfers of zero not possible.")
-    if (checkAmount.currency != demobank.currency)
-        throw badRequest("Won't wire transfer with currency: 
${checkAmount.currency}")
+    if (parsedAmount.currency != demobank.currency)
+        throw badRequest(
+            "Won't wire transfer with currency: ${parsedAmount.currency}." +
+                    "  Only ${demobank.currency} allowed."
+        )
     // Check funds are sufficient.
     /**
      * Using 'pending' balance because Libeufin never books.  The
@@ -122,7 +126,7 @@ fun wireTransfer(
     val maxDebt = if (debitAccount.label == "admin") {
         demobank.bankDebtLimit
     } else demobank.usersDebtLimit
-    val balanceCheck = pendingBalance - checkAmount.amount
+    val balanceCheck = pendingBalance - amountAsNumber
     if (balanceCheck < BigDecimal.ZERO && balanceCheck.abs() > 
BigDecimal.valueOf(maxDebt.toLong())) {
         logger.info("Account ${debitAccount.label} would surpass debit 
threshold of $maxDebt.  Rollback wire transfer")
         throw SandboxError(HttpStatusCode.PreconditionFailed, "Insufficient 
funds")
@@ -138,7 +142,7 @@ fun wireTransfer(
             debtorBic = debitAccount.bic
             debtorName = getPersonNameFromCustomer(debitAccount.owner)
             this.subject = subject
-            this.amount = checkAmount.amount.toPlainString()
+            this.amount = parsedAmount.amount
             this.currency = demobank.currency
             date = timeStamp
             accountServicerReference = transactionRef
@@ -155,7 +159,7 @@ fun wireTransfer(
             debtorBic = debitAccount.bic
             debtorName = getPersonNameFromCustomer(debitAccount.owner)
             this.subject = subject
-            this.amount = checkAmount.amount.toPlainString()
+            this.amount = parsedAmount.amount
             this.currency = demobank.currency
             date = timeStamp
             accountServicerReference = transactionRef
diff --git a/util/src/main/kotlin/Ebics.kt b/util/src/main/kotlin/Ebics.kt
index 405c2fcb..6549dea5 100644
--- a/util/src/main/kotlin/Ebics.kt
+++ b/util/src/main/kotlin/Ebics.kt
@@ -47,7 +47,7 @@ data class EbicsProtocolError(
     val httpStatusCode: HttpStatusCode,
     val reason: String,
     /**
-     * This error type is also used when Nexus finds itself
+     * This class is also used when Nexus finds itself
      * in an inconsistent state, without interacting with the
      * bank.  In this case, the EBICS code below can be left
      * null.
@@ -386,6 +386,7 @@ data class EbicsResponseContent(
     val orderDataEncChunk: String?,
     val technicalReturnCode: EbicsReturnCode,
     val bankReturnCode: EbicsReturnCode,
+    val reportText: String,
     val segmentNumber: Int?,
     // Only present in init phase
     val numSegments: Int?
@@ -496,6 +497,8 @@ fun parseAndValidateEbicsResponse(
     val techReturnCodeStr = resp.value.header.mutable.returnCode
     val techReturnCode = EbicsReturnCode.lookup(techReturnCodeStr)
 
+    val reportText = resp.value.header.mutable.reportText
+
     val daeXml = resp.value.body.dataTransfer?.dataEncryptionInfo
     val dataEncryptionInfo = if (daeXml == null) {
         null
@@ -507,6 +510,7 @@ fun parseAndValidateEbicsResponse(
         transactionID = resp.value.header._static.transactionID,
         bankReturnCode = bankReturnCode,
         technicalReturnCode = techReturnCode,
+        reportText = reportText,
         orderDataEncChunk = resp.value.body.dataTransfer?.orderData?.value,
         dataEncryptionInfo = dataEncryptionInfo,
         numSegments = resp.value.header._static.numSegments?.toInt(),
diff --git a/util/src/main/kotlin/amounts.kt b/util/src/main/kotlin/amounts.kt
index 8ba14192..a1cfe47d 100644
--- a/util/src/main/kotlin/amounts.kt
+++ b/util/src/main/kotlin/amounts.kt
@@ -22,33 +22,18 @@ import io.ktor.http.*
  * <http://www.gnu.org/licenses/>
  */
 
-val re = Regex("^([0-9]+(\\.[0-9]+)?)$")
-val reWithSign = Regex("^-?([0-9]+(\\.[0-9]+)?)$")
-
+const val plainAmountRe = "^([0-9]+(\\.[0-9][0-9]?)?)$"
+const val plainAmountReWithSign = "^-?([0-9]+(\\.[0-9][0-9]?)?)$"
+const val amountWithCurrencyRe = "^([A-Z]+):([0-9]+(\\.[0-9][0-9]?)?)$"
 
 fun validatePlainAmount(plainAmount: String, withSign: Boolean = false): 
Boolean {
-    if (withSign) return reWithSign.matches(plainAmount)
-    return re.matches(plainAmount)
-}
-
-/**
- * Parse an "amount" where the currency is optional.  It returns
- * a pair where the first item is always the amount, and the second
- * is the currency or null (when this one wasn't given in the input)
- */
-fun parseAmountAsString(amount: String): Pair<String, String?> {
-    val match = Regex("^([A-Z]+:)?([0-9]+(\\.[0-9]+)?)$").find(amount) ?: throw
-    UtilError(HttpStatusCode.BadRequest, "invalid amount: $amount")
-    var (currency, number) = match.destructured
-    // Currency given, need to strip the ":".
-    if (currency.isNotEmpty())
-        currency = currency.dropLast(1)
-    return Pair(number, if (currency.isEmpty()) null else currency)
+    if (withSign) return Regex(plainAmountReWithSign).matches(plainAmount)
+    return Regex(plainAmountRe).matches(plainAmount)
 }
 
 fun parseAmount(amount: String): AmountWithCurrency {
-    val match = Regex("([A-Z]+):([0-9]+(\\.[0-9]+)?)").find(amount) ?:
+    val match = Regex(amountWithCurrencyRe).find(amount) ?:
         throw UtilError(HttpStatusCode.BadRequest, "invalid amount: $amount")
     val (currency, number) = match.destructured
-    return AmountWithCurrency(currency, Amount(number))
-}
+    return AmountWithCurrency(currency = currency, amount = number)
+}
\ No newline at end of file
diff --git a/util/src/main/kotlin/strings.kt b/util/src/main/kotlin/strings.kt
index 3b94b517..91c0fd84 100644
--- a/util/src/main/kotlin/strings.kt
+++ b/util/src/main/kotlin/strings.kt
@@ -100,7 +100,7 @@ fun chunkString(input: String): String {
 
 data class AmountWithCurrency(
     val currency: String,
-    val amount: Amount
+    val amount: String
 )
 
 fun parseDecimal(decimalStr: String): BigDecimal {
diff --git a/util/src/test/kotlin/AmountTest.kt 
b/util/src/test/kotlin/AmountTest.kt
index bc7ee39b..1dac0be0 100644
--- a/util/src/test/kotlin/AmountTest.kt
+++ b/util/src/test/kotlin/AmountTest.kt
@@ -1,15 +1,31 @@
 import org.junit.Test
-import tech.libeufin.util.parseAmountAsString
-import kotlin.reflect.typeOf
+import tech.libeufin.util.parseAmount
+import tech.libeufin.util.validatePlainAmount
 
+inline fun <reified ExceptionType> assertException(block: () -> Unit) {
+    try {
+        block()
+    } catch (e: Throwable) {
+        assert(e.javaClass == ExceptionType::class.java)
+        return
+    }
+    return assert(false)
+}
 class AmountTest {
     @Test
     fun parse() {
-        val resWithCurrency = parseAmountAsString("CURRENCY:5.5")
-        assert(resWithCurrency.first == "5.5")
-        assert(resWithCurrency.second == "CURRENCY")
-        val resWithoutCurrency = parseAmountAsString("5.5")
-        assert(resWithoutCurrency.first == "5.5")
-        assert(resWithoutCurrency.second == null)
+        var res = parseAmount("KUDOS:5.5")
+        assert(res.amount == "5.5")
+        assert(res.currency == "KUDOS")
+        assert(validatePlainAmount("1.0"))
+        assert(validatePlainAmount("1.00"))
+        assert(!validatePlainAmount("1.000"))
+        res = parseAmount("TESTKUDOS:1.11")
+        assert(res.amount == "1.11")
+        assert(res.currency == "TESTKUDOS")
+        assertException<UtilError> { parseAmount("TESTKUDOS:1.") }
+        assertException<UtilError> { parseAmount("TESTKUDOS:.1") }
+        assertException<UtilError> { parseAmount("TESTKUDOS:1.000") }
+        assertException<UtilError> { parseAmount("TESTKUDOS:1..") }
     }
 }
\ No newline at end of file

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

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