gnunet-svn
[Top][All Lists]
Advanced

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

[taler-taler-android] branch master updated (9ee202a -> 20b1d26)


From: gnunet
Subject: [taler-taler-android] branch master updated (9ee202a -> 20b1d26)
Date: Fri, 10 Apr 2020 14:53:37 +0200

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

torsten-grote pushed a change to branch master
in repository taler-android.

    from 9ee202a  [wallet] expose notification payloads to Android UI
     new 874b52c  [wallet] add option to see exchange's fee structure
     new 20b1d26  [wallet] move akono into a normal gradle dependency

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:
 .gitignore                                         |   1 -
 .idea/gradle.xml                                   |   1 -
 akono/.gitignore                                   |   1 -
 akono/build.gradle                                 |  18 ---
 settings.gradle                                    |  18 +--
 .../src/main/java/net/taler/common/AndroidUtils.kt |   6 +
 wallet/.gitlab-ci.yml                              |   1 -
 wallet/README.md                                   |  21 +---
 wallet/build.gradle                                |   2 +-
 .../main/java/net/taler/wallet/WalletViewModel.kt  |   7 +-
 .../java/net/taler/wallet/withdraw/ExchangeFees.kt |  99 +++++++++++++++
 .../wallet/withdraw/PromptWithdrawFragment.kt      |  13 +-
 .../wallet/withdraw/SelectExchangeFragment.kt      | 136 +++++++++++++++++++++
 .../net/taler/wallet/withdraw/WithdrawManager.kt   |  42 ++-----
 .../main/res/layout/fragment_prompt_withdraw.xml   |  28 ++++-
 .../main/res/layout/fragment_select_exchange.xml   | 135 ++++++++++++++++++++
 ...{nav_header_main.xml => list_item_coin_fee.xml} |  70 +++++------
 .../src/main/res/layout/list_item_wire_fee.xml     |  40 +++---
 wallet/src/main/res/navigation/nav_graph.xml       |   8 ++
 wallet/src/main/res/values/strings.xml             |  18 +++
 20 files changed, 517 insertions(+), 148 deletions(-)
 delete mode 100644 akono/.gitignore
 delete mode 100644 akono/build.gradle
 create mode 100644 
wallet/src/main/java/net/taler/wallet/withdraw/ExchangeFees.kt
 create mode 100644 
wallet/src/main/java/net/taler/wallet/withdraw/SelectExchangeFragment.kt
 create mode 100644 wallet/src/main/res/layout/fragment_select_exchange.xml
 copy wallet/src/main/res/layout/{nav_header_main.xml => 
list_item_coin_fee.xml} (52%)
 copy merchant-terminal/src/main/res/layout/fragment_order_state.xml => 
wallet/src/main/res/layout/list_item_wire_fee.xml (61%)

diff --git a/.gitignore b/.gitignore
index 52aa44f..84587f2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,5 +15,4 @@
 /captures
 .externalNativeBuild
 .cxx
-/akono/akono.aar
 /*/release/
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index 603ebc0..d14ac7f 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -10,7 +10,6 @@
         <option name="modules">
           <set>
             <option value="$PROJECT_DIR$" />
-            <option value="$PROJECT_DIR$/akono" />
             <option value="$PROJECT_DIR$/cashier" />
             <option value="$PROJECT_DIR$/merchant-terminal" />
             <option value="$PROJECT_DIR$/taler-kotlin-common" />
diff --git a/akono/.gitignore b/akono/.gitignore
deleted file mode 100644
index 796b96d..0000000
--- a/akono/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/build
diff --git a/akono/build.gradle b/akono/build.gradle
deleted file mode 100644
index 45fbf89..0000000
--- a/akono/build.gradle
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * 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/>
- */
-
-configurations.maybeCreate("default")
-artifacts.add("default", file('akono.aar'))
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
index f254aa2..b0e66eb 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,18 +1,2 @@
-/*
- * 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/>
- */
-
-include ':akono', ':cashier', ':merchant-terminal', ':wallet'
+include ':cashier', ':merchant-terminal', ':wallet'
 include ':taler-kotlin-common'
diff --git a/taler-kotlin-common/src/main/java/net/taler/common/AndroidUtils.kt 
b/taler-kotlin-common/src/main/java/net/taler/common/AndroidUtils.kt
index ad9dab9..64d5656 100644
--- a/taler-kotlin-common/src/main/java/net/taler/common/AndroidUtils.kt
+++ b/taler-kotlin-common/src/main/java/net/taler/common/AndroidUtils.kt
@@ -22,6 +22,7 @@ import android.net.ConnectivityManager
 import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
 import android.os.Build.VERSION.SDK_INT
 import android.text.format.DateUtils.DAY_IN_MILLIS
