gnunet-svn
[Top][All Lists]
Advanced

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

[taler-taler-android] branch master updated (10e49b7 -> ea2abca)


From: gnunet
Subject: [taler-taler-android] branch master updated (10e49b7 -> ea2abca)
Date: Wed, 15 Apr 2020 18:56:01 +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 10e49b7  [pos] Fix OrderManagerTest
     new 8b7947a  [wallet] use floating action button for scan action
     new 8e4f85d  [wallet] move dev mode and TESTKUDOS into proper settings 
screen
     new ea32508  [wallet] rename history to transactions
     new ea2abca  [wallet] show simplified transactions per currency

The 4 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:
 build.gradle                                       |   2 +-
 wallet/build.gradle                                |   1 +
 .../main/java/net/taler/wallet/BalanceAdapter.kt   |  79 ++++++++
 .../main/java/net/taler/wallet/BalanceFragment.kt  | 205 ---------------------
 .../src/main/java/net/taler/wallet/MainActivity.kt |  17 +-
 .../src/main/java/net/taler/wallet/MainFragment.kt | 124 +++++++++++++
 .../{WalletViewModel.kt => MainViewModel.kt}       |  18 +-
 wallet/src/main/java/net/taler/wallet/Settings.kt  | 142 --------------
 .../main/java/net/taler/wallet/SettingsFragment.kt |  88 +++++++++
 .../net/taler/wallet/history/HistoryAdapter.kt     | 199 --------------------
 .../taler/wallet/payment/PromptPaymentFragment.kt  |   4 +-
 .../wallet/pending/PendingOperationsFragment.kt    |   6 +-
 .../JsonDialogFragment.kt                          |   2 +-
 .../ReserveTransaction.kt                          |   2 +-
 .../Transaction.kt}                                | 174 +++++++++--------
 .../wallet/transactions/TransactionAdapter.kt      | 143 ++++++++++++++
 .../TransactionDetailFragment.kt}                  |  32 ++--
 .../TransactionManager.kt}                         |  54 +++---
 .../TransactionsFragment.kt}                       |  86 ++++-----
 .../net/taler/wallet/withdraw/ErrorFragment.kt     |   4 +-
 .../wallet/withdraw/PromptWithdrawFragment.kt      |   4 +-
 .../wallet/withdraw/ReviewExchangeTosFragment.kt   |   4 +-
 .../wallet/withdraw/SelectExchangeFragment.kt      |   4 +-
 .../src/main/res/drawable/ic_cash_usd_outline.xml  |   1 +
 wallet/src/main/res/drawable/ic_developer_mode.xml |  10 +
 .../main/res/drawable/ic_history_black_24dp.xml    |  25 ---
 wallet/src/main/res/drawable/pending_border.xml    |   6 +-
 ...aborted.xml => transaction_payment_aborted.xml} |   0
 ...history_refresh.xml => transaction_refresh.xml} |   0
 .../{history_refund.xml => transaction_refund.xml} |   0
 ...p_accepted.xml => transaction_tip_accepted.xml} |   0
 ...p_declined.xml => transaction_tip_declined.xml} |   0
 ...ry_withdrawn.xml => transaction_withdrawal.xml} |   0
 wallet/src/main/res/layout/fragment_event_paid.xml |  30 +--
 .../main/res/layout/fragment_event_withdraw.xml    |  12 +-
 .../src/main/res/layout/fragment_main.xml          |  54 +++---
 .../res/layout/fragment_pending_operations.xml     |   2 +-
 wallet/src/main/res/layout/fragment_settings.xml   | 104 -----------
 .../src/main/res/layout/fragment_show_balance.xml  |  91 ---------
 ..._show_history.xml => fragment_transactions.xml} |   8 +-
 wallet/src/main/res/layout/history_payment.xml     |  87 ---------
 wallet/src/main/res/layout/history_receive.xml     |  92 ---------
 ...ing_row.xml => list_item_pending_operation.xml} |   0
 .../{history_row.xml => list_item_transaction.xml} |  36 ++--
 wallet/src/main/res/menu/activity_main_drawer.xml  |   4 -
 wallet/src/main/res/menu/balance.xml               |  28 ---
 .../menu/{history_event.xml => fragment_main.xml}  |   4 -
 wallet/src/main/res/menu/history.xml               |  30 ---
 .../menu/{history_event.xml => transactions.xml}   |   4 -
 .../{history_event.xml => transactions_detail.xml} |   2 +-
 wallet/src/main/res/navigation/nav_graph.xml       |  27 ++-
 wallet/src/main/res/values/strings.xml             |  79 ++++----
 wallet/src/main/res/values/styles.xml              |   8 +-
 wallet/src/main/res/xml/settings_main.xml          |  41 +++++
 .../ReserveTransactionTest.kt                      |   2 +-
 .../TransactionTest.kt}                            | 120 ++++++------
 56 files changed, 892 insertions(+), 1409 deletions(-)
 create mode 100644 wallet/src/main/java/net/taler/wallet/BalanceAdapter.kt
 delete mode 100644 wallet/src/main/java/net/taler/wallet/BalanceFragment.kt
 create mode 100644 wallet/src/main/java/net/taler/wallet/MainFragment.kt
 rename wallet/src/main/java/net/taler/wallet/{WalletViewModel.kt => 
MainViewModel.kt} (87%)
 delete mode 100644 wallet/src/main/java/net/taler/wallet/Settings.kt
 create mode 100644 wallet/src/main/java/net/taler/wallet/SettingsFragment.kt
 delete mode 100644 
wallet/src/main/java/net/taler/wallet/history/HistoryAdapter.kt
 rename wallet/src/main/java/net/taler/wallet/{history => 
transactions}/JsonDialogFragment.kt (97%)
 rename wallet/src/main/java/net/taler/wallet/{history => 
transactions}/ReserveTransaction.kt (97%)
 rename wallet/src/main/java/net/taler/wallet/{history/HistoryEvent.kt => 
transactions/Transaction.kt} (67%)
 create mode 100644 
wallet/src/main/java/net/taler/wallet/transactions/TransactionAdapter.kt
 rename wallet/src/main/java/net/taler/wallet/{history/HistoryEventFragment.kt 
=> transactions/TransactionDetailFragment.kt} (81%)
 rename wallet/src/main/java/net/taler/wallet/{history/HistoryManager.kt => 
transactions/TransactionManager.kt} (55%)
 rename wallet/src/main/java/net/taler/wallet/{history/HistoryFragment.kt => 
transactions/TransactionsFragment.kt} (52%)
 create mode 100644 wallet/src/main/res/drawable/ic_developer_mode.xml
 delete mode 100644 wallet/src/main/res/drawable/ic_history_black_24dp.xml
 rename wallet/src/main/res/drawable/{history_payment_aborted.xml => 
transaction_payment_aborted.xml} (100%)
 rename wallet/src/main/res/drawable/{history_refresh.xml => 
transaction_refresh.xml} (100%)
 rename wallet/src/main/res/drawable/{history_refund.xml => 
transaction_refund.xml} (100%)
 rename wallet/src/main/res/drawable/{history_tip_accepted.xml => 
transaction_tip_accepted.xml} (100%)
 rename wallet/src/main/res/drawable/{history_tip_declined.xml => 
transaction_tip_declined.xml} (100%)
 rename wallet/src/main/res/drawable/{history_withdrawn.xml => 
transaction_withdrawal.xml} (100%)
 copy cashier/src/main/res/layout/activity_main.xml => 
wallet/src/main/res/layout/fragment_main.xml (50%)
 delete mode 100644 wallet/src/main/res/layout/fragment_settings.xml
 delete mode 100644 wallet/src/main/res/layout/fragment_show_balance.xml
 rename wallet/src/main/res/layout/{fragment_show_history.xml => 
fragment_transactions.xml} (90%)
 delete mode 100644 wallet/src/main/res/layout/history_payment.xml
 delete mode 100644 wallet/src/main/res/layout/history_receive.xml
 rename wallet/src/main/res/layout/{pending_row.xml => 
list_item_pending_operation.xml} (100%)
 rename wallet/src/main/res/layout/{history_row.xml => 
list_item_transaction.xml} (75%)
 delete mode 100644 wallet/src/main/res/menu/balance.xml
 copy wallet/src/main/res/menu/{history_event.xml => fragment_main.xml} (87%)
 delete mode 100644 wallet/src/main/res/menu/history.xml
 copy wallet/src/main/res/menu/{history_event.xml => transactions.xml} (87%)
 rename wallet/src/main/res/menu/{history_event.xml => transactions_detail.xml} 
(94%)
 create mode 100644 wallet/src/main/res/xml/settings_main.xml
 rename wallet/src/test/java/net/taler/wallet/{history => 
transactions}/ReserveTransactionTest.kt (98%)
 rename wallet/src/test/java/net/taler/wallet/{history/HistoryEventTest.kt => 
transactions/TransactionTest.kt} (80%)

diff --git a/build.gradle b/build.gradle
index 59e7f30..71ac905 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,5 +1,5 @@
 buildscript {
-    ext.kotlin_version = '1.3.71'
+    ext.kotlin_version = '1.3.72'
     ext.nav_version = "2.2.1"
     ext.build_tools_version = "29.0.2"
     repositories {
diff --git a/wallet/build.gradle b/wallet/build.gradle
index 3d51477..0095b27 100644
--- a/wallet/build.gradle
+++ b/wallet/build.gradle
@@ -67,6 +67,7 @@ dependencies {
     implementation project(":taler-kotlin-common")
     implementation 'net.taler:akono:0.1'
 
+    implementation 'androidx.preference:preference:1.1.0'
     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/BalanceAdapter.kt 
b/wallet/src/main/java/net/taler/wallet/BalanceAdapter.kt
new file mode 100644
index 0000000..b7b2ef0
--- /dev/null
+++ b/wallet/src/main/java/net/taler/wallet/BalanceAdapter.kt
@@ -0,0 +1,79 @@
+/*
+ * 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
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.View.GONE
+import android.view.View.VISIBLE
+import android.view.ViewGroup
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import androidx.recyclerview.widget.RecyclerView.Adapter
+import net.taler.wallet.BalanceAdapter.BalanceViewHolder
+
+class BalanceAdapter(private val listener: BalanceClickListener) : 
Adapter<BalanceViewHolder>() {
+
+    private var items = emptyList<BalanceItem>()
+
+    init {
+        setHasStableIds(false)
+    }
+
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): 
BalanceViewHolder {
+        val v =
+            
LayoutInflater.from(parent.context).inflate(R.layout.list_item_balance, parent, 
false)
+        return BalanceViewHolder(v)
+    }
+
+    override fun getItemCount() = items.size
+
+    override fun onBindViewHolder(holder: BalanceViewHolder, position: Int) {
+        val item = items[position]
+        holder.bind(item)
+    }
+
+    fun setItems(items: List<BalanceItem>) {
+        this.items = items
+        this.notifyDataSetChanged()
+    }
+
+    inner class BalanceViewHolder(private val v: View) : 
RecyclerView.ViewHolder(v) {
+        private val currencyView: TextView = 
v.findViewById(R.id.balance_currency)
+        private val amountView: TextView = v.findViewById(R.id.balance_amount)
+        private val balanceInboundAmount: TextView = 
v.findViewById(R.id.balanceInboundAmount)
+        private val balanceInboundLabel: TextView = 
v.findViewById(R.id.balanceInboundLabel)
+
+        fun bind(item: BalanceItem) {
+            v.setOnClickListener { 
listener.onBalanceClick(item.available.currency) }
+            currencyView.text = item.available.currency
+            amountView.text = item.available.amountStr
+
+            val amountIncoming = item.pendingIncoming
+            if (amountIncoming.isZero()) {
+                balanceInboundAmount.visibility = GONE
+                balanceInboundLabel.visibility = GONE
+            } else {
+                balanceInboundAmount.visibility = VISIBLE
+                balanceInboundLabel.visibility = VISIBLE
+                balanceInboundAmount.text =
+                    v.context.getString(R.string.amount_positive, 
amountIncoming)
+            }
+        }
+    }
+
+}
diff --git a/wallet/src/main/java/net/taler/wallet/BalanceFragment.kt 
b/wallet/src/main/java/net/taler/wallet/BalanceFragment.kt
deleted file mode 100644
index 3d5364b..0000000
--- a/wallet/src/main/java/net/taler/wallet/BalanceFragment.kt
+++ /dev/null
@@ -1,205 +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/>
- */
-
-package net.taler.wallet
-
-import android.os.Bundle
-import android.transition.TransitionManager.beginDelayedTransition
-import android.util.Log
-import android.view.LayoutInflater
-import android.view.Menu
-import android.view.MenuInflater
-import android.view.MenuItem
-import android.view.View
-import android.view.View.GONE
-import android.view.View.VISIBLE
-import android.view.ViewGroup
-import android.widget.TextView
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.activityViewModels
-import androidx.lifecycle.Observer
-import androidx.navigation.fragment.findNavController
-import androidx.recyclerview.widget.DividerItemDecoration
-import androidx.recyclerview.widget.LinearLayoutManager
-import androidx.recyclerview.widget.LinearLayoutManager.VERTICAL
-import androidx.recyclerview.widget.RecyclerView.Adapter
-import androidx.recyclerview.widget.RecyclerView.ViewHolder
-import com.google.zxing.integration.android.IntentIntegrator
-import com.google.zxing.integration.android.IntentIntegrator.QR_CODE
-import kotlinx.android.synthetic.main.fragment_show_balance.*
-import net.taler.wallet.BalanceAdapter.BalanceViewHolder
-
-interface BalanceClickListener {
-    fun onBalanceClick()
-}
-
-class BalanceFragment : Fragment(), BalanceClickListener {
-
-    private val model: WalletViewModel by activityViewModels()
-    private val withdrawManager by lazy { model.withdrawManager }
-
-    private var reloadBalanceMenuItem: MenuItem? = null
-    private val balancesAdapter = BalanceAdapter(this)
-
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-        setHasOptionsMenu(true)
-    }
-
-    override fun onCreateView(
-        inflater: LayoutInflater,
-        container: ViewGroup?,
-        savedInstanceState: Bundle?
-    ): View? {
-        return inflater.inflate(R.layout.fragment_show_balance, container, 
false)
-    }
-
-    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
-        balancesList.apply {
-            layoutManager = LinearLayoutManager(context)
-            adapter = balancesAdapter
-            addItemDecoration(DividerItemDecoration(context, VERTICAL))
-        }
-
-        model.balances.observe(viewLifecycleOwner, Observer {
-            onBalancesChanged(it)
-        })
-
-        model.devMode.observe(viewLifecycleOwner, Observer { enabled ->
-            delayedTransition()
-            testWithdrawButton.visibility = if (enabled) VISIBLE else GONE
-            reloadBalanceMenuItem?.isVisible = enabled
-        })
-        testWithdrawButton.setOnClickListener {
-            withdrawManager.withdrawTestkudos()
-        }
-        withdrawManager.testWithdrawalInProgress.observe(viewLifecycleOwner, 
Observer { loading ->
-            Log.v("taler-wallet", "observing balance loading $loading in show 
balance")
-            testWithdrawButton.isEnabled = !loading
-            model.showProgressBar.value = loading
-        })
-
-        scanButton.setOnClickListener {
-            IntentIntegrator(activity).apply {
-                setPrompt("")
-                setBeepEnabled(true)
-                setOrientationLocked(false)
-            }.initiateScan(listOf(QR_CODE))
-        }
-    }
-
-    override fun onStart() {
-        super.onStart()
-        model.loadBalances()
-    }
-
-    override fun onOptionsItemSelected(item: MenuItem): Boolean {
-        return when (item.itemId) {
-            R.id.reload_balance -> {
-                model.loadBalances()
-                true
-            }
-            R.id.developer_mode -> {
-                item.isChecked = !item.isChecked
-                model.devMode.value = item.isChecked
-                true
-            }
-            else -> super.onOptionsItemSelected(item)
-        }
-    }
-
-    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
-        inflater.inflate(R.menu.balance, menu)
-        menu.findItem(R.id.developer_mode).isChecked = model.devMode.value!!
-        reloadBalanceMenuItem = menu.findItem(R.id.reload_balance).apply {
-            isVisible = model.devMode.value!!
-        }
-        super.onCreateOptionsMenu(menu, inflater)
-    }
-
-    private fun onBalancesChanged(balances: List<BalanceItem>) {
-        delayedTransition()
-        if (balances.isEmpty()) {
-            balancesEmptyState.visibility = VISIBLE
-            balancesList.visibility = GONE
-        } else {
-            balancesAdapter.setItems(balances)
-            balancesEmptyState.visibility = GONE
-            balancesList.visibility = VISIBLE
-        }
-    }
-
-    private fun delayedTransition() {
-        beginDelayedTransition(view as ViewGroup)
-    }
-
-    override fun onBalanceClick() {
-        findNavController().navigate(R.id.walletHistory)
-    }
-
-}
-
-class BalanceAdapter(private val listener: BalanceClickListener) : 
Adapter<BalanceViewHolder>() {
-
-    private var items = emptyList<BalanceItem>()
-
-    init {
-        setHasStableIds(false)
-    }
-
-    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): 
BalanceViewHolder {
-        val v =
-            
LayoutInflater.from(parent.context).inflate(R.layout.list_item_balance, parent, 
false)
-        return BalanceViewHolder(v)
-    }
-
-    override fun getItemCount() = items.size
-
-    override fun onBindViewHolder(holder: BalanceViewHolder, position: Int) {
-        val item = items[position]
-        holder.bind(item)
-    }
-
-    fun setItems(items: List<BalanceItem>) {
-        this.items = items
-        this.notifyDataSetChanged()
-    }
-
-    inner class BalanceViewHolder(private val v: View) : ViewHolder(v) {
-        private val currencyView: TextView = 
v.findViewById(R.id.balance_currency)
-        private val amountView: TextView = v.findViewById(R.id.balance_amount)
-        private val balanceInboundAmount: TextView = 
v.findViewById(R.id.balanceInboundAmount)
-        private val balanceInboundLabel: TextView = 
v.findViewById(R.id.balanceInboundLabel)
-
-        fun bind(item: BalanceItem) {
-            v.setOnClickListener { listener.onBalanceClick() }
-            currencyView.text = item.available.currency
-            amountView.text = item.available.amountStr
-
-            val amountIncoming = item.pendingIncoming
-            if (amountIncoming.isZero()) {
-                balanceInboundAmount.visibility = GONE
-                balanceInboundLabel.visibility = GONE
-            } else {
-                balanceInboundAmount.visibility = VISIBLE
-                balanceInboundLabel.visibility = VISIBLE
-                balanceInboundAmount.text =
-                    v.context.getString(R.string.amount_positive, 
amountIncoming)
-            }
-        }
-    }
-
-}
diff --git a/wallet/src/main/java/net/taler/wallet/MainActivity.kt 
b/wallet/src/main/java/net/taler/wallet/MainActivity.kt
index 6f0ed89..fa78b16 100644
--- a/wallet/src/main/java/net/taler/wallet/MainActivity.kt
+++ b/wallet/src/main/java/net/taler/wallet/MainActivity.kt
@@ -54,10 +54,9 @@ import 
net.taler.wallet.HostCardEmulatorService.Companion.TRIGGER_PAYMENT_ACTION
 import net.taler.wallet.refund.RefundStatus
 import java.util.Locale.ROOT
 
