summaryrefslogtreecommitdiff
path: root/wallet/src/main/java/net/taler/wallet/exchanges
diff options
context:
space:
mode:
authorTorsten Grote <t@grobox.de>2020-07-29 14:12:50 -0300
committerTorsten Grote <t@grobox.de>2020-07-29 16:17:46 -0300
commite19ba096d57353db6b1f141da4bf170ef2d2d534 (patch)
tree8ce7d138757a73f999f8e270e69cef44aa2f781b /wallet/src/main/java/net/taler/wallet/exchanges
parentbc35e8924e652c323001f62f6781657545fa378f (diff)
downloadtaler-android-e19ba096d57353db6b1f141da4bf170ef2d2d534.tar.gz
taler-android-e19ba096d57353db6b1f141da4bf170ef2d2d534.tar.bz2
taler-android-e19ba096d57353db6b1f141da4bf170ef2d2d534.zip
[wallet] update to new wallet-core with v8 exchange API
(except payments which are still buggy)
Diffstat (limited to 'wallet/src/main/java/net/taler/wallet/exchanges')
-rw-r--r--wallet/src/main/java/net/taler/wallet/exchanges/ExchangeFees.kt95
-rw-r--r--wallet/src/main/java/net/taler/wallet/exchanges/ExchangeManager.kt3
-rw-r--r--wallet/src/main/java/net/taler/wallet/exchanges/SelectExchangeFragment.kt144
3 files changed, 240 insertions, 2 deletions
diff --git a/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeFees.kt b/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeFees.kt
new file mode 100644
index 0000000..ae90b98
--- /dev/null
+++ b/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeFees.kt
@@ -0,0 +1,95 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2020 Taler Systems S.A.
+ *
+ * GNU Taler is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 3, or (at your option) any later version.
+ *
+ * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+package net.taler.wallet.exchanges
+
+import net.taler.common.Amount
+import net.taler.common.Timestamp
+import org.json.JSONObject
+
+data class CoinFee(
+ val coin: Amount,
+ val quantity: Int,
+ val feeDeposit: Amount,
+ val feeRefresh: Amount,
+ val feeRefund: Amount,
+ val feeWithdraw: Amount
+)
+
+data class WireFee(
+ val start: Timestamp,
+ val end: Timestamp,
+ val wireFee: Amount,
+ val closingFee: Amount
+)
+
+data class ExchangeFees(
+ val withdrawFee: Amount,
+ val overhead: Amount,
+ val earliestDepositExpiration: Timestamp,
+ val coinFees: List<CoinFee>,
+ val wireFees: List<WireFee>
+) {
+ companion object {
+ fun fromExchangeWithdrawDetailsJson(json: JSONObject): ExchangeFees {
+ val earliestDepositExpiration =
+ json.getJSONObject("earliestDepositExpiration").getLong("t_ms")
+ val selectedDenoms = json.getJSONObject("selectedDenoms")
+ val denoms = selectedDenoms.getJSONArray("selectedDenoms")
+ val coinFees = ArrayList<CoinFee>(denoms.length())
+ for (i in 0 until denoms.length()) {
+ val denom = denoms.getJSONObject(i)
+ val d = denom.getJSONObject("denom")
+ val coinFee = CoinFee(
+ coin = Amount.fromJsonObject(d.getJSONObject("value")),
+ quantity = denom.getInt("count"),
+ feeDeposit = Amount.fromJsonObject(d.getJSONObject("feeDeposit")),
+ feeRefresh = Amount.fromJsonObject(d.getJSONObject("feeRefresh")),
+ feeRefund = Amount.fromJsonObject(d.getJSONObject("feeRefund")),
+ feeWithdraw = Amount.fromJsonObject(d.getJSONObject("feeWithdraw"))
+ )
+ coinFees.add(coinFee)
+ }
+
+ val wireFeesJson = json.getJSONObject("wireFees")
+ val feesForType = wireFeesJson.getJSONObject("feesForType")
+ val bankFees = feesForType.getJSONArray("x-taler-bank")
+ val wireFees = ArrayList<WireFee>(bankFees.length())
+ for (i in 0 until bankFees.length()) {
+ val fee = bankFees.getJSONObject(i)
+ val startStamp =
+ fee.getJSONObject("startStamp").getLong("t_ms")
+ val endStamp =
+ fee.getJSONObject("endStamp").getLong("t_ms")
+ val wireFee = WireFee(
+ start = Timestamp(startStamp),
+ end = Timestamp(endStamp),
+ wireFee = Amount.fromJsonObject(fee.getJSONObject("wireFee")),
+ closingFee = Amount.fromJsonObject(fee.getJSONObject("closingFee"))
+ )
+ wireFees.add(wireFee)
+ }
+
+ return ExchangeFees(
+ withdrawFee = Amount.fromJsonObject(json.getJSONObject("withdrawFee")),
+ overhead = Amount.fromJsonObject(json.getJSONObject("overhead")),
+ earliestDepositExpiration = Timestamp(earliestDepositExpiration),
+ coinFees = coinFees,
+ wireFees = wireFees
+ )
+ }
+ }
+}
diff --git a/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeManager.kt b/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeManager.kt
index 41c8f2c..9d31b5f 100644
--- a/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeManager.kt
+++ b/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeManager.kt
@@ -21,7 +21,6 @@ import androidx.lifecycle.LiveData
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.common.Event
import net.taler.common.toEvent
import net.taler.wallet.TAG
@@ -46,7 +45,7 @@ class ExchangeManager(
private fun list(): LiveData<List<ExchangeItem>> {
mProgress.value = true
- walletBackendApi.sendRequest("listExchanges", JSONObject()) { isError, result ->
+ walletBackendApi.sendRequest("listExchanges") { isError, result ->
if (isError) {
throw AssertionError("Wallet core failed to return exchanges!")
} else {
diff --git a/wallet/src/main/java/net/taler/wallet/exchanges/SelectExchangeFragment.kt b/wallet/src/main/java/net/taler/wallet/exchanges/SelectExchangeFragment.kt
new file mode 100644
index 0000000..ef4894d
--- /dev/null
+++ b/wallet/src/main/java/net/taler/wallet/exchanges/SelectExchangeFragment.kt
@@ -0,0 +1,144 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2020 Taler Systems S.A.
+ *
+ * GNU Taler is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 3, or (at your option) any later version.
+ *
+ * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+package net.taler.wallet.exchanges
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.View.GONE
+import android.view.ViewGroup
+import android.widget.TextView
+import androidx.core.content.ContextCompat.getColor
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.activityViewModels
+import androidx.recyclerview.widget.RecyclerView.Adapter
+import androidx.recyclerview.widget.RecyclerView.ViewHolder
+import kotlinx.android.synthetic.main.fragment_select_exchange.*
+import net.taler.common.Amount
+import net.taler.common.toRelativeTime
+import net.taler.common.toShortDate
+import net.taler.wallet.MainViewModel
+import net.taler.wallet.R
+import net.taler.wallet.exchanges.CoinFeeAdapter.CoinFeeViewHolder
+import net.taler.wallet.exchanges.WireFeeAdapter.WireFeeViewHolder
+
+class SelectExchangeFragment : Fragment() {
+
+ private val model: MainViewModel by activityViewModels()
+ private val withdrawManager by lazy { model.withdrawManager }
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ return inflater.inflate(R.layout.fragment_select_exchange, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ val fees = withdrawManager.exchangeFees ?: throw IllegalStateException()
+ if (fees.withdrawFee.isZero()) {
+ withdrawFeeLabel.visibility = GONE
+ withdrawFeeView.visibility = GONE
+ } else withdrawFeeView.setAmount(fees.withdrawFee)
+ if (fees.overhead.isZero()) {
+ overheadLabel.visibility = GONE
+ overheadView.visibility = GONE
+ } else overheadView.setAmount(fees.overhead)
+ expirationView.text = fees.earliestDepositExpiration.ms.toRelativeTime(requireContext())
+ coinFeesList.adapter =
+ CoinFeeAdapter(fees.coinFees)
+ wireFeesList.adapter =
+ WireFeeAdapter(fees.wireFees)
+ }
+
+ private fun TextView.setAmount(amount: Amount) {
+ if (amount.isZero()) text = amount.toString()
+ else {
+ text = getString(R.string.amount_negative, amount)
+ setTextColor(getColor(context, R.color.red))
+ }
+ }
+
+}
+
+private class CoinFeeAdapter(private val items: List<CoinFee>) : Adapter<CoinFeeViewHolder>() {
+ override fun getItemCount() = items.size
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CoinFeeViewHolder {
+ val v =
+ LayoutInflater.from(parent.context).inflate(R.layout.list_item_coin_fee, parent, false)
+ return CoinFeeViewHolder(v)
+ }
+
+ override fun onBindViewHolder(holder: CoinFeeViewHolder, position: Int) {
+ holder.bind(items[position])
+ }
+
+ private class CoinFeeViewHolder(private val v: View) : ViewHolder(v) {
+ private val res = v.context.resources
+ private val coinView: TextView = v.findViewById(R.id.coinView)
+ private val withdrawFeeView: TextView = v.findViewById(R.id.withdrawFeeView)
+ private val depositFeeView: TextView = v.findViewById(R.id.depositFeeView)
+ private val refreshFeeView: TextView = v.findViewById(R.id.refreshFeeView)
+ private val refundFeeView: TextView = v.findViewById(R.id.refundFeeView)
+ fun bind(item: CoinFee) {
+ coinView.text = res.getQuantityString(
+ R.plurals.exchange_fee_coin,
+ item.quantity,
+ item.coin,
+ item.quantity
+ )
+ withdrawFeeView.text =
+ v.context.getString(R.string.exchange_fee_withdraw_fee, item.feeWithdraw)
+ depositFeeView.text =
+ v.context.getString(R.string.exchange_fee_deposit_fee, item.feeDeposit)
+ refreshFeeView.text =
+ v.context.getString(R.string.exchange_fee_refresh_fee, item.feeRefresh)
+ refundFeeView.text =
+ v.context.getString(R.string.exchange_fee_refund_fee, item.feeRefresh)
+ }
+ }
+}
+
+private class WireFeeAdapter(private val items: List<WireFee>) : Adapter<WireFeeViewHolder>() {
+ override fun getItemCount() = items.size
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WireFeeViewHolder {
+ val v =
+ LayoutInflater.from(parent.context).inflate(R.layout.list_item_wire_fee, parent, false)
+ return WireFeeViewHolder(v)
+ }
+
+ override fun onBindViewHolder(holder: WireFeeViewHolder, position: Int) {
+ holder.bind(items[position])
+ }
+
+ private class WireFeeViewHolder(private val v: View) : ViewHolder(v) {
+ private val validityView: TextView = v.findViewById(R.id.validityView)
+ private val wireFeeView: TextView = v.findViewById(R.id.wireFeeView)
+ private val closingFeeView: TextView = v.findViewById(R.id.closingFeeView)
+ fun bind(item: WireFee) {
+ validityView.text = v.context.getString(
+ R.string.exchange_fee_wire_fee_timespan,
+ item.start.ms.toShortDate(v.context),
+ item.end.ms.toShortDate(v.context)
+ )
+ wireFeeView.text =
+ v.context.getString(R.string.exchange_fee_wire_fee_wire_fee, item.wireFee)
+ closingFeeView.text =
+ v.context.getString(R.string.exchange_fee_wire_fee_closing_fee, item.closingFee)
+ }
+ }
+}