+import android.text.format.DateUtils.FORMAT_ABBREV_ALL
 import android.text.format.DateUtils.FORMAT_ABBREV_MONTH
 import android.text.format.DateUtils.FORMAT_ABBREV_RELATIVE
 import android.text.format.DateUtils.FORMAT_NO_YEAR
@@ -88,3 +89,8 @@ fun Long.toAbsoluteTime(context: Context): CharSequence {
     val flags = FORMAT_SHOW_TIME or FORMAT_SHOW_DATE or FORMAT_SHOW_YEAR
     return formatDateTime(context, this, flags)
 }
+
+fun Long.toShortDate(context: Context): CharSequence {
+    val flags = FORMAT_SHOW_DATE or FORMAT_SHOW_YEAR or FORMAT_ABBREV_ALL
+    return formatDateTime(context, this, flags)
+}
diff --git a/wallet/.gitlab-ci.yml b/wallet/.gitlab-ci.yml
index 477acca..bbc478a 100644
--- a/wallet/.gitlab-ci.yml
+++ b/wallet/.gitlab-ci.yml
@@ -1,6 +1,5 @@
 .binary_deps:
   before_script:
-    - wget 
"https://git.taler.net/wallet-android.git/plain/akono.aar?h=binary-deps"; -O 
akono/akono.aar
     - mkdir -p app/src/main/assets
     - wget 
"https://git.taler.net/wallet-android.git/plain/taler-wallet-android.js?h=binary-deps";
 -O app/src/main/assets/taler-wallet-android.js
 
diff --git a/wallet/README.md b/wallet/README.md
index 63b128b..e4cee9c 100644
--- a/wallet/README.md
+++ b/wallet/README.md
@@ -1,40 +1,31 @@
-GNU Taler Wallet
-================
+# GNU Taler Wallet
 
 This package implements a GNU Taler wallet for Android.
 It is currently a UI for the wallet writen in TypeScript.
 
+## Building
 
-Building
-========
+Currently, building the wallet for Android requires manually copying a 
dependency:
 
-Currently, building the wallet for Android requires manually copying two
-dependencies:
-
-`akono.aar` -> `../akono/akono.aar`
 `taler-wallet-android.js` -> `src/main/assets/taler-wallet-android.js`
 
 After that, the Android wallet can be built with Gradle:
 
     $ ./gradlew build
 
-
-Obtaining Dependencies
-======================
+## Obtaining Dependencies
 
 There are two ways of obtaining the dependencies.  The easiest one is
 to use the pre-built versions, which are stored in the "binary-deps"
-branch of this repository.
+branch of the git://git.taler.net/wallet-android.git repository.
 
 An easy way to access them is using a git worktree:
 
     $ git fetch origin binary-deps
     $ git worktree add binary-deps binary-deps
-    $ cp binary-deps/akono.aar ../akono/akono.aar
     $ cp binary-deps/taler-wallet-android.js 
src/main/assets/taler-wallet-android.js
     $ git worktree remove binary-deps
 
-Alternatively, you can build them yourself from the respective repositories:
+Alternatively, you can build it yourself from the repository:
 
- * git://git.taler.net/akono.git
  * git://git.taler.net/wallet-core.git
