gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-kotlin] branch master updated: Add exchange management to


From: gnunet
Subject: [taler-wallet-kotlin] branch master updated: Add exchange management to public wallet API
Date: Tue, 04 Aug 2020 17:48:49 +0200

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

torsten-grote pushed a commit to branch master
in repository wallet-kotlin.

The following commit(s) were added to refs/heads/master by this push:
     new a35337b  Add exchange management to public wallet API
a35337b is described below

commit a35337b991f8b3d38c3480fb76acd9fc6df47885
Author: Torsten Grote <t@grobox.de>
AuthorDate: Tue Aug 4 12:46:48 2020 -0300

    Add exchange management to public wallet API
    
    The API already works, but data is stored in-memory only.
    There's a live integration test available, but ignored in CI.
---
 .../kotlin/net/taler/wallet/kotlin/WalletApi.kt    | 51 ++++++++++++++++++-
 .../net/taler/wallet/kotlin/exchange/Exchange.kt   | 37 ++++++++++++++
 .../net/taler/wallet/kotlin/operations/Withdraw.kt |  7 +--
 .../net/taler/wallet/kotlin/WalletApiTest.kt       | 59 +++++++++++++++++++---
 4 files changed, 140 insertions(+), 14 deletions(-)

diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/WalletApi.kt 
b/src/commonMain/kotlin/net/taler/wallet/kotlin/WalletApi.kt
index 61a3a1a..11fd181 100644
--- a/src/commonMain/kotlin/net/taler/wallet/kotlin/WalletApi.kt
+++ b/src/commonMain/kotlin/net/taler/wallet/kotlin/WalletApi.kt
@@ -16,13 +16,25 @@
 
 package net.taler.wallet.kotlin
 
