summaryrefslogtreecommitdiff
path: root/sandbox/src/main/kotlin/tech/libeufin
diff options
context:
space:
mode:
authorMS <ms@taler.net>2023-04-04 21:07:58 +0200
committerMS <ms@taler.net>2023-04-04 21:07:58 +0200
commit4b8314699995083a48515b578ebed5da828c477f (patch)
treee77471cbcad15e0d5d53785c90eb9d00025680fb /sandbox/src/main/kotlin/tech/libeufin
parent4990150b3aac8066c0cdee4c7dc9170e433e73c9 (diff)
downloadlibeufin-4b8314699995083a48515b578ebed5da828c477f.tar.gz
libeufin-4b8314699995083a48515b578ebed5da828c477f.tar.bz2
libeufin-4b8314699995083a48515b578ebed5da828c477f.zip
Introducing account-less Access API's endpoints.
Diffstat (limited to 'sandbox/src/main/kotlin/tech/libeufin')
-rw-r--r--sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt144
1 files changed, 86 insertions, 58 deletions
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.