diff --git a/wallet/build.gradle b/wallet/build.gradle
index 3e8131a..3f9047e 100644
--- a/wallet/build.gradle
+++ b/wallet/build.gradle
@@ -57,8 +57,8 @@ android {
 }
 
 dependencies {
-    implementation project(":akono")
     implementation project(":taler-kotlin-common")
+    implementation 'net.taler:akono:0.1'
 
     implementation 'com.google.android.material:material:1.1.0'
     implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
diff --git a/wallet/src/main/java/net/taler/wallet/WalletViewModel.kt 
b/wallet/src/main/java/net/taler/wallet/WalletViewModel.kt
index c16b6fc..607ce15 100644
--- a/wallet/src/main/java/net/taler/wallet/WalletViewModel.kt
+++ b/wallet/src/main/java/net/taler/wallet/WalletViewModel.kt
@@ -48,9 +48,12 @@ class WalletViewModel(val app: Application) : 
AndroidViewModel(app) {
     val showProgressBar = MutableLiveData<Boolean>()
 
     private val walletBackendApi = WalletBackendApi(app, {
-        loadBalances()
+        // nothing to do when we connect, balance will be requested by 
BalanceFragment in onStart()
     }) { payload ->
-        if (payload.getString("type") != "waiting-for-retry") {
+        if (
+            payload.getString("type") != "waiting-for-retry" && // ignore ping
+            payload.optString("operation") != "init" // ignore init 
notification
+        ) {
             Log.i(TAG, "Received notification from wallet-core: 
${payload.toString(2)}")
             loadBalances()
         }
diff --git a/wallet/src/main/java/net/taler/wallet/withdraw/ExchangeFees.kt 
b/wallet/src/main/java/net/taler/wallet/withdraw/ExchangeFees.kt
new file mode 100644
index 0000000..4494e38
--- /dev/null
+++ b/wallet/src/main/java/net/taler/wallet/withdraw/ExchangeFees.kt
@@ -0,0 +1,99 @@
+/*
+ * 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.withdraw
+
+import net.taler.common.Amount
+import net.taler.common.Timestamp
+import org.json.JSONObject
+
+data class CoinFee(
+    val coin: Amount,
+    val feeDeposit: Amount,
+    val feeRefresh: Amount,
+    val feeRefund: Amount,
+    val feeWithdraw: Amount
+)
+
+data class CoinFees(
+    val quantity: Int,
+    val coinFee: CoinFee
+)
+
+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<CoinFees>,
+    val wireFees: List<WireFee>
+) {
+    companion object {
+        fun fromExchangeWithdrawDetailsJson(json: JSONObject): ExchangeFees {
+            val earliestDepositExpiration =
+                json.getJSONObject("earliestDepositExpiration").getLong("t_ms")
+
+            val selectedDenoms = json.getJSONArray("selectedDenoms")
+            val coinFees = HashMap<CoinFee, Int>(selectedDenoms.length())
+            for (i in 0 until selectedDenoms.length()) {
+                val denom = selectedDenoms.getJSONObject(i)
+                val coinFee = CoinFee(
+                    coin = Amount.fromJsonObject(denom.getJSONObject("value")),
+                    feeDeposit = 
Amount.fromJsonObject(denom.getJSONObject("feeDeposit")),
+                    feeRefresh = 
Amount.fromJsonObject(denom.getJSONObject("feeRefresh")),
+                    feeRefund = 
Amount.fromJsonObject(denom.getJSONObject("feeRefund")),
+                    feeWithdraw = 
Amount.fromJsonObject(denom.getJSONObject("feeWithdraw"))
+                )
+                coinFees[coinFee] = (coinFees[coinFee] ?: 0) + 1
+            }
+
+            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.map { (coinFee, quantity) ->
+                    CoinFees(quantity, coinFee)
+                },
+                wireFees = wireFees
+            )
+        }
+    }
+}
diff --git 
a/wallet/src/main/java/net/taler/wallet/withdraw/PromptWithdrawFragment.kt 
b/wallet/src/main/java/net/taler/wallet/withdraw/PromptWithdrawFragment.kt
index 5d0fe63..56a2a8c 100644
--- a/wallet/src/main/java/net/taler/wallet/withdraw/PromptWithdrawFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/withdraw/PromptWithdrawFragment.kt
@@ -57,16 +57,13 @@ class PromptWithdrawFragment : Fragment() {
 
     private fun showWithdrawStatus(status: WithdrawStatus?): Any = when 
(status) {
         is WithdrawStatus.ReceivedDetails -> {
-            showContent(status.amount, status.fee, status.suggestedExchange)
+            showContent(status.amount, status.fee, status.exchange)
             confirmWithdrawButton.apply {
                 text = getString(R.string.withdraw_button_confirm)
                 setOnClickListener {
                     it.fadeOut()
                     confirmProgressBar.fadeIn()
-                    withdrawManager.acceptWithdrawal(
-                        status.talerWithdrawUri,
-                        status.suggestedExchange
-                    )
+                    withdrawManager.acceptWithdrawal(status.talerWithdrawUri, 
status.exchange)
                 }
                 isEnabled = true
             }
@@ -83,7 +80,7 @@ class PromptWithdrawFragment : Fragment() {
             model.showProgressBar.value = true
         }
         is TermsOfServiceReviewRequired -> {
-            showContent(status.amount, status.fee, status.suggestedExchange)
+            showContent(status.amount, status.fee, status.exchange)
             confirmWithdrawButton.apply {
                 text = getString(R.string.withdraw_button_tos)
                 setOnClickListener {
@@ -118,6 +115,10 @@ class PromptWithdrawFragment : Fragment() {
         exchangeIntroView.fadeIn()
         withdrawExchangeUrl.text = cleanExchange(exchange)
         withdrawExchangeUrl.fadeIn()
+        selectExchangeButton.fadeIn()
+        selectExchangeButton.setOnClickListener {
+            
findNavController().navigate(R.id.action_promptWithdraw_to_selectExchangeFragment)
+        }
 
         withdrawCard.fadeIn()
     }
diff --git 
a/wallet/src/main/java/net/taler/wallet/withdraw/SelectExchangeFragment.kt 
b/wallet/src/main/java/net/taler/wallet/withdraw/SelectExchangeFragment.kt
new file mode 100644
index 0000000..78eba53
--- /dev/null
+++ b/wallet/src/main/java/net/taler/wallet/withdraw/SelectExchangeFragment.kt
@@ -0,0 +1,136 @@
+/*
+ * 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.withdraw
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+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.R
+import net.taler.wallet.WalletViewModel
+import net.taler.wallet.withdraw.CoinFeeAdapter.CoinFeeViewHolder
+import net.taler.wallet.withdraw.WireFeeAdapter.WireFeeViewHolder
+
+class SelectExchangeFragment : Fragment() {
+
+    private val model: WalletViewModel 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()
+        withdrawFeeView.setAmount(fees.withdrawFee)
+        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<CoinFees>) : 
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: CoinFees) {
+            val fee = item.coinFee
+            coinView.text = res.getQuantityString(
+                R.plurals.exchange_fee_coin,
+                item.quantity,
+                fee.coin,
+                item.quantity
+            )
+            withdrawFeeView.text =
+                v.context.getString(R.string.exchange_fee_withdraw_fee, 
fee.feeWithdraw)
+            depositFeeView.text =
+                v.context.getString(R.string.exchange_fee_deposit_fee, 
fee.feeDeposit)
+            refreshFeeView.text =
+                v.context.getString(R.string.exchange_fee_refresh_fee, 
fee.feeRefresh)
+            refundFeeView.text =
+                v.context.getString(R.string.exchange_fee_refund_fee, 
fee.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)
+        }
+    }
+}
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 26515a5..6bcd013 100644
--- a/wallet/src/main/java/net/taler/wallet/withdraw/WithdrawManager.kt
+++ b/wallet/src/main/java/net/taler/wallet/withdraw/WithdrawManager.kt
@@ -28,19 +28,18 @@ sealed class WithdrawStatus {
     data class Loading(val talerWithdrawUri: String) : WithdrawStatus()
     data class TermsOfServiceReviewRequired(
         val talerWithdrawUri: String,
-        val exchangeBaseUrl: String,
+        val exchange: String,
         val tosText: String,
         val tosEtag: String,
         val amount: Amount,
-        val fee: Amount,
-        val suggestedExchange: String
+        val fee: Amount
     ) : WithdrawStatus()
 
     data class ReceivedDetails(
         val talerWithdrawUri: String,
+        val exchange: String,
         val amount: Amount,
-        val fee: Amount,
-        val suggestedExchange: String
+        val fee: Amount
     ) : WithdrawStatus()
 
     data class Withdrawing(val talerWithdrawUri: String) : WithdrawStatus()
@@ -54,7 +53,8 @@ class WithdrawManager(private val walletBackendApi: 
WalletBackendApi) {
     val withdrawStatus = MutableLiveData<WithdrawStatus>()
     val testWithdrawalInProgress = MutableLiveData(false)
 
-    private var currentWithdrawRequestId = 0
+    var exchangeFees: ExchangeFees? = null
+        private set
 
     fun withdrawTestkudos() {
         testWithdrawalInProgress.value = true
@@ -70,9 +70,6 @@ class WithdrawManager(private val walletBackendApi: 
WalletBackendApi) {
         }
         withdrawStatus.value = WithdrawStatus.Loading(talerWithdrawUri)
 
-        this.currentWithdrawRequestId++
-        val myWithdrawRequestId = this.currentWithdrawRequestId
-
         walletBackendApi.sendRequest("getWithdrawDetailsForUri", args) { 
isError, result ->
             if (isError) {
                 Log.e(TAG, "Error getWithdrawDetailsForUri 
${result.toString(4)}")
@@ -80,11 +77,6 @@ class WithdrawManager(private val walletBackendApi: 
WalletBackendApi) {
                 withdrawStatus.postValue(WithdrawStatus.Error(message))
                 return@sendRequest
             }
-            if (myWithdrawRequestId != this.currentWithdrawRequestId) {
-                val mismatch = "$myWithdrawRequestId != 
${this.currentWithdrawRequestId}"
-                Log.w(TAG, "Got withdraw result for different request id 
$mismatch")
-                return@sendRequest
-            }
             Log.v(TAG, "got getWithdrawDetailsForUri result")
             val status = withdrawStatus.value
             if (status !is WithdrawStatus.Loading) {
@@ -105,9 +97,6 @@ class WithdrawManager(private val walletBackendApi: 
WalletBackendApi) {
             put("selectedExchange", selectedExchange)
         }
 
-        currentWithdrawRequestId++
-        val myWithdrawRequestId = currentWithdrawRequestId
-
         walletBackendApi.sendRequest("getWithdrawDetailsForUri", args) { 
isError, result ->
             if (isError) {
                 Log.e(TAG, "Error getWithdrawDetailsForUri 
${result.toString(4)}")
@@ -115,11 +104,6 @@ class WithdrawManager(private val walletBackendApi: 
WalletBackendApi) {
                 withdrawStatus.postValue(WithdrawStatus.Error(message))
                 return@sendRequest
             }
-            if (myWithdrawRequestId != currentWithdrawRequestId) {
-                val mismatch = "$myWithdrawRequestId != 
$currentWithdrawRequestId"
-                Log.w(TAG, "Got withdraw result for different request id 
$mismatch")
-                return@sendRequest
-            }
             Log.v(TAG, "got getWithdrawDetailsForUri result (with exchange 
details)")
             val status = withdrawStatus.value
             if (status !is WithdrawStatus.Loading) {
@@ -127,12 +111,13 @@ class WithdrawManager(private val walletBackendApi: 
WalletBackendApi) {
                 return@sendRequest
             }
             val wi = result.getJSONObject("bankWithdrawDetails")
-            val suggestedExchange = wi.getString("suggestedExchange")
             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
@@ -145,16 +130,15 @@ class WithdrawManager(private val walletBackendApi: 
WalletBackendApi) {
                     WithdrawStatus.TermsOfServiceReviewRequired(
                         status.talerWithdrawUri,
                         selectedExchange, tosText, tosEtag,
-                        amount, fee,
-                        suggestedExchange
+                        amount, fee
                     )
                 )
             } else {
                 withdrawStatus.postValue(
                     ReceivedDetails(
                         status.talerWithdrawUri,
-                        amount, fee,
-                        suggestedExchange
+                        selectedExchange, amount,
+                        fee
                     )
                 )
             }
@@ -191,7 +175,7 @@ class WithdrawManager(private val walletBackendApi: 
WalletBackendApi) {
         check(s is WithdrawStatus.TermsOfServiceReviewRequired)
 
         val args = JSONObject().apply {
-            put("exchangeBaseUrl", s.exchangeBaseUrl)
+            put("exchangeBaseUrl", s.exchange)
             put("etag", s.tosEtag)
         }
         walletBackendApi.sendRequest("acceptExchangeTermsOfService", args) { 
isError, result ->
@@ -199,7 +183,7 @@ class WithdrawManager(private val walletBackendApi: 
WalletBackendApi) {
                 Log.e(TAG, "Error acceptExchangeTermsOfService 
${result.toString(4)}")
                 return@sendRequest
             }
-            val status = ReceivedDetails(s.talerWithdrawUri, s.amount, s.fee, 
s.suggestedExchange)
+            val status = ReceivedDetails(s.talerWithdrawUri, s.exchange, 
s.amount, s.fee)
             withdrawStatus.postValue(status)
         }
     }
diff --git a/wallet/src/main/res/layout/fragment_prompt_withdraw.xml 
b/wallet/src/main/res/layout/fragment_prompt_withdraw.xml
index 4372cba..c9c9402 100644
--- a/wallet/src/main/res/layout/fragment_prompt_withdraw.xml
+++ b/wallet/src/main/res/layout/fragment_prompt_withdraw.xml
@@ -64,7 +64,7 @@
         android:layout_marginTop="32dp"
         android:layout_marginEnd="16dp"
         android:gravity="center"
-        android:text="Chosen Amount"
+        android:text="@string/amount_chosen"
         android:visibility="invisible"
         app:layout_constraintBottom_toTopOf="@+id/chosenAmountView"
         app:layout_constraintEnd_toEndOf="parent"
@@ -144,18 +144,36 @@
 
     <TextView
         android:id="@+id/withdrawExchangeUrl"
-        android:layout_width="0dp"
+        android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginStart="16dp"
-        android:layout_marginEnd="16dp"
+        android:layout_marginEnd="8dp"
         android:gravity="center"
         android:textSize="24sp"
         android:visibility="invisible"
+        app:layout_constrainedWidth="true"
         app:layout_constraintBottom_toTopOf="@+id/withdrawCard"
-        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintEnd_toStartOf="@+id/selectExchangeButton"
+        app:layout_constraintHorizontal_chainStyle="packed"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toBottomOf="@+id/exchangeIntroView"
-        tools:text="long.exchange.demo.taler.net"
+        tools:text="demo.taler.net"
+        tools:visibility="visible" />
+
+    <ImageButton
+        android:id="@+id/selectExchangeButton"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginEnd="16dp"
+        android:backgroundTint="@color/colorPrimary"
+        android:contentDescription="@string/nav_exchange_fees"
+        android:src="@drawable/ic_cash_usd_outline"
+        android:tint="?attr/colorOnPrimary"
+        android:visibility="invisible"
+        app:layout_constraintBottom_toBottomOf="@+id/withdrawExchangeUrl"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toEndOf="@+id/withdrawExchangeUrl"
+        app:layout_constraintTop_toTopOf="@+id/withdrawExchangeUrl"
         tools:visibility="visible" />
 
     <ProgressBar
diff --git a/wallet/src/main/res/layout/fragment_select_exchange.xml 
b/wallet/src/main/res/layout/fragment_select_exchange.xml
new file mode 100644
index 0000000..cb8d35a
--- /dev/null
+++ b/wallet/src/main/res/layout/fragment_select_exchange.xml
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ 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/>
+  -->
+
+<androidx.core.widget.NestedScrollView 
xmlns:android="http://schemas.android.com/apk/res/android";
+    xmlns:app="http://schemas.android.com/apk/res-auto";
+    xmlns:tools="http://schemas.android.com/tools";
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+
+        <TextView
+            android:id="@+id/withdrawFeeLabel"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="16dp"
+            android:layout_marginTop="16dp"
+            android:text="@string/exchange_fee_withdrawal_fee_label"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent" />
+
+        <TextView
+            android:id="@+id/withdrawFeeView"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="16dp"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toEndOf="@+id/withdrawFeeLabel"
+            app:layout_constraintTop_toTopOf="@+id/withdrawFeeLabel"
+            tools:text="-0.23 TESTKUDOS"
+            tools:textColor="@color/red" />
+
+        <TextView
+            android:id="@+id/overheadLabel"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="16dp"
+            android:text="@string/exchange_fee_overhead_label"
+            app:layout_constraintStart_toStartOf="@+id/withdrawFeeLabel"
+            app:layout_constraintTop_toBottomOf="@+id/withdrawFeeLabel" />
+
+        <TextView
+            android:id="@+id/overheadView"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="8dp"
+            app:layout_constraintEnd_toEndOf="@+id/withdrawFeeView"
+            app:layout_constraintStart_toEndOf="@+id/overheadLabel"
+            app:layout_constraintTop_toTopOf="@+id/overheadLabel"
+            tools:text="-0.42 TESTKUDOS"
+            tools:textColor="@color/red" />
+
+        <TextView
+            android:id="@+id/expirationLabel"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="16dp"
+            android:text="@string/exchange_fee_coin_expiration_label"
+            app:layout_constraintStart_toStartOf="@+id/withdrawFeeLabel"
+            app:layout_constraintTop_toBottomOf="@+id/overheadLabel" />
+
+        <TextView
+            android:id="@+id/expirationView"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="8dp"
+            app:layout_constraintEnd_toEndOf="@+id/withdrawFeeView"
+            app:layout_constraintStart_toEndOf="@+id/expirationLabel"
+            app:layout_constraintTop_toTopOf="@+id/expirationLabel"
+            tools:text="in 5 years" />
+
+        <TextView
+            android:id="@+id/coinFeesLabel"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="16dp"
+            android:text="@string/exchange_fee_coin_fees_label"
+            android:textColor="?android:attr/textColorPrimary"
+            android:textSize="16sp"
+            app:layout_constraintStart_toStartOf="@+id/withdrawFeeLabel"
+            app:layout_constraintTop_toBottomOf="@+id/expirationLabel" />
+
+        <androidx.recyclerview.widget.RecyclerView
+            android:id="@+id/coinFeesList"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="8dp"
+            android:overScrollMode="never"
+            
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
+            app:layout_constraintEnd_toEndOf="@+id/withdrawFeeView"
+            app:layout_constraintStart_toStartOf="@+id/withdrawFeeLabel"
+            app:layout_constraintTop_toBottomOf="@+id/coinFeesLabel"
+            tools:listitem="@layout/list_item_coin_fee" />
+
+        <TextView
+            android:id="@+id/wireFeesLabel"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="16dp"
+            android:text="@string/exchange_fee_wire_fees_label"
+            android:textColor="?android:attr/textColorPrimary"
+            android:textSize="16sp"
+            app:layout_constraintStart_toStartOf="@+id/withdrawFeeLabel"
+            app:layout_constraintTop_toBottomOf="@+id/coinFeesList" />
+
+        <androidx.recyclerview.widget.RecyclerView
+            android:id="@+id/wireFeesList"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="8dp"
+            android:overScrollMode="never"
+            
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
+            app:layout_constraintEnd_toEndOf="@+id/withdrawFeeView"
+            app:layout_constraintStart_toStartOf="@+id/withdrawFeeLabel"
+            app:layout_constraintTop_toBottomOf="@+id/wireFeesLabel"
+            tools:listitem="@layout/list_item_wire_fee" />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+</androidx.core.widget.NestedScrollView>
diff --git a/wallet/src/main/res/layout/nav_header_main.xml 
b/wallet/src/main/res/layout/list_item_coin_fee.xml
similarity index 52%
copy from wallet/src/main/res/layout/nav_header_main.xml
copy to wallet/src/main/res/layout/list_item_coin_fee.xml
index 6ae6419..daf2789 100644
--- a/wallet/src/main/res/layout/nav_header_main.xml
+++ b/wallet/src/main/res/layout/list_item_coin_fee.xml
@@ -18,59 +18,61 @@
     xmlns:app="http://schemas.android.com/apk/res-auto";
     xmlns:tools="http://schemas.android.com/tools";
     android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:background="@drawable/side_nav_bar"
-    android:theme="@style/ThemeOverlay.AppCompat.Dark">
+    android:layout_height="wrap_content">
 
-    <ImageView
-        android:id="@+id/talerLogoView"
-        android:layout_width="wrap_content"
+    <TextView
+        android:id="@+id/coinView"
+        android:layout_width="0dp"
         android:layout_height="wrap_content"
-        android:layout_margin="16dp"
-        android:contentDescription="@string/nav_header_desc"
+        app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent"
-        app:srcCompat="@mipmap/ic_launcher_round" />
+        tools:text="Coin: 2 TESTKUDOS (used 3 times)" />
 
     <TextView
-        android:id="@+id/gnuView"
+        android:id="@+id/withdrawFeeView"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
         android:layout_marginStart="16dp"
-        android:layout_marginTop="8dp"
-        android:layout_marginEnd="16dp"
-        android:text="@string/nav_header_title"
-        android:textAppearance="@style/TextAppearance.AppCompat.Body1"
+        android:layout_marginTop="4dp"
         app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@+id/talerLogoView" />
+        app:layout_constraintStart_toStartOf="@+id/coinView"
+        app:layout_constraintTop_toBottomOf="@+id/coinView"
+        tools:text="Withdraw Fee: 0.01 TESTKUDOS" />
 
     <TextView
-        android:id="@+id/walletView"
-        android:layout_width="wrap_content"
+        android:id="@+id/depositFeeView"
+        android:layout_width="0dp"
         android:layout_height="wrap_content"
         android:layout_marginStart="16dp"
         android:layout_marginTop="4dp"
-        android:layout_marginBottom="16dp"
-        android:text="@string/nav_header_subtitle"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@+id/gnuView" />
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="@+id/coinView"
+        app:layout_constraintTop_toBottomOf="@+id/withdrawFeeView"
+        tools:text="Deposit Fee: 0.01 TESTKUDOS" />
 
     <TextView
-        android:id="@+id/versionView"
+        android:id="@+id/refreshFeeView"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
-        android:layout_marginStart="8dp"
-        android:layout_marginEnd="16dp"
-        android:ellipsize="end"
-        android:maxLines="1"
-        android:singleLine="true"
-        app:layout_constraintBottom_toBottomOf="@+id/walletView"
+        android:layout_marginStart="16dp"
+        android:layout_marginTop="4dp"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="@+id/coinView"
+        app:layout_constraintTop_toBottomOf="@+id/depositFeeView"
+        tools:text="Change Fee: 0.01 TESTKUDOS" />
+
+    <TextView
+        android:id="@+id/refundFeeView"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="16dp"
+        android:layout_marginTop="4dp"
+        android:layout_marginBottom="8dp"
+        app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintHorizontal_bias="0.0"
-        app:layout_constraintStart_toEndOf="@+id/walletView"
-        app:layout_constraintTop_toTopOf="@+id/walletView"
-        tools:text="0.6.9-pre15 (eae45ae4e3) (1231242342352245345345345345)" />
+        app:layout_constraintStart_toStartOf="@+id/coinView"
+        app:layout_constraintTop_toBottomOf="@+id/refreshFeeView"
+        tools:text="Refund Fee: 0.01 TESTKUDOS" />
 
 </androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/merchant-terminal/src/main/res/layout/fragment_order_state.xml 
b/wallet/src/main/res/layout/list_item_wire_fee.xml
similarity index 61%
copy from merchant-terminal/src/main/res/layout/fragment_order_state.xml
copy to wallet/src/main/res/layout/list_item_wire_fee.xml
index 42b7f90..92ede8b 100644
--- a/merchant-terminal/src/main/res/layout/fragment_order_state.xml
+++ b/wallet/src/main/res/layout/list_item_wire_fee.xml
@@ -18,34 +18,40 @@
     xmlns:app="http://schemas.android.com/apk/res-auto";
     xmlns:tools="http://schemas.android.com/tools";
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="wrap_content">
 
-    <androidx.recyclerview.widget.RecyclerView
-        android:id="@+id/orderList"
+    <TextView
+        android:id="@+id/validityView"
         android:layout_width="0dp"
-        android:layout_height="0dp"
-        app:layout_constraintBottom_toTopOf="@+id/totalView"
+        android:layout_height="wrap_content"
+        app:layout_constrainedWidth="true"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent"
-        tools:listitem="@layout/list_item_order" />
+        tools:text="Timespan: Jan 1 2020 - Dec 31 2020" />
+
+    <TextView
+        android:id="@+id/wireFeeView"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="16dp"
+        android:layout_marginTop="4dp"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/validityView"
+        tools:text="Wire Fee: 0.01 TESTKUDOS" />
 
     <TextView
-        android:id="@+id/totalView"
+        android:id="@+id/closingFeeView"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
-        android:background="@color/highlightedBackground"
-        android:elevation="2dp"
-        android:gravity="center_vertical|end"
-        android:padding="8dp"
-        android:textColor="?android:textColorPrimary"
-        android:textSize="16sp"
-        android:visibility="invisible"
+        android:layout_marginStart="16dp"
+        android:layout_marginTop="4dp"
+        android:layout_marginBottom="8dp"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@+id/orderList"
-        tools:text="Total: 23.75 TESTKUDOS"
-        tools:visibility="visible" />
+        app:layout_constraintTop_toBottomOf="@+id/wireFeeView"
+        tools:text="Closing Fee: 0.01 TESTKUDOS" />
 
 </androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/wallet/src/main/res/navigation/nav_graph.xml 
b/wallet/src/main/res/navigation/nav_graph.xml
index c39df94..f6d8598 100644
--- a/wallet/src/main/res/navigation/nav_graph.xml
+++ b/wallet/src/main/res/navigation/nav_graph.xml
@@ -96,6 +96,9 @@
             android:id="@+id/action_promptWithdraw_to_errorFragment"
             app:destination="@id/errorFragment"
             app:popUpTo="@id/showBalance" />
+        <action
+            android:id="@+id/action_promptWithdraw_to_selectExchangeFragment"
+            app:destination="@id/selectExchangeFragment" />
     </fragment>
 
     <fragment
@@ -113,6 +116,11 @@
             app:destination="@id/promptWithdraw"
             app:popUpTo="@id/showBalance" />
     </fragment>
+    <fragment
+        android:id="@+id/selectExchangeFragment"
+        android:name="net.taler.wallet.withdraw.SelectExchangeFragment"
+        android:label="@string/nav_exchange_fees"
+        tools:layout="@layout/fragment_select_exchange" />
 
     <fragment
         android:id="@+id/nav_pending_operations"
diff --git a/wallet/src/main/res/values/strings.xml 
b/wallet/src/main/res/values/strings.xml
index 31aaf14..8cbecb9 100644
--- a/wallet/src/main/res/values/strings.xml
+++ b/wallet/src/main/res/values/strings.xml
@@ -23,6 +23,7 @@
 
     <string name="nav_prompt_withdraw">Withdraw Digital Cash</string>
     <string name="nav_exchange_tos">Exchange\'s Terms of Service</string>
+    <string name="nav_exchange_fees">Exchange Fees</string>
     <string name="nav_error">Error</string>
 
     <string name="button_back">Go Back</string>
@@ -103,6 +104,23 @@
     <string name="withdraw_error_title">Withdrawal Error</string>
     <string name="withdraw_error_message">Withdrawing is currently not 
possible. Please try again later!</string>
 
+    <string name="exchange_fee_withdrawal_fee_label">Withdrawal Fee:</string>
+    <string name="exchange_fee_overhead_label">Rounding Loss:</string>
+    <string name="exchange_fee_coin_expiration_label">Earliest Coin 
Expiry:</string>
+    <string name="exchange_fee_coin_fees_label">Coin Fees</string>
+    <string name="exchange_fee_wire_fees_label">Wire Fees</string>
+    <plurals name="exchange_fee_coin">
+        <item quantity="one">Coin: %s (used %d time)</item>
+        <item quantity="other">Coin: %s (used %d times)</item>
+    </plurals>
+    <string name="exchange_fee_withdraw_fee">Withdraw Fee: %s</string>
+    <string name="exchange_fee_deposit_fee">Deposit Fee: %s</string>
+    <string name="exchange_fee_refresh_fee">Change Fee: %s</string>
+    <string name="exchange_fee_refund_fee">Refund Fee: %s</string>
+    <string name="exchange_fee_wire_fee_timespan">Timespan: %1$s - 
%2$s</string>
+    <string name="exchange_fee_wire_fee_wire_fee">Wire Fee: %s</string>
+    <string name="exchange_fee_wire_fee_closing_fee">Closing Fee: %s</string>
+
     <string name="pending_operations_title">Pending Operations</string>
     <string name="pending_operations_refuse">Refuse Proposal</string>
     <string name="pending_operations_no_action">(no action)</string>

-- 
To stop receiving notification emails like this one, please contact
address@hidden.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]