+import io.ktor.client.HttpClient
+import net.taler.wallet.kotlin.crypto.Crypto
+import net.taler.wallet.kotlin.crypto.CryptoFactory
+import net.taler.wallet.kotlin.crypto.Signature
+import net.taler.wallet.kotlin.exchange.Exchange
+import net.taler.wallet.kotlin.exchange.ExchangeListItem
+import net.taler.wallet.kotlin.exchange.GetExchangeTosResult
 import net.taler.wallet.kotlin.operations.Withdraw
 import net.taler.wallet.kotlin.operations.WithdrawalDetails
 import net.taler.wallet.kotlin.operations.WithdrawalDetailsForUri
 
 public class WalletApi {
 
-    private val withdrawManager = Withdraw()
+    private val httpClient: HttpClient = getDefaultHttpClient()
+    private val db: Db = DbFactory().openDb()
+    private val crypto: Crypto = CryptoFactory.getCrypto()
+    private val signature: Signature = Signature(crypto)
+    private val exchangeManager: Exchange = Exchange(crypto, signature, 
httpClient, db = db)
+    private val withdrawManager = Withdraw(httpClient, db, crypto, signature, 
exchangeManager)
 
     public fun getVersions(): SupportedVersions {
         return SupportedVersions(
@@ -42,7 +54,10 @@ public class WalletApi {
         )
     }
 
-    public suspend fun getWithdrawalDetailsForAmount(exchangeBaseUrl: String, 
amount: Amount): WithdrawalDetails {
+    public suspend fun getWithdrawalDetailsForAmount(
+        exchangeBaseUrl: String,
+        amount: Amount
+    ): WithdrawalDetails {
         val details = withdrawManager.getWithdrawalDetails(exchangeBaseUrl, 
amount)
         return WithdrawalDetails(
             tosAccepted = details.exchange.termsOfServiceAccepted,
@@ -51,4 +66,36 @@ public class WalletApi {
         )
     }
 
+    public suspend fun listExchanges(): List<ExchangeListItem> {
+        return db.listExchanges().mapNotNull { exchange ->
+            ExchangeListItem.fromExchangeRecord(exchange)
+        }
+    }
+
+    public suspend fun addExchange(exchangeBaseUrl: String): ExchangeListItem {
+        val exchange = exchangeManager.updateFromUrl(exchangeBaseUrl)
+        db.put(exchange)
+        return ExchangeListItem.fromExchangeRecord(exchange) ?: TODO("error 
handling")
+    }
+
+    public suspend fun getExchangeTos(exchangeBaseUrl: String): 
GetExchangeTosResult {
+        val record = db.getExchangeByBaseUrl(exchangeBaseUrl) ?: TODO("error 
handling")
+        return GetExchangeTosResult(
+            tos = record.termsOfServiceText ?: TODO("error handling"),
+            currentEtag = record.termsOfServiceLastEtag ?: TODO("error 
handling"),
+            acceptedEtag = record.termsOfServiceAcceptedEtag
+        )
+    }
+
+    public suspend fun setExchangeTosAccepted(exchangeBaseUrl: String, 
acceptedEtag: String) {
+        db.transaction {
+            val record = getExchangeByBaseUrl(exchangeBaseUrl) ?: TODO("error 
handling")
+            val updatedRecord = record.copy(
+                termsOfServiceAcceptedEtag = acceptedEtag,
+                termsOfServiceAcceptedTimestamp = Timestamp.now()
+            )
+            put(updatedRecord)
+        }
+    }
+
 }
diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Exchange.kt 
b/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Exchange.kt
index 3af430f..7a6ac7f 100644
--- a/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Exchange.kt
+++ b/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Exchange.kt
@@ -223,3 +223,40 @@ internal class Exchange(
     }
 
 }
+
+
+data class ExchangeListItem(
+    val exchangeBaseUrl: String,
+    val currency: String,
+    val paytoUris: List<String>
+) {
+    companion object {
+        fun fromExchangeRecord(exchange: ExchangeRecord): ExchangeListItem? {
+            return if (exchange.details == null || exchange.wireInfo == null) 
null
+            else ExchangeListItem(
+                exchangeBaseUrl = exchange.baseUrl,
+                currency = exchange.details.currency,
+                paytoUris = exchange.wireInfo.accounts.map {
+                    it.paytoUri
+                }
+            )
+        }
+    }
+}
+
+data class GetExchangeTosResult(
+    /**
+     * Markdown version of the current ToS.
+     */
+    val tos: String,
+
+    /**
+     * Version tag of the current ToS.
+     */
+    val currentEtag: String,
+
+    /**
+     * Version tag of the last ToS that the user has accepted, if any.
+     */
+    val acceptedEtag: String? = null
+)
diff --git 
a/src/commonMain/kotlin/net/taler/wallet/kotlin/operations/Withdraw.kt 
b/src/commonMain/kotlin/net/taler/wallet/kotlin/operations/Withdraw.kt
index 3981012..e51e9ec 100644
--- a/src/commonMain/kotlin/net/taler/wallet/kotlin/operations/Withdraw.kt
+++ b/src/commonMain/kotlin/net/taler/wallet/kotlin/operations/Withdraw.kt
@@ -35,6 +35,7 @@ import 
net.taler.wallet.kotlin.exchange.DenominationStatus.Unverified
 import net.taler.wallet.kotlin.exchange.DenominationStatus.VerifiedBad
 import net.taler.wallet.kotlin.exchange.DenominationStatus.VerifiedGood
 import net.taler.wallet.kotlin.exchange.Exchange
+import net.taler.wallet.kotlin.exchange.ExchangeListItem
 import net.taler.wallet.kotlin.exchange.ExchangeRecord
 import net.taler.wallet.kotlin.exchange.ExchangeWireInfo
 import net.taler.wallet.kotlin.exchange.SelectedDenomination
@@ -286,12 +287,6 @@ data class WithdrawalDetailsForUri(
     val possibleExchanges: List<ExchangeListItem>
 )
 
-data class ExchangeListItem(
-    val exchangeBaseUrl: String,
-    val currency: String,
-    val paytoUris: List<String>
-)
-
 data class WithdrawalDetails(
     /**
      * Did the user accept the current version of the exchange's terms of 
service?
diff --git a/src/commonTest/kotlin/net/taler/wallet/kotlin/WalletApiTest.kt 
b/src/commonTest/kotlin/net/taler/wallet/kotlin/WalletApiTest.kt
index 9498792..7971be5 100644
--- a/src/commonTest/kotlin/net/taler/wallet/kotlin/WalletApiTest.kt
+++ b/src/commonTest/kotlin/net/taler/wallet/kotlin/WalletApiTest.kt
@@ -19,12 +19,19 @@ package net.taler.wallet.kotlin
 import kotlin.test.Ignore
 import kotlin.test.Test
 import kotlin.test.assertEquals
+import kotlin.test.assertTrue
 
-@Ignore // Live-Test
+@Ignore // Live-Test which fails when test environment changes or is not 
available
 class WalletApiTest {
 
     private val api = WalletApi()
 
+    private val exchangeBaseUrl = "https://exchange.test.taler.net/";
+    private val withdrawUri =
+        
"taler://withdraw/bank.test.taler.net/8adabbf8-fe61-4d31-a2d1-89350b5be8fa"
+    private val paytoUris = 
listOf("payto://x-taler-bank/bank.test.taler.net/Exchange")
+    private val tosEtag = "0"
+
     @Test
     fun testGetVersions() {
         api.getVersions()
@@ -32,15 +39,55 @@ class WalletApiTest {
 
     @Test
     fun testGetWithdrawalDetails() = runCoroutine {
-        val detailsForUri =
-            
api.getWithdrawalDetailsForUri("taler://withdraw/bank.test.taler.net/8adabbf8-fe61-4d31-a2d1-89350b5be8fa")
+        val detailsForUri = api.getWithdrawalDetailsForUri(withdrawUri)
         assertEquals(Amount("TESTKUDOS", 5, 0), detailsForUri.amount)
-        assertEquals("https://exchange.test.taler.net/";, 
detailsForUri.defaultExchangeBaseUrl)
+        assertEquals(exchangeBaseUrl, detailsForUri.defaultExchangeBaseUrl)
 
-        val detailsForAmount =
-            
api.getWithdrawalDetailsForAmount(detailsForUri.defaultExchangeBaseUrl!!, 
detailsForUri.amount)
+        val detailsForAmount = api.getWithdrawalDetailsForAmount(
+            detailsForUri.defaultExchangeBaseUrl!!,
+            detailsForUri.amount
+        )
         assertEquals(Amount("TESTKUDOS", 5, 0), detailsForAmount.amountRaw)
         assertEquals(Amount("TESTKUDOS", 4, 80000000), 
detailsForAmount.amountEffective)
+        assertEquals(false, detailsForAmount.tosAccepted)
+    }
+
+    @Test
+    fun testExchangeManagement() = runCoroutine {
+        // initially we have no exchanges
+        assertTrue(api.listExchanges().isEmpty())
+
+        // test exchange gets added correctly
+        val exchange = api.addExchange(exchangeBaseUrl)
+        assertEquals(exchangeBaseUrl, exchange.exchangeBaseUrl)
+        assertEquals("TESTKUDOS", exchange.currency)
+        assertEquals(paytoUris, exchange.paytoUris)
+
+        // added exchange got added to list
+        val exchanges = api.listExchanges()
+        assertEquals(1, exchanges.size)
+        assertEquals(exchange, exchanges[0])
+
+        // ToS are not accepted
+        val tosResult = api.getExchangeTos(exchangeBaseUrl)
+        assertEquals(null, tosResult.acceptedEtag)
+        assertEquals(tosEtag, tosResult.currentEtag)
+        assertTrue(tosResult.tos.length > 100)
+
+        // withdrawal details also show ToS as not accepted
+        val withdrawalDetails =
+            api.getWithdrawalDetailsForAmount(exchangeBaseUrl, 
Amount.zero("TESTKUDOS"))
+        assertEquals(false, withdrawalDetails.tosAccepted)
+
+        // accept ToS
+        api.setExchangeTosAccepted(exchangeBaseUrl, tosResult.currentEtag)
+        val newTosResult = api.getExchangeTos(exchangeBaseUrl)
+        assertEquals(newTosResult.currentEtag, newTosResult.acceptedEtag)
+
+        // withdrawal details now show ToS as accepted as well
+        val newWithdrawalDetails =
+            api.getWithdrawalDetailsForAmount(exchangeBaseUrl, 
Amount.zero("TESTKUDOS"))
+        assertEquals(true, newWithdrawalDetails.tosAccepted)
     }
 
 }

-- 
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]