-class MainActivity : AppCompatActivity(), OnNavigationItemSelectedListener,
-    ResetDialogEventListener {
+class MainActivity : AppCompatActivity(), OnNavigationItemSelectedListener {
 
-    private val model: WalletViewModel by viewModels()
+    private val model: MainViewModel by viewModels()
 
     private lateinit var nav: NavController
 
@@ -76,7 +75,7 @@ class MainActivity : AppCompatActivity(), 
OnNavigationItemSelectedListener,
 
         setSupportActionBar(toolbar)
         val appBarConfiguration = AppBarConfiguration(
-            setOf(R.id.showBalance, R.id.settings, R.id.walletHistory, 
R.id.nav_pending_operations),
+            setOf(R.id.showBalance, R.id.settings, 
R.id.nav_pending_operations),
             drawer_layout
         )
         toolbar.setupWithNavController(nav, appBarConfiguration)
@@ -116,7 +115,6 @@ class MainActivity : AppCompatActivity(), 
OnNavigationItemSelectedListener,
         when (item.itemId) {
             R.id.nav_home -> nav.navigate(R.id.showBalance)
             R.id.nav_settings -> nav.navigate(R.id.settings)
-            R.id.nav_history -> nav.navigate(R.id.walletHistory)
             R.id.nav_pending_operations -> 
nav.navigate(R.id.nav_pending_operations)
         }
         drawer_layout.closeDrawer(START)
@@ -206,13 +204,4 @@ class MainActivity : AppCompatActivity(), 
OnNavigationItemSelectedListener,
         }
     }
 
-    override fun onResetConfirmed() {
-        model.dangerouslyReset()
-        Snackbar.make(nav_view, "Wallet has been reset", LENGTH_SHORT).show()
-    }
-
-    override fun onResetCancelled() {
-        Snackbar.make(nav_view, "Reset cancelled", LENGTH_SHORT).show()
-    }
-
 }
diff --git a/wallet/src/main/java/net/taler/wallet/MainFragment.kt 
b/wallet/src/main/java/net/taler/wallet/MainFragment.kt
new file mode 100644
index 0000000..e0e6f51
--- /dev/null
+++ b/wallet/src/main/java/net/taler/wallet/MainFragment.kt
@@ -0,0 +1,124 @@
+/*
+ * 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
+
+import android.os.Bundle
+import android.transition.TransitionManager.beginDelayedTransition
+import android.view.LayoutInflater
+import android.view.Menu
+import android.view.MenuInflater
+import android.view.MenuItem
+import android.view.View
+import android.view.View.GONE
+import android.view.View.VISIBLE
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.activityViewModels
+import androidx.lifecycle.Observer
+import androidx.navigation.fragment.findNavController
+import androidx.recyclerview.widget.DividerItemDecoration
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.LinearLayoutManager.VERTICAL
+import com.google.zxing.integration.android.IntentIntegrator
+import com.google.zxing.integration.android.IntentIntegrator.QR_CODE
+import kotlinx.android.synthetic.main.fragment_main.*
+
+interface BalanceClickListener {
+    fun onBalanceClick(currency: String)
+}
+
+class MainFragment : Fragment(), BalanceClickListener {
+
+    private val model: MainViewModel by activityViewModels()
+
+    private val balancesAdapter = BalanceAdapter(this)
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        setHasOptionsMenu(true)
+    }
+
+    override fun onCreateView(
+        inflater: LayoutInflater,
+        container: ViewGroup?,
+        savedInstanceState: Bundle?
+    ): View? {
+        return inflater.inflate(R.layout.fragment_main, container, false)
+    }
+
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        mainList.apply {
+            layoutManager = LinearLayoutManager(context)
+            adapter = balancesAdapter
+            addItemDecoration(DividerItemDecoration(context, VERTICAL))
+        }
+
+        model.balances.observe(viewLifecycleOwner, Observer {
+            onBalancesChanged(it.values.toList())
+        })
+
+        mainFab.setOnClickListener {
+            onScanButtonClicked()
+        }
+    }
+
+    override fun onStart() {
+        super.onStart()
+        model.loadBalances()
+    }
+
+    override fun onOptionsItemSelected(item: MenuItem): Boolean {
+        return when (item.itemId) {
+            else -> super.onOptionsItemSelected(item)
+        }
+    }
+
+    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
+        inflater.inflate(R.menu.fragment_main, menu)
+        super.onCreateOptionsMenu(menu, inflater)
+    }
+
+    private fun onScanButtonClicked() {
+        IntentIntegrator(activity).apply {
+            setPrompt("")
+            setBeepEnabled(true)
+            setOrientationLocked(false)
+        }.initiateScan(listOf(QR_CODE))
+    }
+
+    private fun onBalancesChanged(balances: List<BalanceItem>) {
+        delayedTransition()
+        if (balances.isEmpty()) {
+            mainEmptyState.visibility = VISIBLE
+            mainList.visibility = GONE
+        } else {
+            balancesAdapter.setItems(balances)
+            mainEmptyState.visibility = GONE
+            mainList.visibility = VISIBLE
+        }
+    }
+
+    private fun delayedTransition() {
+        beginDelayedTransition(view as ViewGroup)
+    }
+
+    override fun onBalanceClick(currency: String) {
+        model.transactionManager.selectedCurrency = currency
+        findNavController().navigate(R.id.nav_transactions)
+    }
+
+}
diff --git a/wallet/src/main/java/net/taler/wallet/WalletViewModel.kt 
b/wallet/src/main/java/net/taler/wallet/MainViewModel.kt
similarity index 87%
rename from wallet/src/main/java/net/taler/wallet/WalletViewModel.kt
rename to wallet/src/main/java/net/taler/wallet/MainViewModel.kt
index 607ce15..907278c 100644
--- a/wallet/src/main/java/net/taler/wallet/WalletViewModel.kt
+++ b/wallet/src/main/java/net/taler/wallet/MainViewModel.kt
@@ -28,10 +28,10 @@ import com.fasterxml.jackson.databind.ObjectMapper
 import com.fasterxml.jackson.module.kotlin.KotlinModule
 import net.taler.common.Amount
 import net.taler.wallet.backend.WalletBackendApi
-import net.taler.wallet.history.HistoryManager
 import net.taler.wallet.payment.PaymentManager
 import net.taler.wallet.pending.PendingOperationsManager
 import net.taler.wallet.refund.RefundManager
+import net.taler.wallet.transactions.TransactionManager
 import net.taler.wallet.withdraw.WithdrawManager
 import org.json.JSONObject
 
@@ -39,10 +39,10 @@ const val TAG = "taler-wallet"
 
 data class BalanceItem(val available: Amount, val pendingIncoming: Amount)
 
-class WalletViewModel(val app: Application) : AndroidViewModel(app) {
+class MainViewModel(val app: Application) : AndroidViewModel(app) {
 
-    private val mBalances = MutableLiveData<List<BalanceItem>>()
-    val balances: LiveData<List<BalanceItem>> = 
mBalances.distinctUntilChanged()
+    private val mBalances = MutableLiveData<Map<String, BalanceItem>>()
+    val balances: LiveData<Map<String, BalanceItem>> = 
mBalances.distinctUntilChanged()
 
     val devMode = MutableLiveData(BuildConfig.DEBUG)
     val showProgressBar = MutableLiveData<Boolean>()
@@ -66,7 +66,7 @@ class WalletViewModel(val app: Application) : 
AndroidViewModel(app) {
     val withdrawManager = WithdrawManager(walletBackendApi)
     val paymentManager = PaymentManager(walletBackendApi, mapper)
     val pendingOperationsManager = PendingOperationsManager(walletBackendApi)
-    val historyManager = HistoryManager(walletBackendApi, mapper)
+    val transactionManager = TransactionManager(walletBackendApi, mapper)
     val refundManager = RefundManager(walletBackendApi)
 
     override fun onCleared() {
@@ -82,7 +82,7 @@ class WalletViewModel(val app: Application) : 
AndroidViewModel(app) {
                 Log.e(TAG, "Error retrieving balances: ${result.toString(2)}")
                 return@sendRequest
             }
-            val balanceList = mutableListOf<BalanceItem>()
+            val balanceMap = HashMap<String, BalanceItem>()
             val byCurrency = result.getJSONObject("byCurrency")
             val currencyList = byCurrency.keys().asSequence().toList().sorted()
             for (currency in currencyList) {
@@ -92,9 +92,9 @@ class WalletViewModel(val app: Application) : 
AndroidViewModel(app) {
                 val jsonAmountIncoming = byCurrency.getJSONObject(currency)
                     .getJSONObject("pendingIncoming")
                 val amountIncoming = Amount.fromJsonObject(jsonAmountIncoming)
-                balanceList.add(BalanceItem(amount, amountIncoming))
+                balanceMap[currency] = BalanceItem(amount, amountIncoming)
             }
-            mBalances.postValue(balanceList)
+            mBalances.postValue(balanceMap)
             showProgressBar.postValue(false)
         }
     }
@@ -103,7 +103,7 @@ class WalletViewModel(val app: Application) : 
AndroidViewModel(app) {
     fun dangerouslyReset() {
         walletBackendApi.sendRequest("reset", null)
         withdrawManager.testWithdrawalInProgress.value = false
-        mBalances.value = emptyList()
+        mBalances.value = emptyMap()
     }
 
     fun startTunnel() {
diff --git a/wallet/src/main/java/net/taler/wallet/Settings.kt 
b/wallet/src/main/java/net/taler/wallet/Settings.kt
deleted file mode 100644
index 572c036..0000000
--- a/wallet/src/main/java/net/taler/wallet/Settings.kt
+++ /dev/null
@@ -1,142 +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/>
- */
-
-package net.taler.wallet
-
-import android.app.Dialog
-import android.content.Context
-import android.content.Intent
-import android.content.Intent.ACTION_CREATE_DOCUMENT
-import android.content.Intent.ACTION_OPEN_DOCUMENT
-import android.content.Intent.CATEGORY_OPENABLE
-import android.content.Intent.EXTRA_TITLE
-import android.os.Bundle
-import android.util.Log
-import android.view.LayoutInflater
-import android.view.View
-import android.view.View.GONE
-import android.view.View.VISIBLE
-import android.view.ViewGroup
-import androidx.appcompat.app.AlertDialog
-import androidx.fragment.app.DialogFragment
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.activityViewModels
-import androidx.lifecycle.Observer
-import kotlinx.android.synthetic.main.fragment_settings.*
-
-
-interface ResetDialogEventListener {
-    fun onResetConfirmed()
-    fun onResetCancelled()
-}
-
-
-class ResetDialogFragment : DialogFragment() {
-    private lateinit var listener: ResetDialogEventListener
-
-    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
-        return activity?.let {
-            // Use the Builder class for convenient dialog construction
-            val builder = AlertDialog.Builder(it)
-            builder.setMessage("Do you really want to reset the wallet and 
lose all coins and purchases?  Consider making a backup first.")
-                .setPositiveButton("Reset") { _, _ ->
-                    listener.onResetConfirmed()
-                }
-                .setNegativeButton("Cancel") { _, _ ->
-                    listener.onResetCancelled()
-                }
-            // Create the AlertDialog object and return it
-            builder.create()
-        } ?: throw IllegalStateException("Activity cannot be null")
-    }
-
-    override fun onAttach(context: Context) {
-        super.onAttach(context)
-        // Verify that the host activity implements the callback interface
-        try {
-            // Instantiate the NoticeDialogListener so we can send events to 
the host
-            listener = context as ResetDialogEventListener
-        } catch (e: ClassCastException) {
-            // The activity doesn't implement the interface, throw exception
-            throw ClassCastException(
-                (context.toString() +
-                        " must implement ResetDialogEventListener")
-            )
-        }
-    }
-}
-
-class Settings : Fragment() {
-
-    companion object {
-        private const val TAG = "taler-wallet"
-        private const val CREATE_FILE = 1
-        private const val PICK_FILE = 2
-    }
-
-    private val model: WalletViewModel by activityViewModels()
-
-    override fun onCreateView(
-        inflater: LayoutInflater, container: ViewGroup?,
-        savedInstanceState: Bundle?
-    ): View? {
-        return inflater.inflate(R.layout.fragment_settings, container, false)
-    }
-
-    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
-        model.devMode.observe(viewLifecycleOwner, Observer { enabled ->
-            val visibility = if (enabled) VISIBLE else GONE
-            devSettingsTitle.visibility = visibility
-            button_reset_wallet_dangerously.visibility = visibility
-        })
-
-        textView4.text = BuildConfig.VERSION_NAME
-        button_reset_wallet_dangerously.setOnClickListener {
-            val d = ResetDialogFragment()
-            d.show(parentFragmentManager, "walletResetDialog")
-        }
-        button_backup_export.setOnClickListener {
-            val intent = Intent(ACTION_CREATE_DOCUMENT).apply {
-                addCategory(CATEGORY_OPENABLE)
-                type = "application/json"
-                putExtra(EXTRA_TITLE, "taler-wallet-backup.json")
-
-                // Optionally, specify a URI for the directory that should be 
opened in
-                // the system file picker before your app creates the document.
-                //putExtra(DocumentsContract.EXTRA_INITIAL_URI, 
pickerInitialUri)
-            }
-            startActivityForResult(intent, CREATE_FILE)
-        }
-        button_backup_import.setOnClickListener {
-            val intent = Intent(ACTION_OPEN_DOCUMENT).apply {
-                addCategory(CATEGORY_OPENABLE)
-                type = "application/json"
-
-                //putExtra(DocumentsContract.EXTRA_INITIAL_URI, 
pickerInitialUri)
-            }
-            startActivityForResult(intent, PICK_FILE)
-        }
-    }
-
-    override fun onActivityResult(requestCode: Int, resultCode: Int, data: 
Intent?) {
-        if (data == null) return
-        when (requestCode) {
-            CREATE_FILE -> Log.i(TAG, "got createFile result with URL 
${data.data}")
-            PICK_FILE -> Log.i(TAG, "got pickFile result with URL 
${data.data}")
-        }
-    }
-
-}
diff --git a/wallet/src/main/java/net/taler/wallet/SettingsFragment.kt 
b/wallet/src/main/java/net/taler/wallet/SettingsFragment.kt
new file mode 100644
index 0000000..a38a5a3
--- /dev/null
+++ b/wallet/src/main/java/net/taler/wallet/SettingsFragment.kt
@@ -0,0 +1,88 @@
+/*
+ * 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
+
+import android.os.Bundle
+import android.view.View
+import androidx.appcompat.app.AlertDialog
+import androidx.fragment.app.activityViewModels
+import androidx.lifecycle.Observer
+import androidx.preference.Preference
+import androidx.preference.PreferenceFragmentCompat
+import androidx.preference.SwitchPreferenceCompat
+import com.google.android.material.snackbar.BaseTransientBottomBar.LENGTH_SHORT
+import com.google.android.material.snackbar.Snackbar
+
+
+class SettingsFragment : PreferenceFragmentCompat() {
+
+    private val model: MainViewModel by activityViewModels()
+    private val withdrawManager by lazy { model.withdrawManager }
+
+    private lateinit var prefDevMode: SwitchPreferenceCompat
+    private lateinit var prefWithdrawTest: Preference
+    private lateinit var prefReset: Preference
+
+    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: 
String?) {
+        setPreferencesFromResource(R.xml.settings_main, rootKey)
+        prefDevMode = findPreference("pref_dev_mode")!!
+        prefWithdrawTest = findPreference("pref_testkudos")!!
+        prefReset = findPreference("pref_reset")!!
+    }
+
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        super.onViewCreated(view, savedInstanceState)
+
+        model.devMode.observe(viewLifecycleOwner, Observer { enabled ->
+            prefDevMode.isChecked = enabled
+            prefWithdrawTest.isVisible = enabled
+            prefReset.isVisible = enabled
+        })
+        prefDevMode.setOnPreferenceChangeListener { _, newValue ->
+            model.devMode.value = newValue as Boolean
+            true
+        }
+
+        withdrawManager.testWithdrawalInProgress.observe(viewLifecycleOwner, 
Observer { loading ->
+            prefWithdrawTest.isEnabled = !loading
+            model.showProgressBar.value = loading
+        })
+        prefWithdrawTest.setOnPreferenceClickListener {
+            withdrawManager.withdrawTestkudos()
+            true
+        }
+
+        prefReset.setOnPreferenceClickListener {
+            showResetDialog()
+            true
+        }
+    }
+
+    private fun showResetDialog() {
+        AlertDialog.Builder(requireContext())
+            .setMessage("Do you really want to reset the wallet and lose all 
coins and purchases?")
+            .setPositiveButton("Reset") { _, _ ->
+                model.dangerouslyReset()
+                Snackbar.make(view!!, "Wallet has been reset", 
LENGTH_SHORT).show()
+            }
+            .setNegativeButton("Cancel") { _, _ ->
+                Snackbar.make(view!!, "Reset cancelled", LENGTH_SHORT).show()
+            }
+            .show()
+    }
+
+}
diff --git a/wallet/src/main/java/net/taler/wallet/history/HistoryAdapter.kt 
b/wallet/src/main/java/net/taler/wallet/history/HistoryAdapter.kt
deleted file mode 100644
index b9770fb..0000000
--- a/wallet/src/main/java/net/taler/wallet/history/HistoryAdapter.kt
+++ /dev/null
@@ -1,199 +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/>
- */
-
-package net.taler.wallet.history
-
-import android.content.Context
-import android.graphics.Paint.STRIKE_THRU_TEXT_FLAG
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.ImageView
-import android.widget.TextView
-import androidx.annotation.CallSuper
-import androidx.recyclerview.widget.RecyclerView.Adapter
-import androidx.recyclerview.widget.RecyclerView.ViewHolder
-import net.taler.common.toRelativeTime
-import net.taler.wallet.R
-import net.taler.wallet.cleanExchange
-import net.taler.wallet.history.HistoryAdapter.HistoryEventViewHolder
-
-
-internal class HistoryAdapter(
-    private val devMode: Boolean,
-    private val listener: OnEventClickListener,
-    private var history: History = History()
-) : Adapter<HistoryEventViewHolder>() {
-
-    init {
-        setHasStableIds(false)
-    }
-
-    override fun getItemViewType(position: Int): Int = history[position].layout
-
-    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): 
HistoryEventViewHolder {
-        val view = LayoutInflater.from(parent.context).inflate(viewType, 
parent, false)
-        return when (viewType) {
-            R.layout.history_receive -> HistoryReceiveViewHolder(view)
-            R.layout.history_payment -> HistoryPaymentViewHolder(view)
-            else -> GenericHistoryEventViewHolder(view)
-        }
-    }
-
-    override fun getItemCount(): Int = history.size
-
-    override fun onBindViewHolder(holder: HistoryEventViewHolder, position: 
Int) {
-        val event = history[position]
-        holder.bind(event)
-    }
-
-    fun update(updatedHistory: History) {
-        this.history = updatedHistory
-        this.notifyDataSetChanged()
-    }
-
-    internal abstract inner class HistoryEventViewHolder(private val v: View) 
: ViewHolder(v) {
-
-        protected val context: Context = v.context
-        private val icon: ImageView = v.findViewById(R.id.icon)
-        protected val title: TextView = v.findViewById(R.id.title)
-        private val time: TextView = v.findViewById(R.id.time)
-        private val selectableBackground = v.background
-
-        @CallSuper
-        open fun bind(event: HistoryEvent) {
-            if (devMode || event.detailPageLayout != 0) {
-                v.background = selectableBackground
-                v.setOnClickListener { listener.onEventClicked(event) }
-            } else {
-                v.background = null
-                v.setOnClickListener(null)
-            }
-            icon.setImageResource(event.icon)
-            if (event.title == 0) title.text = event::class.java.simpleName
-            else title.setText(event.title)
-            time.text = event.timestamp.ms.toRelativeTime(context)
-        }
-
-    }
-
-    internal inner class GenericHistoryEventViewHolder(v: View) : 
HistoryEventViewHolder(v) {
-
-        private val info: TextView = v.findViewById(R.id.info)
-
-        override fun bind(event: HistoryEvent) {
-            super.bind(event)
-            info.text = when (event) {
-                is ExchangeAddedEvent -> cleanExchange(event.exchangeBaseUrl)
-                is ExchangeUpdatedEvent -> cleanExchange(event.exchangeBaseUrl)
-                is ReserveBalanceUpdatedEvent -> 
event.reserveBalance.toString()
-                is HistoryPaymentSentEvent -> event.orderShortInfo.summary
-                is HistoryOrderAcceptedEvent -> event.orderShortInfo.summary
-                is HistoryOrderRefusedEvent -> event.orderShortInfo.summary
-                is HistoryOrderRedirectedEvent -> 
event.newOrderShortInfo.summary
-                else -> ""
-            }
-        }
-
-    }
-
-    internal inner class HistoryReceiveViewHolder(v: View) : 
HistoryEventViewHolder(v) {
-
-        private val summary: TextView = v.findViewById(R.id.summary)
-        private val amountWithdrawn: TextView = 
v.findViewById(R.id.amountWithdrawn)
-        private val paintFlags = amountWithdrawn.paintFlags
-
-        override fun bind(event: HistoryEvent) {
-            super.bind(event)
-            when (event) {
-                is HistoryWithdrawnEvent -> bind(event)
-                is HistoryRefundedEvent -> bind(event)
-                is HistoryTipAcceptedEvent -> bind(event)
-                is HistoryTipDeclinedEvent -> bind(event)
-            }
-        }
-
-        private fun bind(event: HistoryWithdrawnEvent) {
-            summary.text = cleanExchange(event.exchangeBaseUrl)
-            amountWithdrawn.text =
-                context.getString(R.string.amount_positive, 
event.amountWithdrawnEffective)
-            amountWithdrawn.paintFlags = paintFlags
-        }
-
-        private fun bind(event: HistoryRefundedEvent) {
-            summary.text = event.orderShortInfo.summary
-            amountWithdrawn.text =
-                context.getString(R.string.amount_positive, 
event.amountRefundedEffective)
-            amountWithdrawn.paintFlags = paintFlags
-        }
-
-        private fun bind(event: HistoryTipAcceptedEvent) {
-            summary.text = null
-            amountWithdrawn.text = context.getString(R.string.amount_positive, 
event.tipRaw)
-            amountWithdrawn.paintFlags = paintFlags
-        }
-
-        private fun bind(event: HistoryTipDeclinedEvent) {
-            summary.text = null
-            amountWithdrawn.text = context.getString(R.string.amount_positive, 
event.tipAmount)
-            amountWithdrawn.paintFlags = amountWithdrawn.paintFlags or 
STRIKE_THRU_TEXT_FLAG
-        }
-
-    }
-
-    internal inner class HistoryPaymentViewHolder(v: View) : 
HistoryEventViewHolder(v) {
-
-        private val summary: TextView = v.findViewById(R.id.summary)
-        private val amountPaidWithFees: TextView = 
v.findViewById(R.id.amountPaidWithFees)
-
-        override fun bind(event: HistoryEvent) {
-            super.bind(event)
-            when (event) {
-                is HistoryPaymentSentEvent -> bind(event)
-                is HistoryPaymentAbortedEvent -> bind(event)
-                is HistoryRefreshedEvent -> bind(event)
-            }
-        }
-
-        private fun bind(event: HistoryPaymentSentEvent) {
-            summary.text = event.orderShortInfo.summary
-            amountPaidWithFees.text =
-                context.getString(R.string.amount_negative, 
event.amountPaidWithFees)
-        }
-
-        private fun bind(event: HistoryPaymentAbortedEvent) {
-            summary.text = event.orderShortInfo.summary
-            amountPaidWithFees.text = 
context.getString(R.string.amount_negative, event.amountLost)
-        }
-
-        private fun bind(event: HistoryRefreshedEvent) {
-            val res = when (event.refreshReason) {
-                RefreshReason.MANUAL -> 
R.string.history_event_refresh_reason_manual
-                RefreshReason.PAY -> R.string.history_event_refresh_reason_pay
-                RefreshReason.REFUND -> 
R.string.history_event_refresh_reason_refund
-                RefreshReason.ABORT_PAY -> 
R.string.history_event_refresh_reason_abort_pay
-                RefreshReason.RECOUP -> 
R.string.history_event_refresh_reason_recoup
-                RefreshReason.BACKUP_RESTORED -> 
R.string.history_event_refresh_reason_backup_restored
-            }
-            summary.text = context.getString(res)
-            val fee = event.amountRefreshedRaw - event.amountRefreshedEffective
-            if (fee.isZero()) amountPaidWithFees.text = null
-            else amountPaidWithFees.text = 
context.getString(R.string.amount_negative, fee)
-        }
-
-    }
-
-}
diff --git 
a/wallet/src/main/java/net/taler/wallet/payment/PromptPaymentFragment.kt 
b/wallet/src/main/java/net/taler/wallet/payment/PromptPaymentFragment.kt
index 7fab695..6d31879 100644
--- a/wallet/src/main/java/net/taler/wallet/payment/PromptPaymentFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/payment/PromptPaymentFragment.kt
@@ -37,14 +37,14 @@ import net.taler.common.ContractTerms
 import net.taler.common.fadeIn
 import net.taler.common.fadeOut
 import net.taler.wallet.R
