[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libeufin] branch master updated (9c7079e5 -> 4b831469)
From: |
gnunet |
Subject: |
[libeufin] branch master updated (9c7079e5 -> 4b831469) |
Date: |
Tue, 04 Apr 2023 21:08:33 +0200 |
This is an automated email from the git hooks/post-receive script.
ms pushed a change to branch master
in repository libeufin.
from 9c7079e5 Amount comparison.
new 4990150b testing zero-check for amounts
new 4b831469 Introducing account-less Access API's endpoints.
The 2 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/test/kotlin/SandboxAccessApiTest.kt | 72 +++++++++++
.../src/main/kotlin/tech/libeufin/sandbox/Main.kt | 144 ++++++++++++---------
util/src/test/kotlin/AmountTest.kt | 8 +-
3 files changed, 164 insertions(+), 60 deletions(-)
diff --git a/nexus/src/test/kotlin/SandboxAccessApiTest.kt
b/nexus/src/test/kotlin/SandboxAccessApiTest.kt
index 4c0232c9..ca4f2f08 100644
--- a/nexus/src/test/kotlin/SandboxAccessApiTest.kt
+++ b/nexus/src/test/kotlin/SandboxAccessApiTest.kt
@@ -5,15 +5,87 @@ import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import io.ktor.server.testing.*
+import io.ktor.util.*
import kotlinx.coroutines.runBlocking
import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.transactions.transaction
import org.junit.Test
+import tech.libeufin.nexus.bankaccount.getBankAccount
import tech.libeufin.sandbox.*
class SandboxAccessApiTest {
val mapper = ObjectMapper()
+ /**
+ * Testing that ..access-api/withdrawals/{wopid} and
+ * ..access-api/accounts/{account_name}/withdrawals/{wopid}
+ * are handled in the same way.
+ */
+ @Test
+ fun doubleUriStyle() {
+ // Creating one withdrawal operation.
+ withTestDatabase {
+ prepSandboxDb()
+ val wo: TalerWithdrawalEntity = transaction {
+ TalerWithdrawalEntity.new {
+ this.amount = "TESTKUDOS:3.3"
+ walletBankAccount = getBankAccountFromLabel("foo")
+ selectedExchangePayto =
"payto://iban/SANDBOXX/${BAR_USER_IBAN}"
+ reservePub = "not used"
+ selectionDone = true
+ }
+ }
+ testApplication {
+ application(sandboxApp)
+ // Showing withdrawal info.
+ val get_with_account =
client.get("/demobanks/default/access-api/accounts/foo/withdrawals/${wo.wopid}")
{
+ expectSuccess = true
+ }
+ val get_without_account =
client.get("/demobanks/default/access-api/withdrawals/${wo.wopid}") {
+ expectSuccess = true
+ }
+ assert(get_without_account.bodyAsText() ==
get_with_account.bodyAsText())
+ assert(get_with_account.bodyAsText() ==
get_without_account.bodyAsText())
+ // Confirming a withdrawal.
+ val confirm_with_account =
client.post("/demobanks/default/access-api/accounts/foo/withdrawals/${wo.wopid}/confirm")
{
+ expectSuccess = true
+ }
+ val confirm_without_account =
client.post("/demobanks/default/access-api/withdrawals/${wo.wopid}/confirm") {
+ expectSuccess = true
+ }
+ assert(confirm_with_account.status.value ==
confirm_without_account.status.value)
+ assert(confirm_with_account.bodyAsText() ==
confirm_without_account.bodyAsText())
+ // Aborting one withdrawal.
+ var wo_to_abort = transaction {
+ TalerWithdrawalEntity.new {
+ this.amount = "TESTKUDOS:3.3"
+ walletBankAccount = getBankAccountFromLabel("foo")
+ selectedExchangePayto =
"payto://iban/SANDBOXX/${BAR_USER_IBAN}"
+ reservePub = "not used"
+ selectionDone = true
+ }
+ }
+ val abort_with_account =
client.post("/demobanks/default/access-api/accounts/foo/withdrawals/${wo_to_abort.wopid}/abort")
{
+ expectSuccess = true
+ }
+ wo_to_abort = transaction {
+ TalerWithdrawalEntity.new {
+ this.amount = "TESTKUDOS:3.3"
+ walletBankAccount = getBankAccountFromLabel("foo")
+ selectedExchangePayto =
"payto://iban/SANDBOXX/${BAR_USER_IBAN}"
+ reservePub = "not used"
+ selectionDone = true
+ }
+ }
+ val abort_without_account =
client.post("/demobanks/default/access-api/withdrawals/${wo_to_abort.wopid}/abort")
{
+ expectSuccess = true
+ }
+ assert(abort_with_account.status.value ==
abort_without_account.status.value)
+ // Not checking the content as they abort two different
operations.
+ }
+ }
+ }
+
// Move funds between accounts.
@Test
fun wireTransfer() {
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
index 9c8f8121..4aedf41c 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
@@ -487,6 +487,73 @@ fun setJsonHandler(ctx: ObjectMapper) {
)
}
+private suspend fun getWithdrawal(call: ApplicationCall) {
+ val op = getWithdrawalOperation(call.expectUriComponent("withdrawal_id"))
+ if (!op.selectionDone && op.reservePub != null) throw internalServerError(
+ "Unselected withdrawal has a reserve public key",
+ LibeufinErrorCode.LIBEUFIN_EC_INCONSISTENT_STATE
+ )
+ call.respond(object {
+ val amount = op.amount
+ val aborted = op.aborted
+ val confirmation_done = op.confirmationDone
+ val selection_done = op.selectionDone
+ val selected_reserve_pub = op.reservePub
+ val selected_exchange_account = op.selectedExchangePayto
+ })
+}
+
+private suspend fun confirmWithdrawal(call: ApplicationCall) {
+ val withdrawalId = call.expectUriComponent("withdrawal_id")
+ transaction {
+ val wo = getWithdrawalOperation(withdrawalId)
+ if (wo.aborted) throw SandboxError(
+ HttpStatusCode.Conflict,
+ "Cannot confirm an aborted withdrawal."
+ )
+ if (!wo.selectionDone) throw SandboxError(
+ HttpStatusCode.UnprocessableEntity,
+ "Cannot confirm a unselected withdrawal: " +
+ "specify exchange and reserve public key via Integration
API first."
+ )
+ /**
+ * The wallet chose not to select any exchange, use the default.
+ */
+ val demobank = ensureDemobank(call)
+ if (wo.selectedExchangePayto == null) {
+ wo.selectedExchangePayto = demobank.config.suggestedExchangePayto
+ }
+ val exchangeBankAccount = getBankAccountFromPayto(
+ wo.selectedExchangePayto ?: throw internalServerError(
+ "Cannot withdraw without an exchange."
+ )
+ )
+ if (!wo.confirmationDone) {
+ wireTransfer(
+ debitAccount = wo.walletBankAccount,
+ creditAccount = exchangeBankAccount,
+ amount = wo.amount,
+ subject = wo.reservePub ?: throw internalServerError(
+ "Cannot transfer funds without reserve public key."
+ ),
+ // provide the currency.
+ demobank = ensureDemobank(call)
+ )
+ wo.confirmationDone = true
+ }
+ wo.confirmationDone
+ }
+ call.respond(object {})
+}
+
+private suspend fun abortWithdrawal(call: ApplicationCall) {
+ val withdrawalId = call.expectUriComponent("withdrawal_id")
+ val operation = getWithdrawalOperation(withdrawalId)
+ if (operation.confirmationDone) throw conflict("Cannot abort paid
withdrawal.")
+ transaction { operation.aborted = true }
+ call.respond(object {})
+}
+
val sandboxApp: Application.() -> Unit = {
install(CallLogging) {
this.level = Level.DEBUG
@@ -1283,19 +1350,12 @@ val sandboxApp: Application.() -> Unit = {
}
// Information about one withdrawal.
get("/accounts/{account_name}/withdrawals/{withdrawal_id}") {
- val op =
getWithdrawalOperation(call.expectUriComponent("withdrawal_id"))
- if (!op.selectionDone && op.reservePub != null) throw
internalServerError(
- "Unselected withdrawal has a reserve public key",
- LibeufinErrorCode.LIBEUFIN_EC_INCONSISTENT_STATE
- )
- call.respond(object {
- val amount = op.amount
- val aborted = op.aborted
- val confirmation_done = op.confirmationDone
- val selection_done = op.selectionDone
- val selected_reserve_pub = op.reservePub
- val selected_exchange_account =
op.selectedExchangePayto
- })
+ getWithdrawal(call)
+ return@get
+ }
+ // account-less style:
+ get("/withdrawals/{withdrawal_id}") {
+ getWithdrawal(call)
return@get
}
// Create a new withdrawal operation.
@@ -1372,54 +1432,22 @@ val sandboxApp: Application.() -> Unit = {
}
// Confirm a withdrawal: no basic auth, because the ID should
be unguessable.
post("/accounts/{account_name}/withdrawals/{withdrawal_id}/confirm") {
- val withdrawalId = call.expectUriComponent("withdrawal_id")
- transaction {
- val wo = getWithdrawalOperation(withdrawalId)
- if (wo.aborted) throw SandboxError(
- HttpStatusCode.Conflict,
- "Cannot confirm an aborted withdrawal."
- )
- if (!wo.selectionDone) throw SandboxError(
- HttpStatusCode.UnprocessableEntity,
- "Cannot confirm a unselected withdrawal: " +
- "specify exchange and reserve public key
via Integration API first."
- )
- /**
- * The wallet chose not to select any exchange, use
the default.
- */
- val demobank = ensureDemobank(call)
- if (wo.selectedExchangePayto == null) {
- wo.selectedExchangePayto =
demobank.config.suggestedExchangePayto
- }
- val exchangeBankAccount = getBankAccountFromPayto(
- wo.selectedExchangePayto ?: throw
internalServerError(
- "Cannot withdraw without an exchange."
- )
- )
- if (!wo.confirmationDone) {
- wireTransfer(
- debitAccount = wo.walletBankAccount,
- creditAccount = exchangeBankAccount,
- amount = wo.amount,
- subject = wo.reservePub ?: throw
internalServerError(
- "Cannot transfer funds without reserve
public key."
- ),
- // provide the currency.
- demobank = ensureDemobank(call)
- )
- wo.confirmationDone = true
- }
- wo.confirmationDone
- }
- call.respond(object {})
+ confirmWithdrawal(call)
return@post
}
+ // account-less style:
+ post("/withdrawals/{withdrawal_id}/confirm") {
+ confirmWithdrawal(call)
+ return@post
+ }
+ // Aborting withdrawals:
post("/accounts/{account_name}/withdrawals/{withdrawal_id}/abort") {
- val withdrawalId = call.expectUriComponent("withdrawal_id")
- val operation = getWithdrawalOperation(withdrawalId)
- if (operation.confirmationDone) throw conflict("Cannot
abort paid withdrawal.")
- transaction { operation.aborted = true }
- call.respond(object {})
+ abortWithdrawal(call)
+ return@post
+ }
+ // account-less style:
+ post("/withdrawals/{withdrawal_id}/abort") {
+ abortWithdrawal(call)
return@post
}
// Bank account basic information.
diff --git a/util/src/test/kotlin/AmountTest.kt
b/util/src/test/kotlin/AmountTest.kt
index 5ae1e05f..eb7d8493 100644
--- a/util/src/test/kotlin/AmountTest.kt
+++ b/util/src/test/kotlin/AmountTest.kt
@@ -19,8 +19,12 @@ inline fun <reified ExceptionType> assertException(block: ()
-> Unit) {
class AmountTest {
@Test
fun equalTest() {
- val z = BigDecimal("-0000000000.0000000000")
- assert(isAmountZero(z))
+ assert(isAmountZero(BigDecimal("-0000000000.0000000000")))
+ assert(!isAmountZero(BigDecimal("1")))
+ assert(isAmountZero(BigDecimal("0.00")))
+ assert(isAmountZero(BigDecimal("0")))
+ assert(!isAmountZero(BigDecimal("00000000000001")))
+ assert(!isAmountZero(BigDecimal("-1.00000000")))
}
@Test
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
- [libeufin] branch master updated (9c7079e5 -> 4b831469),
gnunet <=