diff options
Diffstat (limited to 'wallet/src/main/java/net/taler/wallet/withdraw/WithdrawManager.kt')
-rw-r--r-- | wallet/src/main/java/net/taler/wallet/withdraw/WithdrawManager.kt | 227 |
1 files changed, 112 insertions, 115 deletions
diff --git a/wallet/src/main/java/net/taler/wallet/withdraw/WithdrawManager.kt b/wallet/src/main/java/net/taler/wallet/withdraw/WithdrawManager.kt index ea65e7c..e14a747 100644 --- a/wallet/src/main/java/net/taler/wallet/withdraw/WithdrawManager.kt +++ b/wallet/src/main/java/net/taler/wallet/withdraw/WithdrawManager.kt @@ -17,38 +17,57 @@ package net.taler.wallet.withdraw import android.util.Log +import androidx.annotation.UiThread import androidx.lifecycle.MutableLiveData +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.module.kotlin.readValue import net.taler.common.Amount import net.taler.wallet.TAG import net.taler.wallet.backend.WalletBackendApi +import net.taler.wallet.exchanges.ExchangeFees import net.taler.wallet.exchanges.ExchangeItem import net.taler.wallet.withdraw.WithdrawStatus.ReceivedDetails import org.json.JSONObject sealed class WithdrawStatus { - data class Loading(val talerWithdrawUri: String) : WithdrawStatus() - data class TermsOfServiceReviewRequired( - val talerWithdrawUri: String, - val exchange: String, + data class Loading(val talerWithdrawUri: String? = null) : WithdrawStatus() + data class TosReviewRequired( + val talerWithdrawUri: String? = null, + val exchangeBaseUrl: String, + val amountRaw: Amount, + val amountEffective: Amount, val tosText: String, - val tosEtag: String, - val amount: Amount, - val fee: Amount + val tosEtag: String ) : WithdrawStatus() data class ReceivedDetails( - val talerWithdrawUri: String, - val exchange: String, - val amount: Amount, - val fee: Amount + val talerWithdrawUri: String? = null, + val exchangeBaseUrl: String, + val amountRaw: Amount, + val amountEffective: Amount ) : WithdrawStatus() - data class Withdrawing(val talerWithdrawUri: String) : WithdrawStatus() + object Withdrawing : WithdrawStatus() data class Success(val currency: String) : WithdrawStatus() data class Error(val message: String?) : WithdrawStatus() } -class WithdrawManager(private val walletBackendApi: WalletBackendApi) { +data class WithdrawalDetailsForUri( + val amount: Amount, + val defaultExchangeBaseUrl: String?, + val possibleExchanges: List<ExchangeItem> +) + +data class WithdrawalDetails( + val tosAccepted: Boolean, + val amountRaw: Amount, + val amountEffective: Amount +) + +class WithdrawManager( + private val walletBackendApi: WalletBackendApi, + private val mapper: ObjectMapper +) { val withdrawStatus = MutableLiveData<WithdrawStatus>() val testWithdrawalInProgress = MutableLiveData(false) @@ -58,149 +77,127 @@ class WithdrawManager(private val walletBackendApi: WalletBackendApi) { fun withdrawTestkudos() { testWithdrawalInProgress.value = true - - walletBackendApi.sendRequest("withdrawTestkudos", null) { _, _ -> + walletBackendApi.sendRequest("withdrawTestkudos") { _, _ -> testWithdrawalInProgress.postValue(false) } } - fun getWithdrawalDetails(exchangeItem: ExchangeItem, amount: Amount) { + fun getWithdrawalDetails(uri: String) { + withdrawStatus.value = WithdrawStatus.Loading(uri) val args = JSONObject().apply { - put("exchangeBaseUrl", exchangeItem.exchangeBaseUrl) - put("amount", amount.toJSONString()) + put("talerWithdrawUri", uri) } - walletBackendApi.sendRequest("getWithdrawalDetailsForAmount", args) { isError, result -> - // {"rawAmount":"TESTKUDOS:5","effectiveAmount":"TESTKUDOS:4.8","paytoUris":["payto:\/\/x-taler-bank\/bank.test.taler.net\/Exchange"],"tosAccepted":false} + walletBackendApi.sendRequest("getWithdrawalDetailsForUri", args) { isError, result -> if (isError) { - Log.e(TAG, "$result") + handleError("getWithdrawalDetailsForUri", result) + return@sendRequest + } + val details: WithdrawalDetailsForUri = mapper.readValue(result.toString()) + if (details.defaultExchangeBaseUrl == null) { + // TODO go to exchange selection screen instead + val chosenExchange = details.possibleExchanges[0].exchangeBaseUrl + getWithdrawalDetails(chosenExchange, details.amount, uri) } else { - Log.e(TAG, "$result") + getWithdrawalDetails(details.defaultExchangeBaseUrl, details.amount, uri) } } } - fun getWithdrawalInfo(talerWithdrawUri: String) { + fun getWithdrawalDetails(exchangeBaseUrl: String, amount: Amount, uri: String? = null) { + withdrawStatus.value = WithdrawStatus.Loading(uri) val args = JSONObject().apply { - put("talerWithdrawUri", talerWithdrawUri) + put("exchangeBaseUrl", exchangeBaseUrl) + put("amount", amount.toJSONString()) } - withdrawStatus.value = WithdrawStatus.Loading(talerWithdrawUri) - - walletBackendApi.sendRequest("getWithdrawDetailsForUri", args) { isError, result -> + walletBackendApi.sendRequest("getWithdrawalDetailsForAmount", args) { isError, result -> if (isError) { - Log.e(TAG, "Error getWithdrawDetailsForUri ${result.toString(4)}") - val message = if (result.has("message")) result.getString("message") else null - withdrawStatus.postValue(WithdrawStatus.Error(message)) + handleError("getWithdrawalDetailsForAmount", result) return@sendRequest } - Log.v(TAG, "got getWithdrawDetailsForUri result") - val status = withdrawStatus.value - if (status !is WithdrawStatus.Loading) { - Log.v(TAG, "ignoring withdrawal info result, not loading.") - return@sendRequest - } - val wi = result.getJSONObject("bankWithdrawDetails") - val suggestedExchange = wi.getString("suggestedExchange") - // We just use the suggested exchange, in the future there will be - // a selection dialog. - getWithdrawalInfoWithExchange(talerWithdrawUri, suggestedExchange) + val details: WithdrawalDetails = mapper.readValue(result.toString()) + if (details.tosAccepted) + withdrawStatus.value = ReceivedDetails( + talerWithdrawUri = uri, + exchangeBaseUrl = exchangeBaseUrl, + amountRaw = details.amountRaw, + amountEffective = details.amountEffective + ) + else getExchangeTos(exchangeBaseUrl, details, uri) } } - private fun getWithdrawalInfoWithExchange(talerWithdrawUri: String, selectedExchange: String) { + private fun getExchangeTos(exchangeBaseUrl: String, details: WithdrawalDetails, uri: String?) { val args = JSONObject().apply { - put("talerWithdrawUri", talerWithdrawUri) - put("selectedExchange", selectedExchange) + put("exchangeBaseUrl", exchangeBaseUrl) } - - walletBackendApi.sendRequest("getWithdrawDetailsForUri", args) { isError, result -> + walletBackendApi.sendRequest("getExchangeTos", args) { isError, result -> if (isError) { - Log.e(TAG, "Error getWithdrawDetailsForUri ${result.toString(4)}") - val message = if (result.has("message")) result.getString("message") else null - withdrawStatus.postValue(WithdrawStatus.Error(message)) - return@sendRequest - } - Log.v(TAG, "got getWithdrawDetailsForUri result (with exchange details)") - val status = withdrawStatus.value - if (status !is WithdrawStatus.Loading) { - Log.w(TAG, "ignoring withdrawal info result, not loading.") + handleError("getExchangeTos", result) return@sendRequest } - val wi = result.getJSONObject("bankWithdrawDetails") - val amount = Amount.fromJsonObject(wi.getJSONObject("amount")) - - val ei = result.getJSONObject("exchangeWithdrawDetails") - val termsOfServiceAccepted = ei.getBoolean("termsOfServiceAccepted") - - exchangeFees = ExchangeFees.fromExchangeWithdrawDetailsJson(ei) - - val withdrawFee = Amount.fromJsonObject(ei.getJSONObject("withdrawFee")) - val overhead = Amount.fromJsonObject(ei.getJSONObject("overhead")) - val fee = withdrawFee + overhead - - if (!termsOfServiceAccepted) { - val exchange = ei.getJSONObject("exchangeInfo") - val tosText = exchange.getString("termsOfServiceText") - val tosEtag = exchange.optString("termsOfServiceLastEtag", "undefined") - withdrawStatus.postValue( - WithdrawStatus.TermsOfServiceReviewRequired( - status.talerWithdrawUri, - selectedExchange, tosText, tosEtag, - amount, fee - ) - ) - } else { - withdrawStatus.postValue( - ReceivedDetails( - status.talerWithdrawUri, - selectedExchange, amount, - fee - ) - ) - } + withdrawStatus.value = WithdrawStatus.TosReviewRequired( + talerWithdrawUri = uri, + exchangeBaseUrl = exchangeBaseUrl, + amountRaw = details.amountRaw, + amountEffective = details.amountEffective, + tosText = result.getString("tos"), + tosEtag = result.getString("currentEtag") + ) } } - fun acceptWithdrawal(talerWithdrawUri: String, selectedExchange: String, currency: String) { - val args = JSONObject() - args.put("talerWithdrawUri", talerWithdrawUri) - args.put("selectedExchange", selectedExchange) - - withdrawStatus.value = WithdrawStatus.Withdrawing(talerWithdrawUri) - - walletBackendApi.sendRequest("acceptWithdrawal", args) { isError, result -> + /** + * Accept the currently displayed terms of service. + */ + fun acceptCurrentTermsOfService() { + val s = withdrawStatus.value as WithdrawStatus.TosReviewRequired + val args = JSONObject().apply { + put("exchangeBaseUrl", s.exchangeBaseUrl) + put("etag", s.tosEtag) + } + walletBackendApi.sendRequest("setExchangeTosAccepted", args) { isError, result -> if (isError) { - Log.v(TAG, "got acceptWithdrawal error result: ${result.toString(2)}") - return@sendRequest - } - Log.v(TAG, "got acceptWithdrawal result") - val status = withdrawStatus.value - if (status !is WithdrawStatus.Withdrawing) { - Log.w(TAG, "ignoring acceptWithdrawal result, invalid state: $status") + handleError("setExchangeTosAccepted", result) return@sendRequest } - withdrawStatus.postValue(WithdrawStatus.Success(currency)) + withdrawStatus.value = ReceivedDetails( + talerWithdrawUri = s.talerWithdrawUri, + exchangeBaseUrl = s.exchangeBaseUrl, + amountRaw = s.amountRaw, + amountEffective = s.amountEffective + ) } } - /** - * Accept the currently displayed terms of service. - */ - fun acceptCurrentTermsOfService() { - val s = withdrawStatus.value - check(s is WithdrawStatus.TermsOfServiceReviewRequired) + @UiThread + fun acceptWithdrawal() { + val status = withdrawStatus.value as ReceivedDetails + val operation = if (status.talerWithdrawUri == null) + "acceptManualWithdrawal" else "acceptBankIntegratedWithdrawal" val args = JSONObject().apply { - put("exchangeBaseUrl", s.exchange) - put("etag", s.tosEtag) + put("exchangeBaseUrl", status.exchangeBaseUrl) + if (status.talerWithdrawUri == null) { + put("amount", status.amountRaw) + } else { + put("talerWithdrawUri", status.talerWithdrawUri) + } } - walletBackendApi.sendRequest("acceptExchangeTermsOfService", args) { isError, result -> + withdrawStatus.value = WithdrawStatus.Withdrawing + walletBackendApi.sendRequest(operation, args) { isError, result -> if (isError) { - Log.e(TAG, "Error acceptExchangeTermsOfService ${result.toString(4)}") + handleError(operation, result) return@sendRequest } - val status = ReceivedDetails(s.talerWithdrawUri, s.exchange, s.amount, s.fee) - withdrawStatus.postValue(status) + withdrawStatus.value = WithdrawStatus.Success(status.amountRaw.currency) } } + @UiThread + private fun handleError(operation: String, result: JSONObject) { + Log.e(TAG, "Error $operation ${result.toString(2)}") + val message = if (result.has("message")) result.getString("message") else null + withdrawStatus.value = WithdrawStatus.Error(message) + } + } |