-import net.taler.wallet.WalletViewModel
+import net.taler.wallet.MainViewModel
 
 /**
  * Show a payment and ask the user to accept/decline.
  */
 class PromptPaymentFragment : Fragment(), ProductImageClickListener {
 
-    private val model: WalletViewModel by activityViewModels()
+    private val model: MainViewModel by activityViewModels()
     private val paymentManager by lazy { model.paymentManager }
     private val adapter = ProductAdapter(this)
 
diff --git 
a/wallet/src/main/java/net/taler/wallet/pending/PendingOperationsFragment.kt 
b/wallet/src/main/java/net/taler/wallet/pending/PendingOperationsFragment.kt
index d8b0896..2eb8721 100644
--- a/wallet/src/main/java/net/taler/wallet/pending/PendingOperationsFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/pending/PendingOperationsFragment.kt
@@ -39,7 +39,7 @@ import 
com.google.android.material.snackbar.Snackbar.LENGTH_SHORT
 import kotlinx.android.synthetic.main.fragment_pending_operations.*
 import net.taler.wallet.R
 import net.taler.wallet.TAG
-import net.taler.wallet.WalletViewModel
+import net.taler.wallet.MainViewModel
 import org.json.JSONObject
 
 interface PendingOperationClickListener {
@@ -49,7 +49,7 @@ interface PendingOperationClickListener {
 
 class PendingOperationsFragment : Fragment(), PendingOperationClickListener {
 
-    private val model: WalletViewModel by activityViewModels()
+    private val model: MainViewModel by activityViewModels()
     private val pendingOperationsManager by lazy { 
model.pendingOperationsManager }
 
     private val pendingAdapter = PendingOperationsAdapter(emptyList(), this)
@@ -139,7 +139,7 @@ class PendingOperationsAdapter(
 
     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): 
MyViewHolder {
         val rowView =
-            LayoutInflater.from(parent.context).inflate(R.layout.pending_row, 
parent, false)
+            
LayoutInflater.from(parent.context).inflate(R.layout.list_item_pending_operation,
 parent, false)
         return MyViewHolder(rowView)
     }
 
diff --git 
a/wallet/src/main/java/net/taler/wallet/history/JsonDialogFragment.kt 
b/wallet/src/main/java/net/taler/wallet/transactions/JsonDialogFragment.kt
similarity index 97%
rename from wallet/src/main/java/net/taler/wallet/history/JsonDialogFragment.kt
rename to 
wallet/src/main/java/net/taler/wallet/transactions/JsonDialogFragment.kt
index 5421db3..4139da8 100644
--- a/wallet/src/main/java/net/taler/wallet/history/JsonDialogFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/transactions/JsonDialogFragment.kt
@@ -14,7 +14,7 @@
  * GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-package net.taler.wallet.history
+package net.taler.wallet.transactions
 
 import android.os.Bundle
 import android.view.LayoutInflater
diff --git 
a/wallet/src/main/java/net/taler/wallet/history/ReserveTransaction.kt 
b/wallet/src/main/java/net/taler/wallet/transactions/ReserveTransaction.kt
similarity index 97%
rename from wallet/src/main/java/net/taler/wallet/history/ReserveTransaction.kt
rename to 
wallet/src/main/java/net/taler/wallet/transactions/ReserveTransaction.kt
index 6c8fdaa..e497e9a 100644
--- a/wallet/src/main/java/net/taler/wallet/history/ReserveTransaction.kt
+++ b/wallet/src/main/java/net/taler/wallet/transactions/ReserveTransaction.kt
@@ -14,7 +14,7 @@
  * GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-package net.taler.wallet.history
+package net.taler.wallet.transactions
 
 import com.fasterxml.jackson.annotation.JsonProperty
 import com.fasterxml.jackson.annotation.JsonSubTypes
diff --git a/wallet/src/main/java/net/taler/wallet/history/HistoryEvent.kt 
b/wallet/src/main/java/net/taler/wallet/transactions/Transaction.kt
similarity index 67%
rename from wallet/src/main/java/net/taler/wallet/history/HistoryEvent.kt
rename to wallet/src/main/java/net/taler/wallet/transactions/Transaction.kt
index af017ed..c0142d5 100644
--- a/wallet/src/main/java/net/taler/wallet/history/HistoryEvent.kt
+++ b/wallet/src/main/java/net/taler/wallet/transactions/Transaction.kt
@@ -14,11 +14,10 @@
  * GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-package net.taler.wallet.history
+package net.taler.wallet.transactions
 
 import androidx.annotation.DrawableRes
 import androidx.annotation.LayoutRes
-import androidx.annotation.StringRes
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties
 import com.fasterxml.jackson.annotation.JsonInclude
 import com.fasterxml.jackson.annotation.JsonInclude.Include.NON_EMPTY
@@ -32,6 +31,7 @@ import com.fasterxml.jackson.annotation.JsonTypeName
 import net.taler.common.Amount
 import net.taler.common.Timestamp
 import net.taler.wallet.R
+import net.taler.wallet.cleanExchange
 import org.json.JSONObject
 
 enum class ReserveType {
@@ -93,13 +93,24 @@ class ReserveShortInfo(
     val reserveCreationDetail: ReserveCreationDetail
 )
 
-typealias History = ArrayList<HistoryEvent>
+sealed class AmountType {
+    object Positive : AmountType()
+    object Negative : AmountType()
+    object Neutral : AmountType()
+}
+
+class DisplayAmount(
+    val amount: Amount,
+    val type: AmountType
+)
+
+typealias Transactions = ArrayList<Transaction>
 
 @JsonTypeInfo(
     use = NAME,
     include = PROPERTY,
     property = "type",
-    defaultImpl = HistoryUnknownEvent::class
+    defaultImpl = UnknownTransaction::class
 )
 /** missing:
 AuditorComplaintSent = "auditor-complained-sent",
@@ -117,41 +128,40 @@ ReserveCreated = "reserve-created",
 @JsonSubTypes(
     Type(value = ExchangeAddedEvent::class, name = "exchange-added"),
     Type(value = ExchangeUpdatedEvent::class, name = "exchange-updated"),
-    Type(value = ReserveBalanceUpdatedEvent::class, name = 
"reserve-balance-updated"),
-    Type(value = HistoryWithdrawnEvent::class, name = "withdrawn"),
-    Type(value = HistoryOrderAcceptedEvent::class, name = "order-accepted"),
-    Type(value = HistoryOrderRefusedEvent::class, name = "order-refused"),
-    Type(value = HistoryOrderRedirectedEvent::class, name = 
"order-redirected"),
-    Type(value = HistoryPaymentSentEvent::class, name = "payment-sent"),
-    Type(value = HistoryPaymentAbortedEvent::class, name = "payment-aborted"),
-    Type(value = HistoryTipAcceptedEvent::class, name = "tip-accepted"),
-    Type(value = HistoryTipDeclinedEvent::class, name = "tip-declined"),
-    Type(value = HistoryRefundedEvent::class, name = "refund"),
-    Type(value = HistoryRefreshedEvent::class, name = "refreshed")
+    Type(value = ReserveBalanceUpdatedTransaction::class, name = 
"reserve-balance-updated"),
+    Type(value = WithdrawTransaction::class, name = "withdrawn"),
+    Type(value = OrderAcceptedTransaction::class, name = "order-accepted"),
+    Type(value = OrderRefusedTransaction::class, name = "order-refused"),
+    Type(value = OrderRedirectedTransaction::class, name = "order-redirected"),
+    Type(value = PaymentTransaction::class, name = "payment-sent"),
+    Type(value = PaymentAbortedTransaction::class, name = "payment-aborted"),
+    Type(value = TipAcceptedTransaction::class, name = "tip-accepted"),
+    Type(value = TipDeclinedTransaction::class, name = "tip-declined"),
+    Type(value = RefundTransaction::class, name = "refund"),
+    Type(value = RefreshTransaction::class, name = "refreshed")
 )
 @JsonIgnoreProperties(
     value = [
         "eventId"
     ]
 )
-abstract class HistoryEvent(
+abstract class Transaction(
     val timestamp: Timestamp,
     @get:LayoutRes
-    open val layout: Int = R.layout.history_row,
-    @get:LayoutRes
     open val detailPageLayout: Int = 0,
-    @get:StringRes
-    open val title: Int = 0,
     @get:DrawableRes
     open val icon: Int = R.drawable.ic_account_balance,
     open val showToUser: Boolean = false
 ) {
+    abstract val title: String?
     open lateinit var json: JSONObject
+    open val displayAmount: DisplayAmount? = null
+    open fun isCurrency(currency: String): Boolean = true
 }
 
 
-class HistoryUnknownEvent(timestamp: Timestamp) : HistoryEvent(timestamp) {
-    override val title = R.string.history_event_unknown
+class UnknownTransaction(timestamp: Timestamp) : Transaction(timestamp) {
+    override val title: String? = null
 }
 
 @JsonTypeName("exchange-added")
@@ -159,21 +169,21 @@ class ExchangeAddedEvent(
     timestamp: Timestamp,
     val exchangeBaseUrl: String,
     val builtIn: Boolean
-) : HistoryEvent(timestamp) {
-    override val title = R.string.history_event_exchange_added
+) : Transaction(timestamp) {
+    override val title = cleanExchange(exchangeBaseUrl)
 }
 
 @JsonTypeName("exchange-updated")
 class ExchangeUpdatedEvent(
     timestamp: Timestamp,
     val exchangeBaseUrl: String
-) : HistoryEvent(timestamp) {
-    override val title = R.string.history_event_exchange_updated
+) : Transaction(timestamp) {
+    override val title = cleanExchange(exchangeBaseUrl)
 }
 
 
 @JsonTypeName("reserve-balance-updated")
-class ReserveBalanceUpdatedEvent(
+class ReserveBalanceUpdatedTransaction(
     timestamp: Timestamp,
     /**
      * Condensed information about the reserve.
@@ -192,12 +202,14 @@ class ReserveBalanceUpdatedEvent(
      * Amount that hasn't been withdrawn yet.
      */
     val reserveUnclaimedAmount: Amount
-) : HistoryEvent(timestamp) {
-    override val title = R.string.history_event_reserve_balance_updated
+) : Transaction(timestamp) {
+    override val title: String? = null
+    override val displayAmount = DisplayAmount(reserveBalance, 
AmountType.Neutral)
+    override fun isCurrency(currency: String) = reserveBalance.currency == 
currency
 }
 
 @JsonTypeName("withdrawn")
-class HistoryWithdrawnEvent(
+class WithdrawTransaction(
     timestamp: Timestamp,
     /**
      * Exchange that was withdrawn from.
@@ -218,40 +230,43 @@ class HistoryWithdrawnEvent(
      * Amount that actually was added to the wallet's balance.
      */
     val amountWithdrawnEffective: Amount
-) : HistoryEvent(timestamp) {
-    override val layout = R.layout.history_receive
+) : Transaction(timestamp) {
     override val detailPageLayout = R.layout.fragment_event_withdraw
-    override val title = R.string.history_event_withdrawn
-    override val icon = R.drawable.history_withdrawn
+    override val title = cleanExchange(exchangeBaseUrl)
+    override val icon = R.drawable.transaction_withdrawal
     override val showToUser = true
+    override val displayAmount = DisplayAmount(amountWithdrawnEffective, 
AmountType.Positive)
+    override fun isCurrency(currency: String) = amountWithdrawnRaw.currency == 
currency
 }
 
 @JsonTypeName("order-accepted")
-class HistoryOrderAcceptedEvent(
+class OrderAcceptedTransaction(
     timestamp: Timestamp,
     /**
      * Condensed info about the order.
      */
     val orderShortInfo: OrderShortInfo
-) : HistoryEvent(timestamp) {
+) : Transaction(timestamp) {
     override val icon = R.drawable.ic_add_circle
-    override val title = R.string.history_event_order_accepted
+    override val title: String? = null
+    override fun isCurrency(currency: String) = orderShortInfo.amount.currency 
== currency
 }
 
 @JsonTypeName("order-refused")
-class HistoryOrderRefusedEvent(
+class OrderRefusedTransaction(
     timestamp: Timestamp,
     /**
      * Condensed info about the order.
      */
     val orderShortInfo: OrderShortInfo
-) : HistoryEvent(timestamp) {
+) : Transaction(timestamp) {
     override val icon = R.drawable.ic_cancel
-    override val title = R.string.history_event_order_refused
+    override val title: String? = null
+    override fun isCurrency(currency: String) = orderShortInfo.amount.currency 
== currency
 }
 
 @JsonTypeName("payment-sent")
-class HistoryPaymentSentEvent(
+class PaymentTransaction(
     timestamp: Timestamp,
     /**
      * Condensed info about the order that we already paid for.
@@ -274,16 +289,17 @@ class HistoryPaymentSentEvent(
      * Session ID that the payment was (re-)submitted under.
      */
     val sessionId: String?
-) : HistoryEvent(timestamp) {
-    override val layout = R.layout.history_payment
+) : Transaction(timestamp) {
     override val detailPageLayout = R.layout.fragment_event_paid
-    override val title = R.string.history_event_payment_sent
+    override val title = orderShortInfo.summary
     override val icon = R.drawable.ic_cash_usd_outline
     override val showToUser = true
+    override val displayAmount = DisplayAmount(amountPaidWithFees, 
AmountType.Negative)
+    override fun isCurrency(currency: String) = orderShortInfo.amount.currency 
== currency
 }
 
 @JsonTypeName("payment-aborted")
-class HistoryPaymentAbortedEvent(
+class PaymentAbortedTransaction(
     timestamp: Timestamp,
     /**
      * Condensed info about the order that we already paid for.
@@ -293,15 +309,16 @@ class HistoryPaymentAbortedEvent(
      * Amount that was lost due to refund and refreshing fees.
      */
     val amountLost: Amount
-) : HistoryEvent(timestamp) {
-    override val layout = R.layout.history_payment
-    override val title = R.string.history_event_payment_aborted
-    override val icon = R.drawable.history_payment_aborted
+) : Transaction(timestamp) {
+    override val title = orderShortInfo.summary
+    override val icon = R.drawable.transaction_payment_aborted
     override val showToUser = true
+    override val displayAmount = DisplayAmount(amountLost, AmountType.Negative)
+    override fun isCurrency(currency: String) = orderShortInfo.amount.currency 
== currency
 }
 
 @JsonTypeName("refreshed")
-class HistoryRefreshedEvent(
+class RefreshTransaction(
     timestamp: Timestamp,
     /**
      * Amount that is now available again because it has
@@ -324,15 +341,24 @@ class HistoryRefreshedEvent(
      * more refresh session IDs.
      */
     val refreshGroupId: String
-) : HistoryEvent(timestamp) {
-    override val layout = R.layout.history_payment
-    override val icon = R.drawable.history_refresh
-    override val title = R.string.history_event_refreshed
+) : Transaction(timestamp) {
+    override val icon = R.drawable.transaction_refresh
+    override val title: String? = null
     override val showToUser = !(amountRefreshedRaw - 
amountRefreshedEffective).isZero()
+    override val displayAmount: DisplayAmount?
+        get() {
+            return if (showToUser) DisplayAmount(
+                amountRefreshedRaw - amountRefreshedEffective,
+                AmountType.Negative
+            )
+            else null
+        }
+
+    override fun isCurrency(currency: String) = amountRefreshedRaw.currency == 
currency
 }
 
 @JsonTypeName("order-redirected")
-class HistoryOrderRedirectedEvent(
+class OrderRedirectedTransaction(
     timestamp: Timestamp,
     /**
      * Condensed info about the new order that contains a
@@ -343,13 +369,14 @@ class HistoryOrderRedirectedEvent(
      * Condensed info about the order that we already paid for.
      */
     val alreadyPaidOrderShortInfo: OrderShortInfo
-) : HistoryEvent(timestamp) {
+) : Transaction(timestamp) {
     override val icon = R.drawable.ic_directions
-    override val title = R.string.history_event_order_redirected
+    override val title = newOrderShortInfo.summary
+    override fun isCurrency(currency: String) = 
newOrderShortInfo.amount.currency == currency
 }
 
 @JsonTypeName("tip-accepted")
-class HistoryTipAcceptedEvent(
+class TipAcceptedTransaction(
     timestamp: Timestamp,
     /**
      * Unique identifier for the tip to query more information.
@@ -359,15 +386,16 @@ class HistoryTipAcceptedEvent(
      * Raw amount of the tip, without extra fees that apply.
      */
     val tipRaw: Amount
-) : HistoryEvent(timestamp) {
-    override val icon = R.drawable.history_tip_accepted
-    override val title = R.string.history_event_tip_accepted
-    override val layout = R.layout.history_receive
+) : Transaction(timestamp) {
+    override val icon = R.drawable.transaction_tip_accepted
+    override val title: String? = null
     override val showToUser = true
+    override val displayAmount = DisplayAmount(tipRaw, AmountType.Positive)
+    override fun isCurrency(currency: String) = tipRaw.currency == currency
 }
 
 @JsonTypeName("tip-declined")
-class HistoryTipDeclinedEvent(
+class TipDeclinedTransaction(
     timestamp: Timestamp,
     /**
      * Unique identifier for the tip to query more information.
@@ -377,15 +405,16 @@ class HistoryTipDeclinedEvent(
      * Raw amount of the tip, without extra fees that apply.
      */
     val tipAmount: Amount
-) : HistoryEvent(timestamp) {
-    override val icon = R.drawable.history_tip_declined
-    override val title = R.string.history_event_tip_declined
-    override val layout = R.layout.history_receive
+) : Transaction(timestamp) {
+    override val icon = R.drawable.transaction_tip_declined
+    override val title: String? = null
     override val showToUser = true
+    override val displayAmount = DisplayAmount(tipAmount, AmountType.Neutral)
+    override fun isCurrency(currency: String) = tipAmount.currency == currency
 }
 
 @JsonTypeName("refund")
-class HistoryRefundedEvent(
+class RefundTransaction(
     timestamp: Timestamp,
     val orderShortInfo: OrderShortInfo,
     /**
@@ -406,12 +435,13 @@ class HistoryRefundedEvent(
      * Amount will be added to the wallet's balance after fees and refreshing.
      */
     val amountRefundedEffective: Amount
-) : HistoryEvent(timestamp) {
-    override val icon = R.drawable.history_refund
-    override val title = R.string.history_event_refund
-    override val layout = R.layout.history_receive
+) : Transaction(timestamp) {
+    override val icon = R.drawable.transaction_refund
+    override val title = orderShortInfo.summary
     override val detailPageLayout = R.layout.fragment_event_paid
     override val showToUser = true
+    override val displayAmount = DisplayAmount(amountRefundedEffective, 
AmountType.Positive)
+    override fun isCurrency(currency: String) = amountRefundedRaw.currency == 
currency
 }
 
 @JsonTypeInfo(
diff --git 
a/wallet/src/main/java/net/taler/wallet/transactions/TransactionAdapter.kt 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionAdapter.kt
new file mode 100644
index 0000000..809f6a9
--- /dev/null
+++ b/wallet/src/main/java/net/taler/wallet/transactions/TransactionAdapter.kt
@@ -0,0 +1,143 @@
+/*
+ * 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.transactions
+
+import android.content.Context
+import android.view.LayoutInflater
+import android.view.View
+import android.view.View.GONE
+import android.view.View.VISIBLE
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.annotation.CallSuper
+import androidx.recyclerview.widget.RecyclerView.Adapter
+import androidx.recyclerview.widget.RecyclerView.ViewHolder
+import net.taler.common.exhaustive
+import net.taler.common.toRelativeTime
+import net.taler.wallet.R
+import net.taler.wallet.transactions.TransactionAdapter.TransactionViewHolder
+
+
+internal class TransactionAdapter(
+    private val devMode: Boolean,
+    private val listener: OnEventClickListener,
+    private var transactions: Transactions = Transactions()
+) : Adapter<TransactionViewHolder>() {
+
+    init {
+        setHasStableIds(false)
+    }
+
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): 
TransactionViewHolder {
+        val view = LayoutInflater.from(parent.context)
+            .inflate(R.layout.list_item_transaction, parent, false)
+        return TransactionViewHolder(view)
+    }
+
+    override fun getItemCount(): Int = transactions.size
+
+    override fun onBindViewHolder(holder: TransactionViewHolder, position: 
Int) {
+        val event = transactions[position]
+        holder.bind(event)
+    }
+
+    fun update(updatedTransactions: Transactions) {
+        this.transactions = updatedTransactions
+        this.notifyDataSetChanged()
+    }
+
+    internal open inner class TransactionViewHolder(private val v: View) : 
ViewHolder(v) {
+
+        protected val context: Context = v.context
+
+        private val icon: ImageView = v.findViewById(R.id.icon)
+        protected val title: TextView = v.findViewById(R.id.title)
+        private val time: TextView = v.findViewById(R.id.time)
+        private val amount: TextView = v.findViewById(R.id.amount)
+
+        private val selectableBackground = v.background
+        private val amountColor = amount.currentTextColor
+
+        @CallSuper
+        open fun bind(transaction: Transaction) {
+            if (devMode || transaction.detailPageLayout != 0) {
+                v.background = selectableBackground
+                v.setOnClickListener { listener.onEventClicked(transaction) }
+            } else {
+                v.background = null
+                v.setOnClickListener(null)
+            }
+            icon.setImageResource(transaction.icon)
+
+            title.text = if (transaction.title == null) {
+                when (transaction) {
+                    is RefreshTransaction -> getRefreshTitle(transaction)
+                    is OrderAcceptedTransaction -> 
context.getString(R.string.transaction_order_accepted)
+                    is OrderRefusedTransaction -> 
context.getString(R.string.transaction_order_refused)
+                    is TipAcceptedTransaction -> 
context.getString(R.string.transaction_tip_accepted)
+                    is TipDeclinedTransaction -> 
context.getString(R.string.transaction_tip_declined)
+                    is ReserveBalanceUpdatedTransaction -> 
context.getString(R.string.transaction_reserve_balance_updated)
+                    else -> transaction::class.java.simpleName
+                }
+            } else transaction.title
+
+            time.text = transaction.timestamp.ms.toRelativeTime(context)
+            bindAmount(transaction.displayAmount)
+        }
+
+        private fun bindAmount(displayAmount: DisplayAmount?) {
+            if (displayAmount == null) {
+                amount.visibility = GONE
+            } else {
+                amount.visibility = VISIBLE
+                when (displayAmount.type) {
+                    AmountType.Positive -> {
+                        amount.text = context.getString(
+                            R.string.amount_positive, 
displayAmount.amount.amountStr
+                        )
+                        amount.setTextColor(context.getColor(R.color.green))
+                    }
+                    AmountType.Negative -> {
+                        amount.text = context.getString(
+                            R.string.amount_negative, 
displayAmount.amount.amountStr
+                        )
+                        amount.setTextColor(context.getColor(R.color.red))
+                    }
+                    AmountType.Neutral -> {
+                        amount.text = displayAmount.amount.amountStr
+                        amount.setTextColor(amountColor)
+                    }
+                }.exhaustive
+            }
+        }
+
+        private fun getRefreshTitle(transaction: RefreshTransaction): String {
+            val res = when (transaction.refreshReason) {
+                RefreshReason.MANUAL -> 
R.string.transaction_refresh_reason_manual
+                RefreshReason.PAY -> R.string.transaction_refresh_reason_pay
+                RefreshReason.REFUND -> 
R.string.transaction_refresh_reason_refund
+                RefreshReason.ABORT_PAY -> 
R.string.transaction_refresh_reason_abort_pay
+                RefreshReason.RECOUP -> 
R.string.transaction_refresh_reason_recoup
+                RefreshReason.BACKUP_RESTORED -> 
R.string.transaction_refresh_reason_backup_restored
+            }
+            return context.getString(R.string.transaction_refresh) + " " + 
context.getString(res)
+        }
+
+    }
+
+}
diff --git 
a/wallet/src/main/java/net/taler/wallet/history/HistoryEventFragment.kt 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionDetailFragment.kt
similarity index 81%
rename from 
wallet/src/main/java/net/taler/wallet/history/HistoryEventFragment.kt
rename to 
wallet/src/main/java/net/taler/wallet/transactions/TransactionDetailFragment.kt
index 0093bb5..909a7bf 100644
--- a/wallet/src/main/java/net/taler/wallet/history/HistoryEventFragment.kt
+++ 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionDetailFragment.kt
@@ -14,7 +14,7 @@
  * GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-package net.taler.wallet.history
+package net.taler.wallet.transactions
 
 import android.os.Bundle
 import android.view.LayoutInflater
@@ -34,15 +34,15 @@ import 
kotlinx.android.synthetic.main.fragment_event_withdraw.feeView
 import kotlinx.android.synthetic.main.fragment_event_withdraw.timeView
 import net.taler.common.Amount
 import net.taler.common.toAbsoluteTime
+import net.taler.wallet.MainViewModel
 import net.taler.wallet.R
-import net.taler.wallet.WalletViewModel
 import net.taler.wallet.cleanExchange
 
-class HistoryEventFragment : Fragment() {
+class TransactionDetailFragment : Fragment() {
 
-    private val model: WalletViewModel by activityViewModels()
-    private val historyManager by lazy { model.historyManager }
-    private val event by lazy { requireNotNull(historyManager.selectedEvent) }
+    private val model: MainViewModel by activityViewModels()
+    private val transactionManager by lazy { model.transactionManager }
+    private val event by lazy { 
requireNotNull(transactionManager.selectedEvent) }
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
@@ -59,15 +59,15 @@ class HistoryEventFragment : Fragment() {
     override fun onActivityCreated(savedInstanceState: Bundle?) {
         super.onActivityCreated(savedInstanceState)
         requireActivity().title =
-            getString(if (event.title != 0) event.title else 
R.string.history_detail_title)
+            if (event.title != null) event.title else 
getString(R.string.transactions_detail_title)
     }
 
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         timeView.text = event.timestamp.ms.toAbsoluteTime(requireContext())
         when (val e = event) {
-            is HistoryWithdrawnEvent -> bind(e)
-            is HistoryPaymentSentEvent -> bind(e)
-            is HistoryRefundedEvent -> bind(e)
+            is WithdrawTransaction -> bind(e)
+            is PaymentTransaction -> bind(e)
+            is RefundTransaction -> bind(e)
             else -> Toast.makeText(
                 requireContext(),
                 "event ${e.javaClass} not implement",
@@ -77,7 +77,7 @@ class HistoryEventFragment : Fragment() {
     }
 
     override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
-        inflater.inflate(R.menu.history_event, menu)
+        inflater.inflate(R.menu.transactions_detail, menu)
     }
 
     override fun onOptionsItemSelected(item: MenuItem): Boolean {
@@ -90,7 +90,7 @@ class HistoryEventFragment : Fragment() {
         }
     }
 
-    private fun bind(event: HistoryWithdrawnEvent) {
+    private fun bind(event: WithdrawTransaction) {
         effectiveAmountLabel.text = getString(R.string.withdraw_total)
         effectiveAmountView.text = event.amountWithdrawnEffective.toString()
         chosenAmountLabel.text = getString(R.string.amount_chosen)
@@ -101,14 +101,14 @@ class HistoryEventFragment : Fragment() {
         exchangeView.text = cleanExchange(event.exchangeBaseUrl)
     }
 
-    private fun bind(event: HistoryPaymentSentEvent) {
+    private fun bind(event: PaymentTransaction) {
         amountPaidWithFeesView.text = event.amountPaidWithFees.toString()
         val fee = event.amountPaidWithFees - event.orderShortInfo.amount
         bindOrderAndFee(event.orderShortInfo, fee)
     }
 
-    private fun bind(event: HistoryRefundedEvent) {
-        amountPaidWithFeesLabel.text = getString(R.string.history_event_refund)
+    private fun bind(event: RefundTransaction) {
+        amountPaidWithFeesLabel.text = getString(R.string.transaction_refund)
         amountPaidWithFeesView.setTextColor(getColor(requireContext(), 
R.color.green))
         amountPaidWithFeesView.text =
             getString(R.string.amount_positive, 
event.amountRefundedEffective.toString())
@@ -121,7 +121,7 @@ class HistoryEventFragment : Fragment() {
         feeView.text = getString(R.string.amount_negative, fee.toString())
         orderSummaryView.text = orderShortInfo.summary
         orderIdView.text =
-            getString(R.string.history_event_payment_sent_order_id, 
orderShortInfo.orderId)
+            getString(R.string.transaction_order_id, orderShortInfo.orderId)
     }
 
 }
diff --git a/wallet/src/main/java/net/taler/wallet/history/HistoryManager.kt 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt
similarity index 55%
rename from wallet/src/main/java/net/taler/wallet/history/HistoryManager.kt
rename to 
wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt
index 7ce4f5b..549b2a8 100644
--- a/wallet/src/main/java/net/taler/wallet/history/HistoryManager.kt
+++ b/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt
@@ -14,7 +14,7 @@
  * GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-package net.taler.wallet.history
+package net.taler.wallet.transactions
 
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
@@ -27,15 +27,16 @@ import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.flow.callbackFlow
 import kotlinx.coroutines.flow.onCompletion
 import kotlinx.coroutines.flow.onStart
+import kotlinx.coroutines.launch
 import net.taler.wallet.backend.WalletBackendApi
 
-sealed class HistoryResult {
-    object Error : HistoryResult()
-    class Success(val history: History) : HistoryResult()
+sealed class TransactionsResult {
+    object Error : TransactionsResult()
+    class Success(val transactions: Transactions) : TransactionsResult()
 }
 
 @Suppress("EXPERIMENTAL_API_USAGE")
-class HistoryManager(
+class TransactionManager(
     private val walletBackendApi: WalletBackendApi,
     private val mapper: ObjectMapper
 ) {
@@ -45,33 +46,40 @@ class HistoryManager(
 
     val showAll = MutableLiveData<Boolean>()
 
-    var selectedEvent: HistoryEvent? = null
+    var selectedCurrency: String? = null
+    var selectedEvent: Transaction? = null
 
-    val history: LiveData<HistoryResult> = showAll.switchMap { showAll ->
-        loadHistory(showAll)
+    val transactions: LiveData<TransactionsResult> = showAll.switchMap { 
showAll ->
+        loadTransactions(showAll)
             .onStart { mProgress.postValue(true) }
             .onCompletion { mProgress.postValue(false) }
             .asLiveData(Dispatchers.IO)
     }
 
-    private fun loadHistory(showAll: Boolean) = callbackFlow {
+    private fun loadTransactions(showAll: Boolean) = callbackFlow {
         walletBackendApi.sendRequest("getHistory", null) { isError, result ->
-            if (isError) {
-                offer(HistoryResult.Error)
+            launch(Dispatchers.Default) {
+                if (isError) {
+                    offer(TransactionsResult.Error)
+                    close()
+                    return@launch
+                }
+                val transactions = Transactions()
+                val json = result.getJSONArray("history")
+                val currency = selectedCurrency
+                for (i in 0 until json.length()) {
+                    val event: Transaction = 
mapper.readValue(json.getString(i))
+                    event.json = json.getJSONObject(i)
+                    if (currency == null || event.isCurrency(currency)) {
+                        transactions.add(event)
+                    }
+                }
+                transactions.reverse()  // show latest first
+                val filtered =
+                    if (showAll) transactions else transactions.filter { 
it.showToUser } as Transactions
+                offer(TransactionsResult.Success(filtered))
                 close()
-                return@sendRequest
             }
-            val history = History()
-            val json = result.getJSONArray("history")
-            for (i in 0 until json.length()) {
-                val event: HistoryEvent = mapper.readValue(json.getString(i))
-                event.json = json.getJSONObject(i)
-                history.add(event)
-            }
-            history.reverse()  // show latest first
-            val filtered = if (showAll) history else history.filter { 
it.showToUser } as History
-            offer(HistoryResult.Success(filtered))
-            close()
         }
         awaitClose()
     }
diff --git a/wallet/src/main/java/net/taler/wallet/history/HistoryFragment.kt 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionsFragment.kt
similarity index 52%
rename from wallet/src/main/java/net/taler/wallet/history/HistoryFragment.kt
rename to 
wallet/src/main/java/net/taler/wallet/transactions/TransactionsFragment.kt
index 73dbae0..4f62547 100644
--- a/wallet/src/main/java/net/taler/wallet/history/HistoryFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/transactions/TransactionsFragment.kt
@@ -14,7 +14,7 @@
  * GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-package net.taler.wallet.history
+package net.taler.wallet.transactions
 
 import android.os.Bundle
 import android.view.LayoutInflater
@@ -32,23 +32,22 @@ import androidx.navigation.fragment.findNavController
 import androidx.recyclerview.widget.DividerItemDecoration
 import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.recyclerview.widget.LinearLayoutManager.VERTICAL
-import kotlinx.android.synthetic.main.fragment_show_history.*
+import kotlinx.android.synthetic.main.fragment_transactions.*
 import net.taler.common.fadeIn
 import net.taler.common.fadeOut
+import net.taler.wallet.MainViewModel
 import net.taler.wallet.R
-import net.taler.wallet.WalletViewModel
 
 interface OnEventClickListener {
-    fun onEventClicked(event: HistoryEvent)
+    fun onEventClicked(event: Transaction)
 }
 
-class HistoryFragment : Fragment(), OnEventClickListener {
+class TransactionsFragment : Fragment(), OnEventClickListener {
 
-    private val model: WalletViewModel by activityViewModels()
-    private val historyManager by lazy { model.historyManager }
-    private lateinit var showAllItem: MenuItem
-    private var reloadHistoryItem: MenuItem? = null
-    private val historyAdapter by lazy { HistoryAdapter(model.devMode.value == 
true, this) }
+    private val model: MainViewModel by activityViewModels()
+    private val transactionManager by lazy { model.transactionManager }
+    private val transactionAdapter by lazy { 
TransactionAdapter(model.devMode.value == true, this) }
+    private val currency by lazy { transactionManager.selectedCurrency!! }
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
@@ -59,73 +58,66 @@ class HistoryFragment : Fragment(), OnEventClickListener {
         inflater: LayoutInflater, container: ViewGroup?,
         savedInstanceState: Bundle?
     ): View? {
-        return inflater.inflate(R.layout.fragment_show_history, container, 
false)
+        return inflater.inflate(R.layout.fragment_transactions, container, 
false)
     }
 
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
-        historyList.apply {
+        list.apply {
             layoutManager = LinearLayoutManager(context)
-            adapter = historyAdapter
+            adapter = transactionAdapter
             addItemDecoration(DividerItemDecoration(context, VERTICAL))
         }
 
-        model.devMode.observe(viewLifecycleOwner, Observer { enabled ->
-            reloadHistoryItem?.isVisible = enabled
+        transactionManager.progress.observe(viewLifecycleOwner, Observer { 
show ->
+            progressBar.visibility = if (show) VISIBLE else INVISIBLE
         })
-        historyManager.progress.observe(viewLifecycleOwner, Observer { show ->
-            historyProgressBar.visibility = if (show) VISIBLE else INVISIBLE
-        })
-        historyManager.history.observe(viewLifecycleOwner, Observer { history 
->
-            onHistoryResult(history)
+        transactionManager.transactions.observe(viewLifecycleOwner, Observer { 
result ->
+            onTransactionsResult(result)
         })
 
         // kicks off initial load, needs to be adapted if showAll state is 
ever saved
-        if (savedInstanceState == null) historyManager.showAll.value = 
model.devMode.value
+        if (savedInstanceState == null) transactionManager.showAll.value = 
model.devMode.value
+    }
+
+    override fun onActivityCreated(savedInstanceState: Bundle?) {
+        super.onActivityCreated(savedInstanceState)
+        model.balances.observe(viewLifecycleOwner, Observer { balances ->
+            balances[currency]?.available?.let { amount ->
+                requireActivity().title =
+                    getString(R.string.transactions_detail_title_balance, 
amount)
+            }
+        })
     }
 
     override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
-        inflater.inflate(R.menu.history, menu)
-        showAllItem = menu.findItem(R.id.show_all_history)
-        showAllItem.isChecked = historyManager.showAll.value == true
-        reloadHistoryItem = menu.findItem(R.id.reload_history).apply {
-            isVisible = model.devMode.value!!
-        }
+        inflater.inflate(R.menu.transactions, menu)
     }
 
     override fun onOptionsItemSelected(item: MenuItem): Boolean {
         return when (item.itemId) {
-            R.id.show_all_history -> {
-                item.isChecked = !item.isChecked
-                historyManager.showAll.value = item.isChecked
-                true
-            }
-            R.id.reload_history -> {
-                historyManager.showAll.value = showAllItem.isChecked
-                true
-            }
             else -> super.onOptionsItemSelected(item)
         }
     }
 
-    override fun onEventClicked(event: HistoryEvent) {
+    override fun onEventClicked(event: Transaction) {
         if (event.detailPageLayout != 0) {
-            historyManager.selectedEvent = event
-            
findNavController().navigate(R.id.action_walletHistory_to_historyEventFragment)
+            transactionManager.selectedEvent = event
+            
findNavController().navigate(R.id.action_nav_transactions_to_nav_transaction_detail)
         } else if (model.devMode.value == true) {
             JsonDialogFragment.new(event.json.toString(2))
                 .show(parentFragmentManager, null)
         }
     }
 
-    private fun onHistoryResult(result: HistoryResult) = when (result) {
-        HistoryResult.Error -> {
-            historyList.fadeOut()
-            historyEmptyState.text = getString(R.string.history_error)
-            historyEmptyState.fadeIn()
+    private fun onTransactionsResult(result: TransactionsResult) = when 
(result) {
+        TransactionsResult.Error -> {
+            list.fadeOut()
+            emptyState.text = getString(R.string.transactions_error)
+            emptyState.fadeIn()
         }
-        is HistoryResult.Success -> {
-            historyEmptyState.visibility = if (result.history.isEmpty()) 
VISIBLE else INVISIBLE
-            historyAdapter.update(result.history)
+        is TransactionsResult.Success -> {
+            emptyState.visibility = if (result.transactions.isEmpty()) VISIBLE 
else INVISIBLE
+            transactionAdapter.update(result.transactions)
         }
     }
 
diff --git a/wallet/src/main/java/net/taler/wallet/withdraw/ErrorFragment.kt 
b/wallet/src/main/java/net/taler/wallet/withdraw/ErrorFragment.kt
index f0f6610..fa5ab2f 100644
--- a/wallet/src/main/java/net/taler/wallet/withdraw/ErrorFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/withdraw/ErrorFragment.kt
@@ -27,11 +27,11 @@ import androidx.fragment.app.activityViewModels
 import androidx.navigation.fragment.findNavController
 import kotlinx.android.synthetic.main.fragment_error.*
 import net.taler.wallet.R
-import net.taler.wallet.WalletViewModel
+import net.taler.wallet.MainViewModel
 
 class ErrorFragment : Fragment() {
 
-    private val model: WalletViewModel by activityViewModels()
+    private val model: MainViewModel by activityViewModels()
     private val withdrawManager by lazy { model.withdrawManager }
 
     override fun onCreateView(
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 56a2a8c..747551b 100644
--- a/wallet/src/main/java/net/taler/wallet/withdraw/PromptWithdrawFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/withdraw/PromptWithdrawFragment.kt
@@ -29,7 +29,7 @@ import net.taler.common.Amount
 import net.taler.common.fadeIn
 import net.taler.common.fadeOut
 import net.taler.wallet.R
-import net.taler.wallet.WalletViewModel
+import net.taler.wallet.MainViewModel
 import net.taler.wallet.cleanExchange
 import net.taler.wallet.withdraw.WithdrawStatus.Loading
 import net.taler.wallet.withdraw.WithdrawStatus.TermsOfServiceReviewRequired
@@ -37,7 +37,7 @@ import net.taler.wallet.withdraw.WithdrawStatus.Withdrawing
 
 class PromptWithdrawFragment : Fragment() {
 
-    private val model: WalletViewModel by activityViewModels()
+    private val model: MainViewModel by activityViewModels()
     private val withdrawManager by lazy { model.withdrawManager }
 
     override fun onCreateView(
diff --git 
a/wallet/src/main/java/net/taler/wallet/withdraw/ReviewExchangeTosFragment.kt 
b/wallet/src/main/java/net/taler/wallet/withdraw/ReviewExchangeTosFragment.kt
index af76971..47b6f14 100644
--- 
a/wallet/src/main/java/net/taler/wallet/withdraw/ReviewExchangeTosFragment.kt
+++ 
b/wallet/src/main/java/net/taler/wallet/withdraw/ReviewExchangeTosFragment.kt
@@ -29,11 +29,11 @@ import 
kotlinx.android.synthetic.main.fragment_review_exchange_tos.*
 import net.taler.common.fadeIn
 import net.taler.common.fadeOut
 import net.taler.wallet.R
-import net.taler.wallet.WalletViewModel
+import net.taler.wallet.MainViewModel
 
 class ReviewExchangeTosFragment : Fragment() {
 
-    private val model: WalletViewModel by activityViewModels()
+    private val model: MainViewModel by activityViewModels()
     private val withdrawManager by lazy { model.withdrawManager }
 
     override fun onCreateView(
diff --git 
a/wallet/src/main/java/net/taler/wallet/withdraw/SelectExchangeFragment.kt 
b/wallet/src/main/java/net/taler/wallet/withdraw/SelectExchangeFragment.kt
index 1e7ee3a..fd614c6 100644
--- a/wallet/src/main/java/net/taler/wallet/withdraw/SelectExchangeFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/withdraw/SelectExchangeFragment.kt
@@ -32,13 +32,13 @@ 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.MainViewModel
 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 model: MainViewModel by activityViewModels()
     private val withdrawManager by lazy { model.withdrawManager }
 
     override fun onCreateView(
diff --git a/wallet/src/main/res/drawable/ic_cash_usd_outline.xml 
b/wallet/src/main/res/drawable/ic_cash_usd_outline.xml
index 0e26eef..aa5b85f 100644
--- a/wallet/src/main/res/drawable/ic_cash_usd_outline.xml
+++ b/wallet/src/main/res/drawable/ic_cash_usd_outline.xml
@@ -17,6 +17,7 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android";
     android:width="24dp"
     android:height="24dp"
+    android:tint="?attr/colorControlNormal"
     android:viewportWidth="24"
     android:viewportHeight="24">
     <path
diff --git a/wallet/src/main/res/drawable/ic_developer_mode.xml 
b/wallet/src/main/res/drawable/ic_developer_mode.xml
new file mode 100644
index 0000000..c401182
--- /dev/null
+++ b/wallet/src/main/res/drawable/ic_developer_mode.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android";
+    android:width="24dp"
+    android:height="24dp"
+    android:tint="?attr/colorControlNormal"
+    android:viewportWidth="24.0"
+    android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M7,5h10v2h2L19,3c0,-1.1 -0.9,-1.99 
-2,-1.99L7,1c-1.1,0 -2,0.9 -2,2v4h2L7,5zM15.41,16.59L20,12l-4.59,-4.59L14,8.83 
17.17,12 14,15.17l1.41,1.42zM10,15.17L6.83,12 10,8.83 8.59,7.41 
4,12l4.59,4.59L10,15.17zM17,19L7,19v-2L5,17v4c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 
2,-2v-4h-2v2z" />
+</vector>
diff --git a/wallet/src/main/res/drawable/ic_history_black_24dp.xml 
b/wallet/src/main/res/drawable/ic_history_black_24dp.xml
deleted file mode 100644
index 5836444..0000000
--- a/wallet/src/main/res/drawable/ic_history_black_24dp.xml
+++ /dev/null
@@ -1,25 +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/>
-  -->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android";
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportWidth="24.0"
-    android:viewportHeight="24.0">
-    <path
-        android:fillColor="#FF000000"
-        android:pathData="M13,3c-4.97,0 -9,4.03 -9,9L1,12l3.89,3.89 
0.07,0.14L9,12L6,12c0,-3.87 3.13,-7 7,-7s7,3.13 7,7 -3.13,7 -7,7c-1.93,0 
-3.68,-0.79 -4.94,-2.06l-1.42,1.42C8.27,19.99 10.51,21 13,21c4.97,0 9,-4.03 
9,-9s-4.03,-9 -9,-9zM12,8v5l4.28,2.54 0.72,-1.21 -3.5,-2.08L13.5,8L12,8z" />
-</vector>
diff --git a/wallet/src/main/res/drawable/pending_border.xml 
b/wallet/src/main/res/drawable/pending_border.xml
index c858219..0e201dc 100644
--- a/wallet/src/main/res/drawable/pending_border.xml
+++ b/wallet/src/main/res/drawable/pending_border.xml
@@ -18,14 +18,14 @@
     android:shape="rectangle">
 
     <!-- View background color -->
-    <solid android:color="@android:color/transparent"></solid>
+    <solid android:color="@android:color/transparent"/>
 
     <!-- View border color and width -->
     <stroke
         android:width="1dp"
-        android:color="@color/colorPrimary"></stroke>
+        android:color="@color/colorPrimary"/>
 
     <!-- The radius makes the corners rounded -->
-    <corners android:radius="2dp"></corners>
+    <corners android:radius="2dp"/>
 
 </shape>
\ No newline at end of file
diff --git a/wallet/src/main/res/drawable/history_payment_aborted.xml 
b/wallet/src/main/res/drawable/transaction_payment_aborted.xml
similarity index 100%
rename from wallet/src/main/res/drawable/history_payment_aborted.xml
rename to wallet/src/main/res/drawable/transaction_payment_aborted.xml
diff --git a/wallet/src/main/res/drawable/history_refresh.xml 
b/wallet/src/main/res/drawable/transaction_refresh.xml
similarity index 100%
rename from wallet/src/main/res/drawable/history_refresh.xml
rename to wallet/src/main/res/drawable/transaction_refresh.xml
diff --git a/wallet/src/main/res/drawable/history_refund.xml 
b/wallet/src/main/res/drawable/transaction_refund.xml
similarity index 100%
rename from wallet/src/main/res/drawable/history_refund.xml
rename to wallet/src/main/res/drawable/transaction_refund.xml
diff --git a/wallet/src/main/res/drawable/history_tip_accepted.xml 
b/wallet/src/main/res/drawable/transaction_tip_accepted.xml
similarity index 100%
rename from wallet/src/main/res/drawable/history_tip_accepted.xml
rename to wallet/src/main/res/drawable/transaction_tip_accepted.xml
diff --git a/wallet/src/main/res/drawable/history_tip_declined.xml 
b/wallet/src/main/res/drawable/transaction_tip_declined.xml
similarity index 100%
rename from wallet/src/main/res/drawable/history_tip_declined.xml
rename to wallet/src/main/res/drawable/transaction_tip_declined.xml
diff --git a/wallet/src/main/res/drawable/history_withdrawn.xml 
b/wallet/src/main/res/drawable/transaction_withdrawal.xml
similarity index 100%
rename from wallet/src/main/res/drawable/history_withdrawn.xml
rename to wallet/src/main/res/drawable/transaction_withdrawal.xml
diff --git a/wallet/src/main/res/layout/fragment_event_paid.xml 
b/wallet/src/main/res/layout/fragment_event_paid.xml
index 4485744..3f17464 100644
--- a/wallet/src/main/res/layout/fragment_event_paid.xml
+++ b/wallet/src/main/res/layout/fragment_event_paid.xml
@@ -20,7 +20,7 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:fillViewport="true"
-    tools:context=".history.HistoryEventFragment">
+    tools:context=".transactions.TransactionDetailFragment">
 
     <androidx.constraintlayout.widget.ConstraintLayout
         android:layout_width="match_parent"
@@ -28,7 +28,7 @@
 
         <TextView
             android:id="@+id/timeView"
-            style="@style/HistoryEventLabel.Time"
+            style="@style/TransactionLabel.Time"
             app:layout_constraintBottom_toTopOf="@+id/amountPaidWithFeesLabel"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent"
@@ -38,8 +38,8 @@
 
         <TextView
             android:id="@+id/amountPaidWithFeesLabel"
-            style="@style/HistoryEventLabel"
-            android:text="@string/history_event_payment_sent_paid"
+            style="@style/TransactionLabel"
+            android:text="@string/transaction_paid"
             app:layout_constraintBottom_toTopOf="@+id/amountPaidWithFeesView"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent"
@@ -47,7 +47,7 @@
 
         <TextView
             android:id="@+id/amountPaidWithFeesView"
-            style="@style/HistoryEventContent"
+            style="@style/TransactionContent"
             android:textColor="@color/red"
             app:layout_constraintBottom_toTopOf="@+id/orderAmountLabel"
             app:layout_constraintEnd_toEndOf="parent"
@@ -57,8 +57,8 @@
 
         <TextView
             android:id="@+id/orderAmountLabel"
-            style="@style/HistoryEventLabel"
-            android:text="@string/history_event_payment_sent_amount"
+            style="@style/TransactionLabel"
+            android:text="@string/transaction_order_total"
             app:layout_constraintBottom_toTopOf="@+id/orderAmountView"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent"
@@ -66,7 +66,7 @@
 
         <TextView
             android:id="@+id/orderAmountView"
-            style="@style/HistoryEventContent"
+            style="@style/TransactionContent"
             app:layout_constraintBottom_toTopOf="@+id/feeLabel"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent"
@@ -75,7 +75,7 @@
 
         <TextView
             android:id="@+id/feeLabel"
-            style="@style/HistoryEventLabel"
+            style="@style/TransactionLabel"
             android:text="@string/withdraw_fees"
             app:layout_constraintBottom_toTopOf="@+id/feeView"
             app:layout_constraintEnd_toEndOf="parent"
@@ -84,7 +84,7 @@
 
         <TextView
             android:id="@+id/feeView"
-            style="@style/HistoryEventContent"
+            style="@style/TransactionContent"
             android:textColor="@color/red"
             app:layout_constraintBottom_toTopOf="@+id/orderSummaryLabel"
             app:layout_constraintEnd_toEndOf="parent"
@@ -94,8 +94,8 @@
 
         <TextView
             android:id="@+id/orderSummaryLabel"
-            style="@style/HistoryEventLabel"
-            android:text="@string/history_event_payment_sent_order"
+            style="@style/TransactionLabel"
+            android:text="@string/transaction_order"
             app:layout_constraintBottom_toTopOf="@+id/orderSummaryView"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent"
@@ -103,7 +103,7 @@
 
         <TextView
             android:id="@+id/orderSummaryView"
-            style="@style/HistoryEventContent"
+            style="@style/TransactionContent"
             app:layout_constraintBottom_toTopOf="@+id/orderIdView"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent"
@@ -112,8 +112,8 @@
 
         <TextView
             android:id="@+id/orderIdView"
-            style="@style/HistoryEventLabel"
-            android:text="@string/history_event_payment_sent_order_id"
+            style="@style/TransactionLabel"
+            android:text="@string/transaction_order_id"
             app:layout_constraintBottom_toBottomOf="parent"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent"
diff --git a/wallet/src/main/res/layout/fragment_event_withdraw.xml 
b/wallet/src/main/res/layout/fragment_event_withdraw.xml
index 9c5d818..5d30fcf 100644
--- a/wallet/src/main/res/layout/fragment_event_withdraw.xml
+++ b/wallet/src/main/res/layout/fragment_event_withdraw.xml
@@ -20,7 +20,7 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:fillViewport="true"
-    tools:context=".history.HistoryEventFragment">
+    tools:context=".transactions.TransactionDetailFragment">
 
     <androidx.constraintlayout.widget.ConstraintLayout
         android:layout_width="match_parent"
@@ -28,7 +28,7 @@
 
         <TextView
             android:id="@+id/timeView"
-            style="@style/HistoryEventLabel.Time"
+            style="@style/TransactionLabel.Time"
             app:layout_constraintBottom_toTopOf="@+id/effectiveAmountLabel"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent"
@@ -38,7 +38,7 @@
 
         <TextView
             android:id="@+id/effectiveAmountLabel"
-            style="@style/HistoryEventLabel"
+            style="@style/TransactionLabel"
             app:layout_constraintBottom_toTopOf="@+id/effectiveAmountView"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent"
@@ -64,7 +64,7 @@
 
         <TextView
             android:id="@+id/chosenAmountLabel"
-            style="@style/HistoryEventLabel"
+            style="@style/TransactionLabel"
             app:layout_constraintBottom_toTopOf="@+id/chosenAmountView"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent"
@@ -89,7 +89,7 @@
 
         <TextView
             android:id="@+id/feeLabel"
-            style="@style/HistoryEventLabel"
+            style="@style/TransactionLabel"
             android:text="@string/withdraw_fees"
             app:layout_constraintBottom_toTopOf="@+id/feeView"
             app:layout_constraintEnd_toEndOf="parent"
@@ -115,7 +115,7 @@
 
         <TextView
             android:id="@+id/exchangeLabel"
-            style="@style/HistoryEventLabel"
+            style="@style/TransactionLabel"
             android:text="@string/withdraw_exchange"
             app:layout_constraintBottom_toTopOf="@+id/exchangeView"
             app:layout_constraintEnd_toEndOf="parent"
diff --git a/cashier/src/main/res/layout/activity_main.xml 
b/wallet/src/main/res/layout/fragment_main.xml
similarity index 50%
copy from cashier/src/main/res/layout/activity_main.xml
copy to wallet/src/main/res/layout/fragment_main.xml
index a56b647..57fe73e 100644
--- a/cashier/src/main/res/layout/activity_main.xml
+++ b/wallet/src/main/res/layout/fragment_main.xml
@@ -13,38 +13,44 @@
   ~ 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.coordinatorlayout.widget.CoordinatorLayout 
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"
-    tools:context=".MainActivity">
+    android:layout_height="match_parent">
 
-    <com.google.android.material.appbar.AppBarLayout
+    <androidx.recyclerview.widget.RecyclerView
+        android:id="@+id/mainList"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:theme="@style/AppTheme.AppBarOverlay">
-
-        <com.google.android.material.appbar.MaterialToolbar
-            android:id="@+id/toolbar"
-            style="@style/AppTheme.Toolbar"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content" />
-
-    </com.google.android.material.appbar.AppBarLayout>
+        android:layout_height="match_parent"
+        android:visibility="gone"
+        tools:listitem="@layout/list_item_balance"
+        tools:visibility="visible" />
 
-    <androidx.fragment.app.FragmentContainerView
-        android:id="@+id/nav_host_fragment"
-        android:name="androidx.navigation.fragment.NavHostFragment"
+    <TextView
+        android:id="@+id/mainEmptyState"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        app:defaultNavHost="true"
-        app:layout_behavior="@string/appbar_scrolling_view_behavior"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintLeft_toLeftOf="parent"
-        app:layout_constraintRight_toRightOf="parent"
-        app:layout_constraintTop_toTopOf="parent"
-        app:navGraph="@navigation/nav_graph" />
+        android:autoLink="web"
+        android:gravity="center"
+        android:padding="16dp"
+        android:text="@string/balances_empty_state"
+        android:textSize="18sp"
+        android:visibility="gone"
+        tools:visibility="visible" />
+
+    <com.google.android.material.floatingactionbutton.FloatingActionButton
+        android:id="@+id/mainFab"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="bottom|end"
+        android:layout_marginEnd="16dp"
+        android:layout_marginBottom="16dp"
+        android:contentDescription="@string/button_scan_qr_code"
+        android:src="@drawable/ic_scan_qr"
+        app:backgroundTint="@color/colorPrimary"
+        
app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior"
+        app:layout_dodgeInsetEdges="bottom"
+        app:tint="?attr/colorOnPrimary" />
 
 </androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/wallet/src/main/res/layout/fragment_pending_operations.xml 
b/wallet/src/main/res/layout/fragment_pending_operations.xml
index 775c89f..5030234 100644
--- a/wallet/src/main/res/layout/fragment_pending_operations.xml
+++ b/wallet/src/main/res/layout/fragment_pending_operations.xml
@@ -29,6 +29,6 @@
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent"
-        tools:listitem="@layout/pending_row" />
+        tools:listitem="@layout/list_item_pending_operation" />
 
 </androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/wallet/src/main/res/layout/fragment_settings.xml 
b/wallet/src/main/res/layout/fragment_settings.xml
deleted file mode 100644
index fdd0120..0000000
--- a/wallet/src/main/res/layout/fragment_settings.xml
+++ /dev/null
@@ -1,104 +0,0 @@
-<?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/>
-  -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android";
-    xmlns:tools="http://schemas.android.com/tools";
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:layout_margin="10dp"
-    android:orientation="vertical"
-    tools:context=".Settings">
-
-
-    <TextView
-        android:id="@+id/editText2"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:ems="10"
-        android:text="@string/settings_version"
-        android:textSize="18sp" />
-
-
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="horizontal">
-
-        <TextView
-            android:id="@+id/textView5"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
-            android:text="@string/app_name" />
-
-        <TextView
-            android:id="@+id/textView4"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
-            tools:text="0.6.0pre8" />
-
-    </LinearLayout>
-
-    <Space
-        android:layout_width="0dp"
-        android:layout_height="15dp" />
-
-    <TextView
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:ems="10"
-        android:text="@string/settings_backups"
-        android:textSize="18sp"
-        android:visibility="gone" />
-
-    <Button
-        android:id="@+id/button_backup_export"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:text="@string/settings_export_to_file"
-        android:visibility="gone" />
-
-    <Button
-        android:id="@+id/button_backup_import"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:text="@string/settings_import_from_file"
-        android:visibility="gone" />
-
-
-    <TextView
-        android:id="@+id/devSettingsTitle"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:ems="10"
-        android:text="@string/settings_developer"
-        android:textSize="18sp" />
-
-    <!--
-    <Button
-            android:text="Withdraw TESTKUDOS"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:id="@+id/button_withdraw_testkudos"/>-->
-
-    <Button
-        android:id="@+id/button_reset_wallet_dangerously"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:text="@string/settings_reset" />
-
-</LinearLayout>
diff --git a/wallet/src/main/res/layout/fragment_show_balance.xml 
b/wallet/src/main/res/layout/fragment_show_balance.xml
deleted file mode 100644
index 82b5106..0000000
--- a/wallet/src/main/res/layout/fragment_show_balance.xml
+++ /dev/null
@@ -1,91 +0,0 @@
-<?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.constraintlayout.widget.ConstraintLayout 
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.recyclerview.widget.RecyclerView
-        android:id="@+id/balancesList"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:visibility="gone"
-        app:layout_constraintBottom_toTopOf="@+id/scanButton"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toTopOf="parent"
-        app:layout_constraintVertical_bias="0.0"
-        app:layout_constraintVertical_chainStyle="packed"
-        tools:layout_height="200dp"
-        tools:listitem="@layout/list_item_balance"
-        tools:visibility="visible" />
-
-    <TextView
-        android:id="@+id/balancesEmptyState"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:autoLink="web"
-        android:gravity="center"
-        android:padding="16dp"
-        android:text="@string/balances_empty_state"
-        android:textSize="18sp"
-        android:visibility="gone"
-        app:layout_constraintBottom_toTopOf="@+id/scanButton"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toTopOf="parent"
-        tools:visibility="gone" />
-
-    <androidx.constraintlayout.widget.Barrier
-        android:id="@+id/barrier"
-        android:layout_width="0dp"
-        android:layout_height="0dp"
-        app:barrierAllowsGoneWidgets="false"
-        app:barrierDirection="bottom"
-        app:constraint_referenced_ids="balancesList, balancesEmptyState" />
-
-    <Button
-        android:id="@+id/scanButton"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_margin="16dp"
-        android:drawableLeft="@drawable/ic_scan_qr"
-        android:padding="16dp"
-        android:text="@string/button_scan_qr_code"
-        app:layout_constraintBottom_toTopOf="@+id/testWithdrawButton"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@+id/barrier"
-        app:layout_constraintVertical_chainStyle="packed"
-        tools:ignore="RtlHardcoded" />
-
-    <Button
-        android:id="@+id/testWithdrawButton"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="16dp"
-        android:layout_marginTop="16dp"
-        android:layout_marginEnd="16dp"
-        android:padding="16dp"
-        android:text="@string/withdraw_button_testkudos"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@+id/scanButton"
-        tools:visibility="visible" />
-
-</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/wallet/src/main/res/layout/fragment_show_history.xml 
b/wallet/src/main/res/layout/fragment_transactions.xml
similarity index 90%
rename from wallet/src/main/res/layout/fragment_show_history.xml
rename to wallet/src/main/res/layout/fragment_transactions.xml
index 97194d8..a2aebcd 100644
--- a/wallet/src/main/res/layout/fragment_show_history.xml
+++ b/wallet/src/main/res/layout/fragment_transactions.xml
@@ -20,22 +20,22 @@
     android:layout_height="match_parent">
 
     <androidx.recyclerview.widget.RecyclerView
-        android:id="@+id/historyList"
+        android:id="@+id/list"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:scrollbars="vertical" />
 
     <TextView
-        android:id="@+id/historyEmptyState"
+        android:id="@+id/emptyState"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center"
-        android:text="@string/history_empty"
+        android:text="@string/transactions_empty"
         android:visibility="invisible"
         tools:visibility="visible" />
 
     <ProgressBar
-        android:id="@+id/historyProgressBar"
+        android:id="@+id/progressBar"
         style="?android:progressBarStyleLarge"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
diff --git a/wallet/src/main/res/layout/history_payment.xml 
b/wallet/src/main/res/layout/history_payment.xml
deleted file mode 100644
index 33cb676..0000000
--- a/wallet/src/main/res/layout/history_payment.xml
+++ /dev/null
@@ -1,87 +0,0 @@
-<?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.constraintlayout.widget.ConstraintLayout 
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="wrap_content"
-    android:background="?attr/selectableItemBackground"
-    android:paddingStart="16dp"
-    android:paddingTop="8dp"
-    android:paddingEnd="16dp"
-    android:paddingBottom="8dp">
-
-    <ImageView
-        android:id="@+id/icon"
-        android:layout_width="32dp"
-        android:layout_height="32dp"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toTopOf="parent"
-        app:tint="?android:colorControlNormal"
-        tools:ignore="ContentDescription"
-        tools:src="@drawable/ic_cash_usd_outline" />
-
-    <TextView
-        android:id="@+id/title"
-        style="@style/HistoryTitle"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="16dp"
-        android:layout_marginEnd="8dp"
-        app:layout_constraintEnd_toStartOf="@+id/amountPaidWithFees"
-        app:layout_constraintStart_toEndOf="@+id/icon"
-        app:layout_constraintTop_toTopOf="parent"
-        tools:text="@string/history_event_payment_sent" />
-
-    <TextView
-        android:id="@+id/summary"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="16dp"
-        android:layout_marginTop="8dp"
-        app:layout_constrainedWidth="true"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toStartOf="@+id/time"
-        app:layout_constraintHorizontal_bias="0.0"
-        app:layout_constraintStart_toEndOf="@+id/icon"
-        app:layout_constraintTop_toBottomOf="@+id/title"
-        app:layout_constraintVertical_bias="0.0"
-        tools:text="Lots of books with very long titles" />
-
-    <TextView
-        android:id="@+id/amountPaidWithFees"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:textColor="@color/red"
-        android:textSize="16sp"
-        app:layout_constraintBottom_toTopOf="@+id/time"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintTop_toTopOf="parent"
-        app:layout_constraintVertical_bias="0.0"
-        tools:text="0.2 TESTKUDOS" />
-
-    <TextView
-        android:id="@+id/time"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:textSize="14sp"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"
-        tools:text="23 min ago" />
-
-</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/wallet/src/main/res/layout/history_receive.xml 
b/wallet/src/main/res/layout/history_receive.xml
deleted file mode 100644
index 5f386a2..0000000
--- a/wallet/src/main/res/layout/history_receive.xml
+++ /dev/null
@@ -1,92 +0,0 @@
-<?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.constraintlayout.widget.ConstraintLayout 
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="wrap_content"
-    android:background="?attr/selectableItemBackground"
-    android:paddingStart="16dp"
-    android:paddingTop="8dp"
-    android:paddingEnd="16dp"
-    android:paddingBottom="8dp">
-
-    <ImageView
-        android:id="@+id/icon"
-        android:layout_width="32dp"
-        android:layout_height="32dp"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toTopOf="parent"
-        app:srcCompat="@drawable/history_withdrawn"
-        app:tint="?android:colorControlNormal"
-        tools:ignore="ContentDescription" />
-
-    <TextView
-        android:id="@+id/title"
-        style="@style/HistoryTitle"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="16dp"
-        android:layout_marginEnd="8dp"
-        android:text="@string/history_event_withdrawn"
-        app:layout_constraintEnd_toStartOf="@+id/amountWithdrawn"
-        app:layout_constraintStart_toEndOf="@+id/icon"
-        app:layout_constraintTop_toTopOf="parent" />
-
-    <TextView
-        android:id="@+id/summary"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="16dp"
-        android:layout_marginTop="8dp"
-        android:layout_marginEnd="8dp"
-        android:layout_marginBottom="8dp"
-        app:layout_constrainedWidth="true"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toStartOf="@+id/time"
-        app:layout_constraintHorizontal_bias="0.5"
-        app:layout_constraintStart_toEndOf="@+id/icon"
-        app:layout_constraintTop_toBottomOf="@+id/title"
-        app:layout_constraintVertical_bias="0.0"
-        tools:text="exchange.taler.quite-long-domain-name.org" />
-
-    <TextView
-        android:id="@+id/amountWithdrawn"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:textColor="@color/green"
-        android:textSize="16sp"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintTop_toTopOf="parent"
-        tools:text="10 TESTKUDOS" />
-
-    <TextView
-        android:id="@+id/time"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="8dp"
-        android:layout_marginBottom="8dp"
-        android:textSize="14sp"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toEndOf="@+id/summary"
-        app:layout_constraintTop_toBottomOf="@+id/amountWithdrawn"
-        app:layout_constraintVertical_bias="1.0"
-        tools:text="23 min. ago" />
-
-</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/wallet/src/main/res/layout/pending_row.xml 
b/wallet/src/main/res/layout/list_item_pending_operation.xml
similarity index 100%
rename from wallet/src/main/res/layout/pending_row.xml
rename to wallet/src/main/res/layout/list_item_pending_operation.xml
diff --git a/wallet/src/main/res/layout/history_row.xml 
b/wallet/src/main/res/layout/list_item_transaction.xml
similarity index 75%
rename from wallet/src/main/res/layout/history_row.xml
rename to wallet/src/main/res/layout/list_item_transaction.xml
index 5eac44b..a3ac980 100644
--- a/wallet/src/main/res/layout/history_row.xml
+++ b/wallet/src/main/res/layout/list_item_transaction.xml
@@ -32,45 +32,43 @@
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent"
-        app:srcCompat="@drawable/ic_account_balance"
         app:tint="?android:colorControlNormal"
-        tools:ignore="ContentDescription" />
+        tools:ignore="ContentDescription"
+        tools:src="@drawable/ic_cash_usd_outline" />
 
     <TextView
         android:id="@+id/title"
-        style="@style/HistoryTitle"
+        style="@style/TransactionTitle"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
         android:layout_marginStart="16dp"
-        app:layout_constraintEnd_toEndOf="parent"
+        android:layout_marginEnd="8dp"
+        app:layout_constraintEnd_toStartOf="@+id/amount"
         app:layout_constraintStart_toEndOf="@+id/icon"
         app:layout_constraintTop_toTopOf="parent"
-        app:layout_constraintVertical_chainStyle="packed"
-        tools:text="My History Event" />
+        tools:text="@string/transaction_payment" />
 
     <TextView
-        android:id="@+id/info"
-        android:layout_width="0dp"
+        android:id="@+id/amount"
+        android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginStart="16dp"
-        android:layout_marginTop="8dp"
-        android:layout_marginEnd="8dp"
+        android:textSize="24sp"
         app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toStartOf="@+id/time"
-        app:layout_constraintStart_toEndOf="@+id/icon"
-        app:layout_constraintTop_toBottomOf="@+id/title"
-        tools:text="TextView" />
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        tools:text="- 1337.23" />
 
     <TextView
         android:id="@+id/time"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
         android:layout_marginTop="8dp"
-        android:gravity="end"
+        android:layout_marginEnd="8dp"
         android:textSize="14sp"
         app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintEnd_toStartOf="@+id/amount"
+        app:layout_constraintStart_toStartOf="@+id/title"
         app:layout_constraintTop_toBottomOf="@+id/title"
-        tools:text="3 days ago" />
+        tools:text="23 min ago" />
 
-</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/wallet/src/main/res/menu/activity_main_drawer.xml 
b/wallet/src/main/res/menu/activity_main_drawer.xml
index 49119f8..896ff69 100644
--- a/wallet/src/main/res/menu/activity_main_drawer.xml
+++ b/wallet/src/main/res/menu/activity_main_drawer.xml
@@ -24,10 +24,6 @@
             android:icon="@drawable/ic_account_balance_wallet"
             android:title="@string/balances_title"
             tools:checked="true" />
-        <item
-            android:id="@+id/nav_history"
-            android:icon="@drawable/ic_history_black_24dp"
-            android:title="@string/menu_history" />
         <item
             android:id="@+id/nav_settings"
             android:icon="@drawable/ic_settings"
diff --git a/wallet/src/main/res/menu/balance.xml 
b/wallet/src/main/res/menu/balance.xml
deleted file mode 100644
index 1685526..0000000
--- a/wallet/src/main/res/menu/balance.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?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/>
-  -->
-
-<menu xmlns:android="http://schemas.android.com/apk/res/android";
-    xmlns:app="http://schemas.android.com/apk/res-auto";>
-    <item
-        android:id="@+id/reload_balance"
-        android:title="@string/menu_balance_reload"
-        app:showAsAction="never" />
-    <item
-        android:id="@+id/developer_mode"
-        android:checkable="true"
-        android:title="@string/menu_developer_mode"
-        app:showAsAction="never" />
-</menu>
diff --git a/wallet/src/main/res/menu/history_event.xml 
b/wallet/src/main/res/menu/fragment_main.xml
similarity index 87%
copy from wallet/src/main/res/menu/history_event.xml
copy to wallet/src/main/res/menu/fragment_main.xml
index 45a1e0e..d4568d4 100644
--- a/wallet/src/main/res/menu/history_event.xml
+++ b/wallet/src/main/res/menu/fragment_main.xml
@@ -16,8 +16,4 @@
 
 <menu xmlns:android="http://schemas.android.com/apk/res/android";
     xmlns:app="http://schemas.android.com/apk/res-auto";>
-    <item
-        android:id="@+id/show_json"
-        android:title="@string/history_detail_json"
-        app:showAsAction="never" />
 </menu>
diff --git a/wallet/src/main/res/menu/history.xml 
b/wallet/src/main/res/menu/history.xml
deleted file mode 100644
index bd50f5d..0000000
--- a/wallet/src/main/res/menu/history.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?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/>
-  -->
-
-<menu xmlns:android="http://schemas.android.com/apk/res/android";
-    xmlns:app="http://schemas.android.com/apk/res-auto";>
-    <item
-        android:id="@+id/show_all_history"
-        android:checkable="true"
-        android:checked="false"
-        android:title="@string/history_show_all"
-        app:showAsAction="never" />
-    <item
-        android:id="@+id/reload_history"
-        android:orderInCategory="100"
-        android:title="@string/history_reload"
-        app:showAsAction="never" />
-</menu>
diff --git a/wallet/src/main/res/menu/history_event.xml 
b/wallet/src/main/res/menu/transactions.xml
similarity index 87%
copy from wallet/src/main/res/menu/history_event.xml
copy to wallet/src/main/res/menu/transactions.xml
index 45a1e0e..d4568d4 100644
--- a/wallet/src/main/res/menu/history_event.xml
+++ b/wallet/src/main/res/menu/transactions.xml
@@ -16,8 +16,4 @@
 
 <menu xmlns:android="http://schemas.android.com/apk/res/android";
     xmlns:app="http://schemas.android.com/apk/res-auto";>
-    <item
-        android:id="@+id/show_json"
-        android:title="@string/history_detail_json"
-        app:showAsAction="never" />
 </menu>
diff --git a/wallet/src/main/res/menu/history_event.xml 
b/wallet/src/main/res/menu/transactions_detail.xml
similarity index 94%
rename from wallet/src/main/res/menu/history_event.xml
rename to wallet/src/main/res/menu/transactions_detail.xml
index 45a1e0e..388e3c4 100644
--- a/wallet/src/main/res/menu/history_event.xml
+++ b/wallet/src/main/res/menu/transactions_detail.xml
@@ -18,6 +18,6 @@
     xmlns:app="http://schemas.android.com/apk/res-auto";>
     <item
         android:id="@+id/show_json"
-        android:title="@string/history_detail_json"
+        android:title="@string/transactions_detail_json"
         app:showAsAction="never" />
 </menu>
diff --git a/wallet/src/main/res/navigation/nav_graph.xml 
b/wallet/src/main/res/navigation/nav_graph.xml
index f6d8598..ef0f48b 100644
--- a/wallet/src/main/res/navigation/nav_graph.xml
+++ b/wallet/src/main/res/navigation/nav_graph.xml
@@ -23,9 +23,9 @@
 
     <fragment
         android:id="@+id/showBalance"
-        android:name="net.taler.wallet.BalanceFragment"
+        android:name="net.taler.wallet.MainFragment"
         android:label="@string/balances_title"
-        tools:layout="@layout/fragment_show_balance">
+        tools:layout="@layout/fragment_main">
         <action
             android:id="@+id/action_showBalance_to_promptPayment"
             app:destination="@id/promptPayment" />
@@ -54,24 +54,23 @@
         tools:layout="@layout/fragment_payment_successful" />
     <fragment
         android:id="@+id/settings"
-        android:name="net.taler.wallet.Settings"
-        android:label="Settings"
-        tools:layout="@layout/fragment_settings" />
+        android:name="net.taler.wallet.SettingsFragment"
+        android:label="Settings" />
 
     <fragment
-        android:id="@+id/walletHistory"
-        android:name="net.taler.wallet.history.HistoryFragment"
-        android:label="@string/history_title"
-        tools:layout="@layout/fragment_show_history">
+        android:id="@+id/nav_transactions"
+        android:name="net.taler.wallet.transactions.TransactionsFragment"
+        android:label="@string/transactions_title"
+        tools:layout="@layout/fragment_transactions">
         <action
-            android:id="@+id/action_walletHistory_to_historyEventFragment"
-            app:destination="@id/historyEventFragment" />
+            android:id="@+id/action_nav_transactions_to_nav_transaction_detail"
+            app:destination="@id/nav_transactions_detail" />
     </fragment>
 
     <fragment
-        android:id="@+id/historyEventFragment"
-        android:name="net.taler.wallet.history.HistoryEventFragment"
-        android:label="@string/history_detail_title"
+        android:id="@+id/nav_transactions_detail"
+        android:name="net.taler.wallet.transactions.TransactionDetailFragment"
+        android:label="@string/transactions_detail_title"
         tools:layout="@layout/fragment_event_withdraw" />
 
     <fragment
diff --git a/wallet/src/main/res/values/strings.xml 
b/wallet/src/main/res/values/strings.xml
index 357aedc..e0b3183 100644
--- a/wallet/src/main/res/values/strings.xml
+++ b/wallet/src/main/res/values/strings.xml
@@ -30,55 +30,45 @@
     <string name="button_continue">Continue</string>
     <string name="button_scan_qr_code">Scan Taler QR Code</string>
 
-    <string name="menu_history">History</string>
     <string name="menu_settings">Settings</string>
-    <string name="menu_balance_reload">Reload balances</string>
-    <string name="menu_developer_mode">Developer Mode</string>
     <string name="menu_retry_pending_operations">Retry Pending 
Operations</string>
 
     <string name="servicedesc">my service</string>
     <string name="aiddescription">my aid</string>
 
     <string name="balances_title">Balances</string>
-    <string name="amount_positive">+%s</string>
-    <string name="amount_negative">-%s</string>
+    <string name="amount_positive">+ %s</string>
+    <string name="amount_negative">- %s</string>
     <string name="amount_chosen">Chosen Amount</string>
     <string name="balances_inbound_label">inbound</string>
     <string name="balances_empty_state">There is no digital cash in your 
wallet.\n\nYou can get test money from the demo 
bank:\n\nhttps://bank.demo.taler.net</string>
 
-    <string name="history_title">History</string>
-    <string name="history_show_all">Show All</string>
-    <string name="history_reload">Reload History</string>
-    <string name="history_empty">The wallet history is empty</string>
-    <string name="history_error">Could not load history</string>
-    <string name="history_detail_title">Transaction</string>
-    <string name="history_detail_json">Show JSON</string>
-
-    <!-- HistoryEvents -->
-    <string name="history_event_exchange_added">Exchange Added</string>
-    <string name="history_event_exchange_updated">Exchange Updated</string>
-    <string name="history_event_reserve_balance_updated">Reserve Balance 
Updated</string>
-    <string name="history_event_payment_sent">Payment</string>
-    <string name="history_event_payment_sent_paid">Paid</string>
-    <string name="history_event_payment_sent_amount">Order Total</string>
-    <string name="history_event_payment_sent_order">Order</string>
-    <string name="history_event_payment_sent_order_id">Order Reference: 
%1$s</string>
-    <string name="history_event_payment_aborted">Payment Aborted</string>
-    <string name="history_event_withdrawn">Withdraw</string>
-    <string name="history_event_order_accepted">Purchase Confirmed</string>
-    <string name="history_event_order_refused">Purchase Cancelled</string>
-    <string name="history_event_tip_accepted">Tip Accepted</string>
-    <string name="history_event_tip_declined">Tip Declined</string>
-    <string name="history_event_order_redirected">Purchase Redirected</string>
-    <string name="history_event_refund">Refund</string>
-    <string name="history_event_refreshed">Obtained change</string>
-    <string name="history_event_refresh_reason_manual">because of manual 
request</string>
-    <string name="history_event_refresh_reason_pay">for payment</string>
-    <string name="history_event_refresh_reason_refund">for refund</string>
-    <string name="history_event_refresh_reason_abort_pay">to abort 
payment</string>
-    <string name="history_event_refresh_reason_recoup">to recoup funds</string>
-    <string name="history_event_refresh_reason_backup_restored">because of 
restoring from backup</string>
-    <string name="history_event_unknown">Unknown Event</string>
+    <string name="transactions_title">Transactions</string>
+    <string name="transactions_empty">You don\'t have any transactions</string>
+    <string name="transactions_error">Could not load transactions</string>
+    <string name="transactions_detail_title">Transaction</string>
+    <string name="transactions_detail_title_balance">Balance: %s</string>
+    <string name="transactions_detail_json">Show JSON</string>
+
+    <!-- Transactions -->
+    <string name="transaction_reserve_balance_updated">Reserve Balance 
Updated</string>
+    <string name="transaction_payment">Payment</string>
+    <string name="transaction_paid">Paid</string>
+    <string name="transaction_order_total">Order Total</string>
+    <string name="transaction_order">Order</string>
+    <string name="transaction_order_id">Order Reference: %1$s</string>
+    <string name="transaction_order_accepted">Purchase Confirmed</string>
+    <string name="transaction_order_refused">Purchase Cancelled</string>
+    <string name="transaction_tip_accepted">Tip Accepted</string>
+    <string name="transaction_tip_declined">Tip Declined</string>
+    <string name="transaction_refund">Refund</string>
+    <string name="transaction_refresh">Obtained change</string>
+    <string name="transaction_refresh_reason_manual">because of manual 
request</string>
+    <string name="transaction_refresh_reason_pay">for payment</string>
+    <string name="transaction_refresh_reason_refund">for refund</string>
+    <string name="transaction_refresh_reason_abort_pay">to abort 
payment</string>
+    <string name="transaction_refresh_reason_recoup">to recoup funds</string>
+    <string name="transaction_refresh_reason_backup_restored">because of 
restoring from backup</string>
 
     <string name="payment_fee">+%s payment fee</string>
     <string name="payment_button_confirm">Confirm Payment</string>
@@ -97,7 +87,6 @@
     <string name="withdraw_total">Withdraw</string>
     <string name="withdraw_fees">Fee</string>
     <string name="withdraw_exchange">Exchange</string>
-    <string name="withdraw_button_testkudos">Withdraw TESTKUDOS</string>
     <string name="withdraw_button_confirm">Confirm Withdraw</string>
     <string name="withdraw_button_tos">Review Terms</string>
     <string name="withdraw_error_title">Withdrawal Error</string>
@@ -119,18 +108,18 @@
     <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="exchange_tos_accept">Accept Terms of Service</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>
 
-    <string name="settings_version">Version Information</string>
-    <string name="exchange_tos_accept">Accept Terms of Service</string>
-    <string name="settings_backups">Backups</string>
-    <string name="settings_export_to_file">Export wallet to file</string>
-    <string name="settings_import_from_file">Import from file</string>
-    <string name="settings_developer">Developer Settings (use with 
caution!)</string>
+    <string name="settings_dev_mode">Developer Mode</string>
+    <string name="settings_dev_mode_summary">Shows more information intended 
for debugging</string>
+    <string name="settings_withdraw_testkudos">Withdraw TESTKUDOS</string>
+    <string name="settings_withdraw_testkudos_summary">Get money for 
testing</string>
     <string name="settings_reset">Reset Wallet (dangerous!)</string>
+    <string name="settings_reset_summary">Throws away your money</string>
 
     <string name="refund_error">Error processing refund</string>
     <string name="refund_success">Refund received</string>
diff --git a/wallet/src/main/res/values/styles.xml 
b/wallet/src/main/res/values/styles.xml
index 9ebcae5..c8a2c3b 100644
--- a/wallet/src/main/res/values/styles.xml
+++ b/wallet/src/main/res/values/styles.xml
@@ -33,12 +33,12 @@
 
     <style name="AppTheme.Toolbar" 
parent="Widget.MaterialComponents.Toolbar.Primary" />
 
-    <style name="HistoryTitle">
+    <style name="TransactionTitle">
         <item name="android:textSize">16sp</item>
         <item name="android:textColor">?android:textColorPrimary</item>
     </style>
 
-    <style name="HistoryEventLabel">
+    <style name="TransactionLabel">
         <item name="android:layout_width">0dp</item>
         <item name="android:layout_height">wrap_content</item>
         <item name="android:layout_marginStart">16dp</item>
@@ -47,12 +47,12 @@
         <item name="android:gravity">center</item>
     </style>
 
-    <style name="HistoryEventLabel.Time">
+    <style name="TransactionLabel.Time">
         <item name="android:layout_marginBottom">16dp</item>
         <item 
name="android:textAppearance">@style/TextAppearance.AppCompat.Medium</item>
     </style>
 
-    <style name="HistoryEventContent">
+    <style name="TransactionContent">
         <item name="android:layout_width">0dp</item>
         <item name="android:layout_height">wrap_content</item>
         <item name="android:layout_marginStart">16dp</item>
diff --git a/wallet/src/main/res/xml/settings_main.xml 
b/wallet/src/main/res/xml/settings_main.xml
new file mode 100644
index 0000000..d200bb5
--- /dev/null
+++ b/wallet/src/main/res/xml/settings_main.xml
@@ -0,0 +1,41 @@
+<?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/>
+  -->
+
+<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto";
+    xmlns:tools="http://schemas.android.com/tools";>
+
+    <SwitchPreferenceCompat
+        app:icon="@drawable/ic_developer_mode"
+        app:key="pref_dev_mode"
+        app:summary="@string/settings_dev_mode_summary"
+        app:title="@string/settings_dev_mode" />
+
+    <Preference
+        app:icon="@drawable/ic_cash_usd_outline"
+        app:isPreferenceVisible="false"
+        app:key="pref_testkudos"
+        app:summary="@string/settings_withdraw_testkudos_summary"
+        app:title="@string/settings_withdraw_testkudos"
+        tools:isPreferenceVisible="true" />
+
+    <Preference
+        app:isPreferenceVisible="false"
+        app:key="pref_reset"
+        app:summary="@string/settings_reset_summary"
+        app:title="@string/settings_reset"
+        tools:isPreferenceVisible="true" />
+
+</PreferenceScreen>
diff --git 
a/wallet/src/test/java/net/taler/wallet/history/ReserveTransactionTest.kt 
b/wallet/src/test/java/net/taler/wallet/transactions/ReserveTransactionTest.kt
similarity index 98%
rename from 
wallet/src/test/java/net/taler/wallet/history/ReserveTransactionTest.kt
rename to 
wallet/src/test/java/net/taler/wallet/transactions/ReserveTransactionTest.kt
index d3d66f5..4a3c75b 100644
--- a/wallet/src/test/java/net/taler/wallet/history/ReserveTransactionTest.kt
+++ 
b/wallet/src/test/java/net/taler/wallet/transactions/ReserveTransactionTest.kt
@@ -14,7 +14,7 @@
  * GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-package net.taler.wallet.history
+package net.taler.wallet.transactions
 
 import com.fasterxml.jackson.databind.ObjectMapper
 import com.fasterxml.jackson.module.kotlin.KotlinModule
diff --git a/wallet/src/test/java/net/taler/wallet/history/HistoryEventTest.kt 
b/wallet/src/test/java/net/taler/wallet/transactions/TransactionTest.kt
similarity index 80%
rename from wallet/src/test/java/net/taler/wallet/history/HistoryEventTest.kt
rename to wallet/src/test/java/net/taler/wallet/transactions/TransactionTest.kt
index 6b8c41a..6549434 100644
--- a/wallet/src/test/java/net/taler/wallet/history/HistoryEventTest.kt
+++ b/wallet/src/test/java/net/taler/wallet/transactions/TransactionTest.kt
@@ -14,20 +14,20 @@
  * GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-package net.taler.wallet.history
+package net.taler.wallet.transactions
 
 import com.fasterxml.jackson.databind.ObjectMapper
 import com.fasterxml.jackson.module.kotlin.KotlinModule
 import com.fasterxml.jackson.module.kotlin.readValue
 import net.taler.common.Amount
-import net.taler.wallet.history.RefreshReason.PAY
-import net.taler.wallet.history.ReserveType.MANUAL
+import net.taler.wallet.transactions.RefreshReason.PAY
+import net.taler.wallet.transactions.ReserveType.MANUAL
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertTrue
 import org.junit.Test
 import kotlin.random.Random
 
-class HistoryEventTest {
+class TransactionTest {
 
     private val mapper = ObjectMapper().registerModule(KotlinModule())
 
@@ -93,7 +93,7 @@ class HistoryEventTest {
     }
 
     @Test
-    fun `test ReserveBalanceUpdatedEvent`() {
+    fun `test ReserveBalanceUpdatedTransaction`() {
         val json = """{
             "type": "reserve-balance-updated",
             "eventId": 
"reserve-balance-updated;K0H10Q6HB9WH0CKHQQMNH5C6GA7A9AR1E2XSS9G1KG3ZXMBVT26G",
@@ -111,17 +111,17 @@ class HistoryEventTest {
                 "reservePub": 
"BRT2P0YMQSD5F48V9XHVNH73ZTS6EZC0KCQCPGPZQWTSQB77615G"
             }
         }""".trimIndent()
-        val event: ReserveBalanceUpdatedEvent = mapper.readValue(json)
+        val transaction: ReserveBalanceUpdatedTransaction = 
mapper.readValue(json)
 
-        assertEquals(timestamp, event.timestamp.ms)
-        assertEquals("TESTKUDOS:23", event.reserveAwaitedAmount.toJSONString())
-        assertEquals("TESTKUDOS:10", event.reserveBalance.toJSONString())
-        assertEquals("TESTKUDOS:0.01", 
event.reserveUnclaimedAmount.toJSONString())
-        assertEquals(exchangeBaseUrl, event.reserveShortInfo.exchangeBaseUrl)
+        assertEquals(timestamp, transaction.timestamp.ms)
+        assertEquals("TESTKUDOS:23", 
transaction.reserveAwaitedAmount.toJSONString())
+        assertEquals("TESTKUDOS:10", transaction.reserveBalance.toJSONString())
+        assertEquals("TESTKUDOS:0.01", 
transaction.reserveUnclaimedAmount.toJSONString())
+        assertEquals(exchangeBaseUrl, 
transaction.reserveShortInfo.exchangeBaseUrl)
     }
 
     @Test
-    fun `test HistoryWithdrawnEvent`() {
+    fun `test WithdrawTransaction`() {
         val json = """{
             "type": "withdrawn",
             "withdrawalGroupId": 
"974FT7JDNR20EQKNR21G1HV9PB6T5AZHYHX9NHR51Q30ZK3T10S0",
@@ -137,7 +137,7 @@ class HistoryEventTest {
                 "reservePub": 
"BRT2P0YMQSD5F48V9XHVNH73ZTS6EZC0KCQCPGPZQWTSQB77615G"
             }
         }""".trimIndent()
-        val event: HistoryWithdrawnEvent = mapper.readValue(json)
+        val event: WithdrawTransaction = mapper.readValue(json)
 
         assertEquals(
             "974FT7JDNR20EQKNR21G1HV9PB6T5AZHYHX9NHR51Q30ZK3T10S0",
@@ -171,7 +171,7 @@ class HistoryEventTest {
     }
 
     @Test
-    fun `test HistoryOrderAcceptedEvent`() {
+    fun `test OrderAcceptedTransaction`() {
         val json = """{
             "type": "order-accepted",
             "eventId": 
"order-accepted;EP5MH4R5C9RMNA06YS1QGEJ3EY682PY8R1SGRFRP74EV735N3ATG",
@@ -186,14 +186,14 @@ class HistoryEventTest {
                 "t_ms": $timestamp
             }
         }""".trimIndent()
-        val event: HistoryOrderAcceptedEvent = mapper.readValue(json)
+        val transaction: OrderAcceptedTransaction = mapper.readValue(json)
 
-        assertEquals(orderShortInfo, event.orderShortInfo)
-        assertEquals(timestamp, event.timestamp.ms)
+        assertEquals(orderShortInfo, transaction.orderShortInfo)
+        assertEquals(timestamp, transaction.timestamp.ms)
     }
 
     @Test
-    fun `test HistoryOrderRefusedEvent`() {
+    fun `test OrderRefusedTransaction`() {
         val json = """{
             "type": "order-refused",
             "eventId": 
"order-refused;9RJGAYXKWX0Y3V37H66606SXSA7V2CV255EBFS4G1JSH6W1EG7F0",
@@ -208,14 +208,14 @@ class HistoryEventTest {
                 "t_ms": $timestamp
             }
         }""".trimIndent()
-        val event: HistoryOrderRefusedEvent = mapper.readValue(json)
+        val transaction: OrderRefusedTransaction = mapper.readValue(json)
 
-        assertEquals(orderShortInfo, event.orderShortInfo)
-        assertEquals(timestamp, event.timestamp.ms)
+        assertEquals(orderShortInfo, transaction.orderShortInfo)
+        assertEquals(timestamp, transaction.timestamp.ms)
     }
 
     @Test
-    fun `test HistoryPaymentSentEvent`() {
+    fun `test PaymentTransaction`() {
         val json = """{
             "type": "payment-sent",
             "eventId": 
"payment-sent;EP5MH4R5C9RMNA06YS1QGEJ3EY682PY8R1SGRFRP74EV735N3ATG",
@@ -234,7 +234,7 @@ class HistoryEventTest {
             "numCoins": 6,
             "amountPaidWithFees": "KUDOS:0.6"
         }""".trimIndent()
-        val event: HistoryPaymentSentEvent = mapper.readValue(json)
+        val event: PaymentTransaction = mapper.readValue(json)
 
         assertEquals(orderShortInfo, event.orderShortInfo)
         assertEquals(false, event.replay)
@@ -245,7 +245,7 @@ class HistoryEventTest {
     }
 
     @Test
-    fun `test HistoryPaymentSentEvent without sessionId`() {
+    fun `test PaymentTransaction without sessionId`() {
         val json = """{
             "type": "payment-sent",
             "eventId": 
"payment-sent;EP5MH4R5C9RMNA06YS1QGEJ3EY682PY8R1SGRFRP74EV735N3ATG",
@@ -263,7 +263,7 @@ class HistoryEventTest {
             "numCoins": 6,
             "amountPaidWithFees": "KUDOS:0.6"
         }""".trimIndent()
-        val event: HistoryPaymentSentEvent = mapper.readValue(json)
+        val event: PaymentTransaction = mapper.readValue(json)
 
         assertEquals(orderShortInfo, event.orderShortInfo)
         assertEquals(true, event.replay)
@@ -274,7 +274,7 @@ class HistoryEventTest {
     }
 
     @Test
-    fun `test HistoryPaymentAbortedEvent`() {
+    fun `test PaymentAbortedTransaction`() {
         val json = """{
             "type": "payment-aborted",
             "eventId": 
"payment-sent;898724XGQ1GGMZB4WY3KND582NSP74FZ60BX0Y87FF81H0FJ8XD0",
@@ -290,15 +290,15 @@ class HistoryEventTest {
             },
             "amountLost": "KUDOS:0.1"
           }""".trimIndent()
-        val event: HistoryPaymentAbortedEvent = mapper.readValue(json)
+        val transaction: PaymentAbortedTransaction = mapper.readValue(json)
 
-        assertEquals(orderShortInfo, event.orderShortInfo)
-        assertEquals("KUDOS:0.1", event.amountLost.toJSONString())
-        assertEquals(timestamp, event.timestamp.ms)
+        assertEquals(orderShortInfo, transaction.orderShortInfo)
+        assertEquals("KUDOS:0.1", transaction.amountLost.toJSONString())
+        assertEquals(timestamp, transaction.timestamp.ms)
     }
 
     @Test
-    fun `test HistoryTipAcceptedEvent`() {
+    fun `test TipAcceptedTransaction`() {
         val json = """{
             "type": "tip-accepted",
             "timestamp": {
@@ -308,18 +308,18 @@ class HistoryEventTest {
             "tipId": 
"tip-accepted;898724XGQ1GGMZB4WY3KND582NSP74FZ60BX0Y87FF81H0FJ8XD0",
             "tipRaw": "KUDOS:4"
           }""".trimIndent()
-        val event: HistoryTipAcceptedEvent = mapper.readValue(json)
+        val transaction: TipAcceptedTransaction = mapper.readValue(json)
 
         assertEquals(
             
"tip-accepted;898724XGQ1GGMZB4WY3KND582NSP74FZ60BX0Y87FF81H0FJ8XD0",
-            event.tipId
+            transaction.tipId
         )
-        assertEquals("KUDOS:4", event.tipRaw.toJSONString())
-        assertEquals(timestamp, event.timestamp.ms)
+        assertEquals("KUDOS:4", transaction.tipRaw.toJSONString())
+        assertEquals(timestamp, transaction.timestamp.ms)
     }
 
     @Test
-    fun `test HistoryTipDeclinedEvent`() {
+    fun `test TipDeclinedTransaction`() {
         val json = """{
             "type": "tip-declined",
             "timestamp": {
@@ -329,18 +329,18 @@ class HistoryEventTest {
             "tipId": 
"tip-accepted;998724XGQ1GGMZB4WY3KND582NSP74FZ60BX0Y87FF81H0FJ8XD0",
             "tipAmount": "KUDOS:4"
           }""".trimIndent()
-        val event: HistoryTipDeclinedEvent = mapper.readValue(json)
+        val transaction: TipDeclinedTransaction = mapper.readValue(json)
 
         assertEquals(
             
"tip-accepted;998724XGQ1GGMZB4WY3KND582NSP74FZ60BX0Y87FF81H0FJ8XD0",
-            event.tipId
+            transaction.tipId
         )
-        assertEquals("KUDOS:4", event.tipAmount.toJSONString())
-        assertEquals(timestamp, event.timestamp.ms)
+        assertEquals("KUDOS:4", transaction.tipAmount.toJSONString())
+        assertEquals(timestamp, transaction.timestamp.ms)
     }
 
     @Test
-    fun `test HistoryRefundedEvent`() {
+    fun `test RefundTransaction`() {
         val json = """{
             "type": "refund",
             "eventId": 
"refund;898724XGQ1GGMZB4WY3KND582NSP74FZ60BX0Y87FF81H0FJ8XD0",
@@ -359,7 +359,7 @@ class HistoryEventTest {
             "amountRefundedInvalid": "KUDOS:0.5",
             "amountRefundedEffective": "KUDOS:0.4"
           }""".trimIndent()
-        val event: HistoryRefundedEvent = mapper.readValue(json)
+        val event: RefundTransaction = mapper.readValue(json)
 
         assertEquals("refund;998724", event.refundGroupId)
         assertEquals("KUDOS:1", event.amountRefundedRaw.toJSONString())
@@ -370,7 +370,7 @@ class HistoryEventTest {
     }
 
     @Test
-    fun `test HistoryRefreshedEvent`() {
+    fun `test RefreshTransaction`() {
         val json = """{
             "type": "refreshed",
             "refreshGroupId": 
"8AVHKJFAN4QV4C11P56NEY83AJMGFF2KF412AN3Y0QBP09RSN640",
@@ -385,7 +385,7 @@ class HistoryEventTest {
             "numOutputCoins": 0,
             "numRefreshedInputCoins": 1
         }""".trimIndent()
-        val event: HistoryRefreshedEvent = mapper.readValue(json)
+        val event: RefreshTransaction = mapper.readValue(json)
 
         assertEquals("KUDOS:0", event.amountRefreshedEffective.toJSONString())
         assertEquals("KUDOS:1", event.amountRefreshedRaw.toJSONString())
@@ -398,7 +398,7 @@ class HistoryEventTest {
     }
 
     @Test
-    fun `test HistoryOrderRedirectedEvent`() {
+    fun `test OrderRedirectedTransaction`() {
         val json = """{
             "type": "order-redirected",
             "eventId": 
"order-redirected;621J6D5SXG7M17TYA26945DYKNQZPW4600MZ1W8MADA1RRR49F8G",
@@ -420,40 +420,40 @@ class HistoryEventTest {
               "t_ms": $timestamp
             }
           }""".trimIndent()
-        val event: HistoryOrderRedirectedEvent = mapper.readValue(json)
+        val transaction: OrderRedirectedTransaction = mapper.readValue(json)
 
         assertEquals(
             "898724XGQ1GGMZB4WY3KND582NSP74FZ60BX0Y87FF81H0FJ8XD0",
-            event.alreadyPaidOrderShortInfo.proposalId
+            transaction.alreadyPaidOrderShortInfo.proposalId
         )
         assertEquals(
             "https://backend.demo.taler.net/public/instances/FSF/";,
-            event.alreadyPaidOrderShortInfo.merchantBaseUrl
+            transaction.alreadyPaidOrderShortInfo.merchantBaseUrl
         )
-        assertEquals("2019.354-01P25CD66P8NG", 
event.alreadyPaidOrderShortInfo.orderId)
-        assertEquals("KUDOS:0.5", 
event.alreadyPaidOrderShortInfo.amount.toJSONString())
+        assertEquals("2019.354-01P25CD66P8NG", 
transaction.alreadyPaidOrderShortInfo.orderId)
+        assertEquals("KUDOS:0.5", 
transaction.alreadyPaidOrderShortInfo.amount.toJSONString())
         assertEquals(
             "Essay: 1. The Free Software Definition",
-            event.alreadyPaidOrderShortInfo.summary
+            transaction.alreadyPaidOrderShortInfo.summary
         )
 
         assertEquals(
             "621J6D5SXG7M17TYA26945DYKNQZPW4600MZ1W8MADA1RRR49F8G",
-            event.newOrderShortInfo.proposalId
+            transaction.newOrderShortInfo.proposalId
         )
         assertEquals(
             "https://backend.demo.taler.net/public/instances/FSF/";,
-            event.newOrderShortInfo.merchantBaseUrl
+            transaction.newOrderShortInfo.merchantBaseUrl
         )
-        assertEquals("2019.364-01M4QH6KPMJY4", event.newOrderShortInfo.orderId)
-        assertEquals("KUDOS:0.5", 
event.newOrderShortInfo.amount.toJSONString())
-        assertEquals("Essay: 1. The Free Software Definition", 
event.newOrderShortInfo.summary)
+        assertEquals("2019.364-01M4QH6KPMJY4", 
transaction.newOrderShortInfo.orderId)
+        assertEquals("KUDOS:0.5", 
transaction.newOrderShortInfo.amount.toJSONString())
+        assertEquals("Essay: 1. The Free Software Definition", 
transaction.newOrderShortInfo.summary)
 
-        assertEquals(timestamp, event.timestamp.ms)
+        assertEquals(timestamp, transaction.timestamp.ms)
     }
 
     @Test
-    fun `test HistoryUnknownEvent`() {
+    fun `test UnknownTransaction`() {
         val json = """{
             "type": "does not exist",
             "timestamp": {
@@ -461,9 +461,9 @@ class HistoryEventTest {
             },
             "eventId": 
"does-not-exist;898724XGQ1GGMZB4WY3KND582NSP74FZ60BX0Y87FF81H0FJ8XD0"
           }""".trimIndent()
-        val event: HistoryEvent = mapper.readValue(json)
+        val event: Transaction = mapper.readValue(json)
 
-        assertEquals(HistoryUnknownEvent::class.java, event.javaClass)
+        assertEquals(UnknownTransaction::class.java, event.javaClass)
         assertEquals(timestamp, event.timestamp.ms)
     }
 

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



reply via email to

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