gnunet-svn
[Top][All Lists]
Advanced

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

[taler-taler-android] branch master updated (39b6926 -> 4af27e7)


From: gnunet
Subject: [taler-taler-android] branch master updated (39b6926 -> 4af27e7)
Date: Wed, 27 Mar 2024 18:27:03 +0100

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 39b6926  [wallet] User friendlier p2p insufficient balance error
     new 1e9ee99  [wallet] DD51: initial rendering based on currency spec
     new c86ae12  [wallet] DD51: enrich some tx amounts with 
currencySpecification
     new cc59e35  [wallet] DD51: enrich manual withdrawal amounts with 
currencySpecification
     new f495657  [wallet] Balance layout improvements
     new e305ddb  [wallet] Display transactions by scopeInfo instead of currency
     new 390b562  [wallet] Improve DD51 unit rendering and adapt tests 
accordingly
     new 4b4cf98  [wallet] Set input digits of some amount inputs
     new 8d56c1d  [wallet] Cache currencySpec in loadBalances()
     new 5b6ba02  [taler-android] Improved and refactored testToString test
     new 881eeab  [taler-android] Improve handling of currencies with no symbol
     new 18a8322  [wallet] Cache currency spec per scope info
     new 945620b  [wallet] Fix call to loadBalances() from non-UI thread
     new 0b91663  [wallet] DD51'd more views, UX improvements and some fixes
     new 3d4f7f9  [wallet] Use Backend.json instead of Json
     new 4af27e7  [wallet] Use TransactionManager.selectedScope instead of 
passing around scopeInfo

The 15 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:
 .../main/java/net/taler/cashier/SignedAmount.kt    |   8 +-
 .../src/main/java/net/taler/common/Amount.kt       |  57 +++++++-
 .../net/taler/common}/CurrencySpecification.kt     |  11 +-
 .../src/test/java/net/taler/common/AmountTest.kt   | 157 ++++++++++++++++++++-
 .../src/main/java/net/taler/wallet/MainActivity.kt |   5 +-
 .../src/main/java/net/taler/wallet/MainFragment.kt |  22 +--
 .../main/java/net/taler/wallet/MainViewModel.kt    |  13 +-
 .../java/net/taler/wallet/ReceiveFundsFragment.kt  |  15 +-
 .../java/net/taler/wallet/SendFundsFragment.kt     |  16 ++-
 .../net/taler/wallet/balances/BalanceAdapter.kt    |   9 +-
 .../net/taler/wallet/balances/BalanceManager.kt    |  61 +++++++-
 .../net/taler/wallet/balances/BalancesFragment.kt  |   6 +-
 .../net/taler/wallet/compose/AmountInputField.kt   |  11 +-
 .../net/taler/wallet/deposit/DepositFragment.kt    |   8 +-
 .../taler/wallet/deposit/MakeDepositComposable.kt  |   4 +-
 .../wallet/deposit/TransactionDepositComposable.kt |  10 +-
 .../taler/wallet/exchanges/ExchangeListFragment.kt |   2 +-
 .../java/net/taler/wallet/exchanges/Exchanges.kt   |   2 +
 .../wallet/payment/TransactionPaymentComposable.kt |  10 +-
 .../taler/wallet/peer/OutgoingPullComposable.kt    |   2 +-
 .../net/taler/wallet/peer/OutgoingPullFragment.kt  |   6 +-
 .../taler/wallet/peer/OutgoingPushComposable.kt    |   2 +-
 .../net/taler/wallet/peer/OutgoingPushFragment.kt  |   5 +-
 .../taler/wallet/peer/TransactionPeerPullCredit.kt |  11 +-
 .../taler/wallet/peer/TransactionPeerPullDebit.kt  |  13 +-
 .../taler/wallet/peer/TransactionPeerPushCredit.kt |  11 +-
 .../taler/wallet/peer/TransactionPeerPushDebit.kt  |  11 +-
 .../wallet/refund/TransactionRefundComposable.kt   |  10 +-
 .../wallet/transactions/TransactionAdapter.kt      |  10 +-
 .../transactions/TransactionDepositFragment.kt     |   1 +
 .../transactions/TransactionDetailFragment.kt      |   1 +
 .../wallet/transactions/TransactionManager.kt      |  32 +++--
 .../transactions/TransactionPaymentFragment.kt     |   1 +
 .../wallet/transactions/TransactionPeerFragment.kt |  16 ++-
 .../transactions/TransactionRefreshFragment.kt     |  10 +-
 .../transactions/TransactionRefundFragment.kt      |   4 +-
 .../transactions/TransactionWithdrawalFragment.kt  |   1 +
 .../net/taler/wallet/transactions/Transactions.kt  |   2 +-
 .../wallet/transactions/TransactionsFragment.kt    |  14 +-
 .../withdraw/TransactionWithdrawalComposable.kt    |  13 +-
 .../net/taler/wallet/withdraw/WithdrawManager.kt   |   2 +
 .../manual/ManualWithdrawSuccessFragment.kt        |   2 +
 .../taler/wallet/withdraw/manual/ScreenTransfer.kt |  12 +-
 .../wallet/withdraw/manual/TransferBitcoin.kt      |   4 +-
 .../taler/wallet/withdraw/manual/TransferIBAN.kt   |   4 +-
 wallet/src/main/res/layout/list_item_balance.xml   |  20 +--
 wallet/src/main/res/values/strings.xml             |   2 +
 47 files changed, 491 insertions(+), 158 deletions(-)
 rename {wallet/src/main/java/net/taler/wallet/balances => 
taler-kotlin-android/src/main/java/net/taler/common}/CurrencySpecification.kt 
(85%)

diff --git a/cashier/src/main/java/net/taler/cashier/SignedAmount.kt 
b/cashier/src/main/java/net/taler/cashier/SignedAmount.kt
index 4f624ae..45bc3af 100644
--- a/cashier/src/main/java/net/taler/cashier/SignedAmount.kt
+++ b/cashier/src/main/java/net/taler/cashier/SignedAmount.kt
@@ -23,8 +23,10 @@ data class SignedAmount(
     val amount: Amount
 ) {
 
-    override fun toString(): String {
-        return if (positive) "$amount" else "-$amount"
-    }
+    override fun toString() = toString(showSymbol = true)
 
+    fun toString(showSymbol: Boolean) = amount.toString(
+            showSymbol = showSymbol,
+            negative = !positive,
+    )
 }
diff --git a/taler-kotlin-android/src/main/java/net/taler/common/Amount.kt 
b/taler-kotlin-android/src/main/java/net/taler/common/Amount.kt
index 5fb36fa..3e3bd0a 100644
--- a/taler-kotlin-android/src/main/java/net/taler/common/Amount.kt
+++ b/taler-kotlin-android/src/main/java/net/taler/common/Amount.kt
@@ -16,11 +16,15 @@
 
 package net.taler.common
 
+import android.os.Build
 import kotlinx.serialization.KSerializer
 import kotlinx.serialization.Serializable
 import kotlinx.serialization.Serializer
 import kotlinx.serialization.encoding.Decoder
 import kotlinx.serialization.encoding.Encoder
+import java.text.DecimalFormat
+import java.text.DecimalFormatSymbols
+import java.text.NumberFormat
 import kotlin.math.floor
 import kotlin.math.pow
 import kotlin.math.roundToInt
@@ -54,6 +58,11 @@ public data class Amount(
      * of 50_000_000 would correspond to 50 cents.
      */
     val fraction: Int,
+
+    /**
+     * Currency specification for amount
+     */
+    val spec: CurrencySpecification? = null,
 ) : Comparable<Amount> {
 
     public companion object {
@@ -170,6 +179,8 @@ public data class Amount(
         return Amount(checkCurrency(currency), this.value, this.fraction)
     }
 
+    fun withSpec(spec: CurrencySpecification?) = copy(spec = spec)
+
     public operator fun minus(other: Amount): Amount {
         check(currency == other.currency) { "Can only subtract from same 
currency" }
         var resultValue = value
@@ -196,8 +207,50 @@ public data class Amount(
         return "$currency:$amountStr"
     }
 
-    override fun toString(): String {
-        return "$amountStr $currency"
+    override fun toString() = toString(
+        showSymbol = true,
+        negative = false,
+    )
+
+    fun toString(
+        showSymbol: Boolean = true,
+        negative: Boolean = false,
+        symbols: DecimalFormatSymbols = DecimalFormat().decimalFormatSymbols,
+    ): String {
+        // We clone the object to safely/cleanly modify it
+        val s = symbols.clone() as DecimalFormatSymbols
+        val amount = (if (negative) "-$amountStr" else 
amountStr).toBigDecimal()
+
+        // No currency spec, so we render normally
+        if (spec == null) {
+            val format = NumberFormat.getInstance()
+            format.maximumFractionDigits = MAX_FRACTION_LENGTH
+            format.minimumFractionDigits = 0
+            if (Build.VERSION.SDK_INT >= 34) {
+                s.groupingSeparator = s.monetaryGroupingSeparator
+            }
+            s.decimalSeparator = s.monetaryDecimalSeparator
+            (format as DecimalFormat).decimalFormatSymbols = s
+
+            val fmt = format.format(amount)
+            return if (showSymbol) "$fmt $currency" else fmt
+        }
+
+        // There is currency spec, so we can do things right
+        val format = NumberFormat.getCurrencyInstance()
+        format.maximumFractionDigits = spec.numFractionalNormalDigits
+        format.minimumFractionDigits = spec.numFractionalTrailingZeroDigits
+        s.currencySymbol = spec.symbol ?: ""
+        (format as DecimalFormat).decimalFormatSymbols = s
+
+        val fmt = format.format(amount)
+        return if (showSymbol) {
+            // If no symbol, then we use the currency string
+            if (spec.symbol != null) fmt else "$fmt $currency"
+        } else {
+            // We should do better than manually removing the symbol here
+            fmt.replace(s.currencySymbol, "").trim()
+        }
     }
 
     override fun compareTo(other: Amount): Int {
diff --git 
a/wallet/src/main/java/net/taler/wallet/balances/CurrencySpecification.kt 
b/taler-kotlin-android/src/main/java/net/taler/common/CurrencySpecification.kt
similarity index 85%
rename from 
wallet/src/main/java/net/taler/wallet/balances/CurrencySpecification.kt
rename to 
taler-kotlin-android/src/main/java/net/taler/common/CurrencySpecification.kt
index 5001db4..02113f4 100644
--- a/wallet/src/main/java/net/taler/wallet/balances/CurrencySpecification.kt
+++ 
b/taler-kotlin-android/src/main/java/net/taler/common/CurrencySpecification.kt
@@ -1,6 +1,6 @@
 /*
  * This file is part of GNU Taler
- * (C) 2023 Taler Systems S.A.
+ * (C) 2024 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
@@ -14,7 +14,7 @@
  * GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-package net.taler.wallet.balances
+package net.taler.common
 
 import kotlinx.serialization.SerialName
 import kotlinx.serialization.Serializable
@@ -29,5 +29,8 @@ data class CurrencySpecification(
     @SerialName("num_fractional_trailing_zero_digits")
     val numFractionalTrailingZeroDigits: Int,
     @SerialName("alt_unit_names")
-    val altUnitNames: Map<String, String>,
-)
\ No newline at end of file
+    val altUnitNames: Map<Int, String>,
+) {
+    // TODO: add support for alt units
+    val symbol: String? get() = altUnitNames[0]
+}
\ No newline at end of file
diff --git a/taler-kotlin-android/src/test/java/net/taler/common/AmountTest.kt 
b/taler-kotlin-android/src/test/java/net/taler/common/AmountTest.kt
index 7072426..1ea4e70 100644
--- a/taler-kotlin-android/src/test/java/net/taler/common/AmountTest.kt
+++ b/taler-kotlin-android/src/test/java/net/taler/common/AmountTest.kt
@@ -16,10 +16,12 @@
 
 package net.taler.common
 
+import android.os.Build
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertFalse
 import org.junit.Assert.assertTrue
 import org.junit.Test
+import java.text.DecimalFormatSymbols
 import kotlin.random.Random
 
 class AmountTest {
@@ -41,7 +43,6 @@ class AmountTest {
         assertEquals("TESTKUDOS", amount.currency)
         assertEquals(23, amount.value)
         assertEquals((0.42 * 1e8).toInt(), amount.fraction)
-        assertEquals("23.42 TESTKUDOS", amount.toString())
 
         str = "EUR:500000000.00000001"
         amount = Amount.fromJSONString(str)
@@ -49,7 +50,6 @@ class AmountTest {
         assertEquals("EUR", amount.currency)
         assertEquals(500000000, amount.value)
         assertEquals(1, amount.fraction)
-        assertEquals("500000000.00000001 EUR", amount.toString())
 
         str = "EUR:1500000000.00000003"
         amount = Amount.fromJSONString(str)
@@ -57,14 +57,158 @@ class AmountTest {
         assertEquals("EUR", amount.currency)
         assertEquals(1500000000, amount.value)
         assertEquals(3, amount.fraction)
-        assertEquals("1500000000.00000003 EUR", amount.toString())
     }
 
     @Test
     fun testToString() {
-        Amount.fromString("BITCOINBTC", "0.00000001").let { amount ->
-            assertEquals("0.00000001 BITCOINBTC", amount.toString())
-            assertEquals("0.00000001", amount.amountStr)
+        amountToString(
+            amount = Amount.fromString("KUDOS", "13.71"),
+            spec = CurrencySpecification(
+                name = "Test (Taler Demostrator)",
+                numFractionalInputDigits = 2,
+                numFractionalNormalDigits = 2,
+                numFractionalTrailingZeroDigits = 2,
+                altUnitNames = mapOf(0 to "ク"),
+            ),
+            rawStr = "13.71",
+            fraction = 71000000,
+            specAmount = "13.71",
+            noSpecAmount = "13.71",
+            currency = "KUDOS",
+            symbol = "ク",
+        )
+
+        amountToString(
+            amount = Amount.fromString("TESTKUDOS", "23.42"),
+            spec = CurrencySpecification(
+                name = "Test (Taler Unstable Demostrator)",
+                numFractionalInputDigits = 0,
+                numFractionalNormalDigits = 0,
+                numFractionalTrailingZeroDigits = 0,
+                altUnitNames = mapOf(0 to "テ"),
+            ),
+            rawStr = "23.42",
+            fraction = 42000000,
+            specAmount = "23",
+            noSpecAmount = "23.42",
+            currency = "TESTKUDOS",
+            symbol = "テ",
+        )
+
+        amountToString(
+            amount = Amount.fromString("BITCOINBTC", "0.00000001"),
+            spec = CurrencySpecification(
+                name = "Bitcoin",
+                numFractionalInputDigits = 8,
+                numFractionalNormalDigits = 8,
+                numFractionalTrailingZeroDigits = 0,
+                altUnitNames = mapOf(
+                    0 to "₿",
+                    // TODO: uncomment when units get implemented
+                    //  and then write tests for units, please
+//                -1 to "d₿",
+//                -2 to "c₿",
+//                -3 to "m₿",
+//                -6 to "µ₿",
+//                -8 to "sat",
+                ),
+            ),
+            rawStr = "0.00000001",
+            fraction = 1,
+            specAmount = "0.00000001",
+            noSpecAmount = "0.00000001",
+            currency = "BITCOINBTC",
+            symbol = "₿",
+        )
+
+        val specEUR = CurrencySpecification(
+            name = "EUR",
+            numFractionalInputDigits = 2,
+            numFractionalNormalDigits = 2,
+            numFractionalTrailingZeroDigits = 2,
+            altUnitNames = mapOf(0 to "€"),
+        )
+
+        amountToString(
+            amount = Amount.fromString("EUR", "1500000000.00000003"),
+            spec = specEUR,
+            rawStr = "1500000000.00000003",
+            fraction = 3,
+            specAmount = "1,500,000,000.00",
+            noSpecAmount = "1,500,000,000.00000003",
+            currency = "EUR",
+            symbol = "€",
+        )
+
+        amountToString(
+            amount = Amount.fromString("EUR", "500000000.126"),
+            spec = specEUR,
+            rawStr = "500000000.126",
+            fraction = 12600000,
+            specAmount = "500,000,000.13",
+            noSpecAmount = "500,000,000.126",
+            currency = "EUR",
+            symbol = "€",
+        )
+
+        amountToString(
+            amount = Amount.fromString("NOSYMBOL", "13.24"),
+            spec = CurrencySpecification(
+                name = "No symbol!",
+                numFractionalInputDigits = 2,
+                numFractionalNormalDigits = 2,
+                numFractionalTrailingZeroDigits = 2,
+                altUnitNames = mapOf(),
+            ),
+            rawStr = "13.24",
+            fraction = 24000000,
+            specAmount = "13.24",
+            noSpecAmount = "13.24",
+            currency = "NOSYMBOL",
+            symbol = "NOSYMBOL",
+        )
+    }
+
+    private fun amountToString(
+        amount: Amount,
+        spec: CurrencySpecification,
+        rawStr: String,
+        fraction: Int,
+        specAmount: String,
+        noSpecAmount: String,
+        currency: String,
+        symbol: String,
+    ) {
+        val symbols = DecimalFormatSymbols.getInstance()
+        symbols.decimalSeparator = '.'
+        symbols.groupingSeparator = ','
+        symbols.monetaryDecimalSeparator = '.'
+        if (Build.VERSION.SDK_INT >= 34) {
+            symbols.monetaryGroupingSeparator = ','
+        }
+
+        // Only the raw amount
+        assertEquals(rawStr, amount.amountStr)
+        assertEquals(fraction, amount.fraction)
+
+        // The amount without currency spec
+        assertEquals("$noSpecAmount $currency", amount.toString(symbols = 
symbols))
+        assertEquals(noSpecAmount, amount.toString(symbols = symbols, 
showSymbol = false))
+        assertEquals("-$noSpecAmount $currency", amount.toString(symbols = 
symbols, negative = true))
+        assertEquals("-$noSpecAmount", amount.toString(symbols = symbols, 
showSymbol = false, negative = true))
+
+        // The amount with currency spec
+        val withSpec = amount.withSpec(spec)
+        assertEquals(specAmount, withSpec.toString(symbols = symbols, 
showSymbol = false))
+        assertEquals(specAmount, withSpec.toString(symbols = symbols, 
showSymbol = false))
+        assertEquals("-$specAmount", withSpec.toString(symbols = symbols, 
showSymbol = false, negative = true))
+        assertEquals("-$specAmount", withSpec.toString(symbols = symbols, 
showSymbol = false, negative = true))
+        if (spec.symbol != null) {
+            assertEquals("${symbol}$specAmount", withSpec.toString(symbols = 
symbols))
+            assertEquals("-${symbol}$specAmount", withSpec.toString(symbols = 
symbols, negative = true))
+        } else {
+            assertEquals("$specAmount $currency", withSpec.toString(symbols = 
symbols))
+            assertEquals("-$specAmount $currency", withSpec.toString(symbols = 
symbols, negative = true))
         }
     }
 
@@ -76,7 +220,6 @@ class AmountTest {
         assertEquals(str, amount.toJSONString())
         assertEquals("TESTKUDOS123", amount.currency)
         assertEquals(maxValue, amount.value)
-        assertEquals("$maxValue.99999999 TESTKUDOS123", amount.toString())
 
         // longer currency not accepted
         assertThrows<AmountParserException>("longer currency was accepted") {
diff --git a/wallet/src/main/java/net/taler/wallet/MainActivity.kt 
b/wallet/src/main/java/net/taler/wallet/MainActivity.kt
index 65e5c2a..5dfd920 100644
--- a/wallet/src/main/java/net/taler/wallet/MainActivity.kt
+++ b/wallet/src/main/java/net/taler/wallet/MainActivity.kt
@@ -346,8 +346,9 @@ class MainActivity : AppCompatActivity(), 
OnNavigationItemSelectedListener,
                     val transactionId = status.response.transactionId
                     val transaction = 
model.transactionManager.getTransactionById(transactionId)
                     if (transaction != null) {
-                        val currency = transaction.amountRaw.currency
-                        model.showTransactions(currency)
+                        // TODO: currency what? scopes are the cool thing now
+                        // val currency = transaction.amountRaw.currency
+                        // model.showTransactions(currency)
                         Snackbar.make(ui.navView, 
getString(R.string.refund_success), LENGTH_LONG).show()
                     }
                 }
diff --git a/wallet/src/main/java/net/taler/wallet/MainFragment.kt 
b/wallet/src/main/java/net/taler/wallet/MainFragment.kt
index 656db63..9fa9838 100644
--- a/wallet/src/main/java/net/taler/wallet/MainFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/MainFragment.kt
@@ -24,20 +24,20 @@ import androidx.fragment.app.Fragment
 import androidx.fragment.app.activityViewModels
 import androidx.navigation.fragment.findNavController
 import net.taler.common.EventObserver
-import net.taler.wallet.CurrencyMode.MULTI
-import net.taler.wallet.CurrencyMode.SINGLE
+import net.taler.wallet.ScopeMode.MULTI
+import net.taler.wallet.ScopeMode.SINGLE
 import net.taler.wallet.balances.BalanceState
 import net.taler.wallet.balances.BalanceState.Success
 import net.taler.wallet.balances.BalancesFragment
 import net.taler.wallet.databinding.FragmentMainBinding
 import net.taler.wallet.transactions.TransactionsFragment
 
-enum class CurrencyMode { SINGLE, MULTI }
+enum class ScopeMode { SINGLE, MULTI }
 
 class MainFragment : Fragment() {
 
     private val model: MainViewModel by activityViewModels()
-    private var currencyMode: CurrencyMode? = null
+    private var scopeMode: ScopeMode? = null
 
     private lateinit var ui: FragmentMainBinding
 
@@ -54,10 +54,10 @@ class MainFragment : Fragment() {
         model.balanceManager.state.observe(viewLifecycleOwner) {
             onBalancesChanged(it)
         }
-        model.transactionsEvent.observe(viewLifecycleOwner, EventObserver { 
currency ->
-            // we only need to navigate to a dedicated list, when in 
multi-currency mode
-            if (currencyMode == MULTI) {
-                model.transactionManager.selectedCurrency = currency
+        model.transactionsEvent.observe(viewLifecycleOwner, EventObserver { 
scopeInfo ->
+            // we only need to navigate to a dedicated list, when in 
multi-scope mode
+            if (scopeMode == MULTI) {
+                model.transactionManager.selectedScope = scopeInfo
                 
findNavController().navigate(R.id.action_nav_main_to_nav_transactions)
             }
         })
@@ -80,14 +80,14 @@ class MainFragment : Fragment() {
         if (state !is Success) return
         val balances = state.balances
         val mode = if (balances.size == 1) SINGLE else MULTI
-        if (currencyMode != mode) {
+        if (scopeMode != mode) {
             val f = if (mode == SINGLE) {
-                model.transactionManager.selectedCurrency = 
balances[0].available.currency
+                model.transactionManager.selectedScope = balances[0].scopeInfo
                 TransactionsFragment()
             } else {
                 BalancesFragment()
             }
-            currencyMode = mode
+            scopeMode = mode
             childFragmentManager.beginTransaction()
                 .replace(R.id.mainFragmentContainer, f, mode.name)
                 .commitNow()
diff --git a/wallet/src/main/java/net/taler/wallet/MainViewModel.kt 
b/wallet/src/main/java/net/taler/wallet/MainViewModel.kt
index fe11d6a..5903446 100644
--- a/wallet/src/main/java/net/taler/wallet/MainViewModel.kt
+++ b/wallet/src/main/java/net/taler/wallet/MainViewModel.kt
@@ -36,6 +36,7 @@ import net.taler.wallet.backend.VersionReceiver
 import net.taler.wallet.backend.WalletBackendApi
 import net.taler.wallet.backend.WalletCoreVersion
 import net.taler.wallet.balances.BalanceManager
+import net.taler.wallet.balances.ScopeInfo
 import net.taler.wallet.deposit.DepositManager
 import net.taler.wallet.exchanges.ExchangeManager
 import net.taler.wallet.payment.PaymentManager
@@ -81,8 +82,8 @@ class MainViewModel(
     val accountManager: AccountManager = AccountManager(api, viewModelScope)
     val depositManager: DepositManager = DepositManager(api, viewModelScope)
 
-    private val mTransactionsEvent = MutableLiveData<Event<String>>()
-    val transactionsEvent: LiveData<Event<String>> = mTransactionsEvent
+    private val mTransactionsEvent = MutableLiveData<Event<ScopeInfo>>()
+    val transactionsEvent: LiveData<Event<ScopeInfo>> = mTransactionsEvent
 
     private val mScanCodeEvent = MutableLiveData<Event<Boolean>>()
     val scanCodeEvent: LiveData<Event<Boolean>> = mScanCodeEvent
@@ -99,7 +100,7 @@ class MainViewModel(
         Log.i(TAG, "Received notification from wallet-core: $payload")
 
         // Only update balances when we're told they changed
-        if (payload.type == "balance-change") {
+        if (payload.type == "balance-change") 
viewModelScope.launch(Dispatchers.Main) {
             balanceManager.loadBalances()
         }
 
@@ -111,11 +112,11 @@ class MainViewModel(
     }
 
     /**
-     * Navigates to the given currency's transaction list, when [MainFragment] 
is shown.
+     * Navigates to the given scope info's transaction list, when 
[MainFragment] is shown.
      */
     @UiThread
-    fun showTransactions(currency: String) {
-        mTransactionsEvent.value = currency.toEvent()
+    fun showTransactions(scopeInfo: ScopeInfo) {
+        mTransactionsEvent.value = scopeInfo.toEvent()
     }
 
     @UiThread
diff --git a/wallet/src/main/java/net/taler/wallet/ReceiveFundsFragment.kt 
b/wallet/src/main/java/net/taler/wallet/ReceiveFundsFragment.kt
index a25c352..9a83bc8 100644
--- a/wallet/src/main/java/net/taler/wallet/ReceiveFundsFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/ReceiveFundsFragment.kt
@@ -51,7 +51,9 @@ import androidx.fragment.app.activityViewModels
 import androidx.lifecycle.lifecycleScope
 import androidx.navigation.fragment.findNavController
 import net.taler.common.Amount
+import net.taler.common.CurrencySpecification
 import net.taler.wallet.compose.AmountInputField
+import net.taler.wallet.compose.DEFAULT_INPUT_DECIMALS
 import net.taler.wallet.compose.TalerSurface
 import net.taler.wallet.exchanges.ExchangeItem
 
@@ -59,7 +61,9 @@ class ReceiveFundsFragment : Fragment() {
     private val model: MainViewModel by activityViewModels()
     private val exchangeManager get() = model.exchangeManager
     private val withdrawManager get() = model.withdrawManager
+    private val balanceManager get() = model.balanceManager
     private val peerManager get() = model.peerManager
+    private val scopeInfo get() = model.transactionManager.selectedScope ?: 
error("No scope selected")
 
     override fun onCreateView(
         inflater: LayoutInflater, container: ViewGroup?,
@@ -68,7 +72,8 @@ class ReceiveFundsFragment : Fragment() {
         setContent {
             TalerSurface {
                 ReceiveFundsIntro(
-                    model.transactionManager.selectedCurrency ?: error("No 
currency selected"),
+                    scopeInfo.currency,
+                    balanceManager.getSpecForScopeInfo(scopeInfo),
                     this@ReceiveFundsFragment::onManualWithdraw,
                     this@ReceiveFundsFragment::onPeerPull,
                 )
@@ -78,7 +83,7 @@ class ReceiveFundsFragment : Fragment() {
 
     override fun onStart() {
         super.onStart()
-        activity?.setTitle(R.string.transactions_receive_funds)
+        
activity?.setTitle(getString(R.string.transactions_receive_funds_title, 
scopeInfo.currency))
     }
 
     private fun onManualWithdraw(amount: Amount) {
@@ -113,6 +118,7 @@ class ReceiveFundsFragment : Fragment() {
 @Composable
 private fun ReceiveFundsIntro(
     currency: String,
+    spec: CurrencySpecification?,
     onManualWithdraw: (Amount) -> Unit,
     onPeerPull: (Amount) -> Unit,
 ) {
@@ -143,10 +149,11 @@ private fun ReceiveFundsIntro(
                     if (isError) 
Text(stringResource(R.string.receive_amount_invalid))
                 },
                 isError = isError,
+                numberOfDecimals = spec?.numFractionalInputDigits ?: 
DEFAULT_INPUT_DECIMALS,
             )
             Text(
                 modifier = Modifier,
-                text = currency,
+                text = spec?.symbol ?: currency,
                 softWrap = false,
                 style = MaterialTheme.typography.titleLarge,
             )
@@ -189,6 +196,6 @@ private fun ReceiveFundsIntro(
 @Composable
 fun PreviewReceiveFundsIntro() {
     Surface {
-        ReceiveFundsIntro("TESTKUDOS", {}) {}
+        ReceiveFundsIntro("TESTKUDOS", null, {}) {}
     }
 }
diff --git a/wallet/src/main/java/net/taler/wallet/SendFundsFragment.kt 
b/wallet/src/main/java/net/taler/wallet/SendFundsFragment.kt
index 09d33e2..2581979 100644
--- a/wallet/src/main/java/net/taler/wallet/SendFundsFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/SendFundsFragment.kt
@@ -48,12 +48,16 @@ import androidx.fragment.app.Fragment
 import androidx.fragment.app.activityViewModels
 import androidx.navigation.fragment.findNavController
 import net.taler.common.Amount
+import net.taler.common.CurrencySpecification
 import net.taler.wallet.compose.AmountInputField
+import net.taler.wallet.compose.DEFAULT_INPUT_DECIMALS
 import net.taler.wallet.compose.TalerSurface
 
 class SendFundsFragment : Fragment() {
     private val model: MainViewModel by activityViewModels()
+    private val balanceManager get() = model.balanceManager
     private val peerManager get() = model.peerManager
+    private val scopeInfo get() = model.transactionManager.selectedScope ?: 
error("No scope selected")
 
     override fun onCreateView(
         inflater: LayoutInflater,
@@ -63,8 +67,8 @@ class SendFundsFragment : Fragment() {
         setContent {
             TalerSurface {
                 SendFundsIntro(
-                    currency = model.transactionManager.selectedCurrency
-                        ?: error("No currency selected"),
+                    currency = scopeInfo.currency,
+                    spec = balanceManager.getSpecForScopeInfo(scopeInfo),
                     hasSufficientBalance = model::hasSufficientBalance,
                     onDeposit = this@SendFundsFragment::onDeposit,
                     onPeerPush = this@SendFundsFragment::onPeerPush,
@@ -75,7 +79,7 @@ class SendFundsFragment : Fragment() {
 
     override fun onStart() {
         super.onStart()
-        activity?.setTitle(R.string.transactions_send_funds)
+        activity?.setTitle(getString(R.string.transactions_send_funds_title, 
scopeInfo.currency))
     }
 
     private fun onDeposit(amount: Amount) {
@@ -93,6 +97,7 @@ class SendFundsFragment : Fragment() {
 @Composable
 private fun SendFundsIntro(
     currency: String,
+    spec: CurrencySpecification?,
     hasSufficientBalance: (Amount) -> Boolean,
     onDeposit: (Amount) -> Unit,
     onPeerPush: (Amount) -> Unit,
@@ -129,10 +134,11 @@ private fun SendFundsIntro(
                     }
                 },
                 isError = isError || insufficientBalance,
+                numberOfDecimals = spec?.numFractionalInputDigits ?: 
DEFAULT_INPUT_DECIMALS,
             )
             Text(
                 modifier = Modifier,
-                text = currency,
+                text = spec?.symbol ?: currency,
                 softWrap = false,
                 style = MaterialTheme.typography.titleLarge,
             )
@@ -185,6 +191,6 @@ private fun SendFundsIntro(
 @Composable
 fun PreviewSendFundsIntro() {
     Surface {
-        SendFundsIntro("TESTKUDOS", { true }, {}) {}
+        SendFundsIntro("TESTKUDOS", null, { true }, {}) {}
     }
 }
diff --git a/wallet/src/main/java/net/taler/wallet/balances/BalanceAdapter.kt 
b/wallet/src/main/java/net/taler/wallet/balances/BalanceAdapter.kt
index efb3d48..f40def4 100644
--- a/wallet/src/main/java/net/taler/wallet/balances/BalanceAdapter.kt
+++ b/wallet/src/main/java/net/taler/wallet/balances/BalanceAdapter.kt
@@ -58,7 +58,6 @@ class BalanceAdapter(private val listener: 
BalanceClickListener) : Adapter<Balan
     }
 
     inner class BalanceViewHolder(private val v: View) : 
RecyclerView.ViewHolder(v) {
-        private val currencyView: TextView = 
v.findViewById(R.id.balanceCurrencyView)
         private val amountView: TextView = 
v.findViewById(R.id.balanceAmountView)
         private val scopeView: TextView = v.findViewById(R.id.scopeView)
         private val balanceInboundAmount: TextView = 
v.findViewById(R.id.balanceInboundAmount)
@@ -66,9 +65,8 @@ class BalanceAdapter(private val listener: 
BalanceClickListener) : Adapter<Balan
         private val pendingView: TextView = v.findViewById(R.id.pendingView)
 
         fun bind(item: BalanceItem) {
-            v.setOnClickListener { 
listener.onBalanceClick(item.available.currency) }
-            currencyView.text = item.currency
-            amountView.text = item.available.amountStr
+            v.setOnClickListener { listener.onBalanceClick(item.scopeInfo) }
+            amountView.text = item.available.toString()
 
             val amountIncoming = item.pendingIncoming
             if (amountIncoming.isZero()) {
@@ -77,8 +75,7 @@ class BalanceAdapter(private val listener: 
BalanceClickListener) : Adapter<Balan
             } else {
                 balanceInboundAmount.visibility = VISIBLE
                 balanceInboundLabel.visibility = VISIBLE
-                balanceInboundAmount.text =
-                    v.context.getString(R.string.amount_positive, 
amountIncoming)
+                balanceInboundAmount.text = 
v.context.getString(R.string.amount_positive, 
amountIncoming.toString(showSymbol = false))
             }
 
             val scopeInfo = item.scopeInfo
diff --git a/wallet/src/main/java/net/taler/wallet/balances/BalanceManager.kt 
b/wallet/src/main/java/net/taler/wallet/balances/BalanceManager.kt
index 2930c77..42e67cf 100644
--- a/wallet/src/main/java/net/taler/wallet/balances/BalanceManager.kt
+++ b/wallet/src/main/java/net/taler/wallet/balances/BalanceManager.kt
@@ -24,15 +24,24 @@ import androidx.lifecycle.distinctUntilChanged
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.launch
 import kotlinx.serialization.Serializable
+import kotlinx.serialization.encodeToString
+import kotlinx.serialization.json.Json
+import net.taler.common.CurrencySpecification
 import net.taler.wallet.TAG
 import net.taler.wallet.backend.TalerErrorInfo
 import net.taler.wallet.backend.WalletBackendApi
+import org.json.JSONObject
 
 @Serializable
 data class BalanceResponse(
     val balances: List<BalanceItem>
 )
 
+@Serializable
+data class GetCurrencySpecificationResponse(
+    val currencySpecification: CurrencySpecification,
+)
+
 sealed class BalanceState {
     data object None: BalanceState()
     data object Loading: BalanceState()
@@ -56,6 +65,8 @@ class BalanceManager(
     private val mState = MutableLiveData<BalanceState>(BalanceState.None)
     val state: LiveData<BalanceState> = mState.distinctUntilChanged()
 
+    private val currencySpecs: MutableMap<ScopeInfo, CurrencySpecification?> = 
mutableMapOf()
+
     @UiThread
     fun loadBalances() {
         mState.value = BalanceState.Loading
@@ -66,12 +77,60 @@ class BalanceManager(
                 mState.postValue(BalanceState.Error(it))
             }
             response.onSuccess {
-                mState.postValue(BalanceState.Success(it.balances))
                 mBalances.postValue(it.balances)
+                scope.launch {
+                    // Fetch missing currency specs for all balances
+                    it.balances.forEach { balance ->
+                        if (!currencySpecs.containsKey(balance.scopeInfo)) {
+                            currencySpecs[balance.scopeInfo] = 
getCurrencySpecification(balance.scopeInfo)
+                        }
+                    }
+
+                    mState.postValue(
+                        BalanceState.Success(it.balances.map { balance ->
+                            val spec = currencySpecs[balance.scopeInfo]
+                            balance.copy(
+                                available = balance.available.withSpec(spec),
+                                pendingIncoming = 
balance.pendingIncoming.withSpec(spec),
+                                pendingOutgoing = 
balance.pendingOutgoing.withSpec(spec),
+                            )
+                        }),
+                    )
+                }
             }
         }
     }
 
+    private suspend fun getCurrencySpecification(scopeInfo: ScopeInfo): 
CurrencySpecification? {
+        var spec: CurrencySpecification? = null
+        api.request("getCurrencySpecification", 
GetCurrencySpecificationResponse.serializer()) {
+            val json = Json.encodeToString(scopeInfo)
+            Log.d(TAG, "BalanceManager: $json")
+            put("scope", JSONObject(json))
+        }.onSuccess {
+            spec = it.currencySpecification
+        }.onError {
+            Log.e(TAG, "Error getting currency spec for scope $scopeInfo: $it")
+        }
+
+        return spec
+    }
+
+    @Deprecated("Please find spec via scopeInfo instead", 
ReplaceWith("getSpecForScopeInfo"))
+    fun getSpecForCurrency(currency: String): CurrencySpecification? {
+        val state = mState.value
+        if (state !is BalanceState.Success) return null
+
+        return state.balances.find { it.currency == currency }?.available?.spec
+    }
+
+    fun getSpecForScopeInfo(scopeInfo: ScopeInfo): CurrencySpecification? {
+        val state = mState.value
+        if (state !is BalanceState.Success) return null
+
+        return state.balances.find { it.scopeInfo == scopeInfo 
}?.available?.spec
+    }
+
     fun resetBalances() {
         mState.value = BalanceState.None
     }
diff --git a/wallet/src/main/java/net/taler/wallet/balances/BalancesFragment.kt 
b/wallet/src/main/java/net/taler/wallet/balances/BalancesFragment.kt
index cfbbc46..93636ea 100644
--- a/wallet/src/main/java/net/taler/wallet/balances/BalancesFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/balances/BalancesFragment.kt
@@ -39,7 +39,7 @@ import net.taler.wallet.databinding.FragmentBalancesBinding
 import net.taler.wallet.showError
 
 interface BalanceClickListener {
-    fun onBalanceClick(currency: String)
+    fun onBalanceClick(scopeInfo: ScopeInfo)
 }
 
 class BalancesFragment : Fragment(),
@@ -96,8 +96,8 @@ class BalancesFragment : Fragment(),
         }
     }
 
-    override fun onBalanceClick(currency: String) {
-        model.showTransactions(currency)
+    override fun onBalanceClick(scopeInfo: ScopeInfo) {
+        model.showTransactions(scopeInfo)
     }
 
 }
diff --git a/wallet/src/main/java/net/taler/wallet/compose/AmountInputField.kt 
b/wallet/src/main/java/net/taler/wallet/compose/AmountInputField.kt
index 077c89a..a524d1b 100644
--- a/wallet/src/main/java/net/taler/wallet/compose/AmountInputField.kt
+++ b/wallet/src/main/java/net/taler/wallet/compose/AmountInputField.kt
@@ -40,6 +40,8 @@ import kotlin.math.max
 import kotlin.math.pow
 import kotlin.math.roundToLong
 
+const val DEFAULT_INPUT_DECIMALS = 2
+
 @Composable
 fun AmountInputField(
     value: String,
@@ -50,7 +52,7 @@ fun AmountInputField(
     isError: Boolean = false,
     keyboardActions: KeyboardActions = KeyboardActions.Default,
     decimalFormatSymbols: DecimalFormatSymbols = 
DecimalFormat().decimalFormatSymbols,
-    numberOfDecimals: Int = 2,
+    numberOfDecimals: Int = DEFAULT_INPUT_DECIMALS,
 ) {
     var amountInput by remember { mutableStateOf(value) }
 
@@ -146,7 +148,12 @@ private class AmountInputVisualTransformation(
             }
         }
 
-        val formattedNumber = intPart + decimalSeparator + fractionPart
+        // Hide trailing decimal separator if decimals are 0
+        val formattedNumber = if (numberOfDecimals > 0) {
+            intPart + decimalSeparator + fractionPart
+        } else {
+            intPart
+        }
 
         val newText = AnnotatedString(
             text = formattedNumber,
diff --git a/wallet/src/main/java/net/taler/wallet/deposit/DepositFragment.kt 
b/wallet/src/main/java/net/taler/wallet/deposit/DepositFragment.kt
index 28dcc3f..20acee1 100644
--- a/wallet/src/main/java/net/taler/wallet/deposit/DepositFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/deposit/DepositFragment.kt
@@ -37,6 +37,8 @@ import net.taler.wallet.showError
 class DepositFragment : Fragment() {
     private val model: MainViewModel by activityViewModels()
     private val depositManager get() = model.depositManager
+    private val balanceManager get() = model.balanceManager
+    private val transactionManager get() = model.transactionManager
 
     override fun onCreateView(
         inflater: LayoutInflater,
@@ -46,6 +48,8 @@ class DepositFragment : Fragment() {
         val amount = arguments?.getString("amount")?.let {
             Amount.fromJSONString(it)
         } ?: error("no amount passed")
+        val scopeInfo = transactionManager.selectedScope
+        val spec = scopeInfo?.let { balanceManager.getSpecForScopeInfo(it) }
         val receiverName = arguments?.getString("receiverName")
         val iban = arguments?.getString("IBAN")
         if (receiverName != null && iban != null) {
@@ -57,14 +61,14 @@ class DepositFragment : Fragment() {
                     val state = 
depositManager.depositState.collectAsStateLifecycleAware()
                     if (amount.currency == CURRENCY_BTC) 
MakeBitcoinDepositComposable(
                         state = state.value,
-                        amount = amount,
+                        amount = amount.withSpec(spec),
                         bitcoinAddress = null,
                         onMakeDeposit = { amount, bitcoinAddress ->
                             depositManager.onDepositButtonClicked(amount, 
bitcoinAddress)
                         },
                     ) else MakeDepositComposable(
                         state = state.value,
-                        amount = amount,
+                        amount = amount.withSpec(spec),
                         presetName = receiverName,
                         presetIban = iban,
                         onMakeDeposit = 
this@DepositFragment::onDepositButtonClicked,
diff --git 
a/wallet/src/main/java/net/taler/wallet/deposit/MakeDepositComposable.kt 
b/wallet/src/main/java/net/taler/wallet/deposit/MakeDepositComposable.kt
index 97e2eb0..9333ce1 100644
--- a/wallet/src/main/java/net/taler/wallet/deposit/MakeDepositComposable.kt
+++ b/wallet/src/main/java/net/taler/wallet/deposit/MakeDepositComposable.kt
@@ -138,13 +138,13 @@ fun MakeDepositComposable(
 
                 TransactionAmountComposable(
                     label = stringResource(R.string.withdraw_fees),
-                    amount = fee,
+                    amount = fee.withSpec(amount.spec),
                     amountType = if (fee.isZero()) Positive else Negative,
                 )
 
                 TransactionAmountComposable(
                     label = stringResource(R.string.send_amount),
-                    amount = effectiveAmount,
+                    amount = effectiveAmount.withSpec(amount.spec),
                     amountType = Positive,
                 )
             }
diff --git 
a/wallet/src/main/java/net/taler/wallet/deposit/TransactionDepositComposable.kt 
b/wallet/src/main/java/net/taler/wallet/deposit/TransactionDepositComposable.kt
index 807d631..817dfac 100644
--- 
a/wallet/src/main/java/net/taler/wallet/deposit/TransactionDepositComposable.kt
+++ 
b/wallet/src/main/java/net/taler/wallet/deposit/TransactionDepositComposable.kt
@@ -32,6 +32,7 @@ import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import net.taler.common.Amount
+import net.taler.common.CurrencySpecification
 import net.taler.common.Timestamp
 import net.taler.common.toAbsoluteTime
 import net.taler.wallet.R
@@ -53,6 +54,7 @@ import net.taler.wallet.transactions.TransitionsComposable
 fun TransactionDepositComposable(
     t: TransactionDeposit,
     devMode: Boolean,
+    spec: CurrencySpecification?,
     onTransition: (t: TransactionAction) -> Unit,
 ) {
     val scrollState = rememberScrollState()
@@ -71,7 +73,7 @@ fun TransactionDepositComposable(
 
         TransactionAmountComposable(
             label = stringResource(id = R.string.amount_chosen),
-            amount = t.amountRaw,
+            amount = t.amountRaw.withSpec(spec),
             amountType = AmountType.Neutral,
         )
 
@@ -79,14 +81,14 @@ fun TransactionDepositComposable(
         if (!fee.isZero()) {
             TransactionAmountComposable(
                 label = stringResource(id = R.string.withdraw_fees),
-                amount = fee,
+                amount = fee.withSpec(spec),
                 amountType = AmountType.Negative,
             )
         }
 
         TransactionAmountComposable(
             label = stringResource(id = R.string.amount_sent),
-            amount = t.amountEffective,
+            amount = t.amountEffective.withSpec(spec),
             amountType = AmountType.Negative,
         )
 
@@ -112,6 +114,6 @@ fun TransactionDepositComposablePreview() {
         error = TalerErrorInfo(code = EXCHANGE_GENERIC_KYC_REQUIRED),
     )
     Surface {
-        TransactionDepositComposable(t, true) {}
+        TransactionDepositComposable(t, true, null) {}
     }
 }
diff --git 
a/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeListFragment.kt 
b/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeListFragment.kt
index 494b187..5482b5a 100644
--- a/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeListFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeListFragment.kt
@@ -141,7 +141,7 @@ open class ExchangeListFragment : Fragment(), 
ExchangeClickListener {
     }
 
     override fun onPeerReceive(item: ExchangeItem) {
-        transactionManager.selectedCurrency = item.currency
+        transactionManager.selectedScope = item.scopeInfo
         findNavController().navigate(R.id.action_global_receiveFunds)
     }
 
diff --git a/wallet/src/main/java/net/taler/wallet/exchanges/Exchanges.kt 
b/wallet/src/main/java/net/taler/wallet/exchanges/Exchanges.kt
index af373c2..ce0bd82 100644
--- a/wallet/src/main/java/net/taler/wallet/exchanges/Exchanges.kt
+++ b/wallet/src/main/java/net/taler/wallet/exchanges/Exchanges.kt
@@ -17,6 +17,7 @@
 package net.taler.wallet.exchanges
 
 import kotlinx.serialization.Serializable
+import net.taler.wallet.balances.ScopeInfo
 import net.taler.wallet.cleanExchange
 
 @Serializable
@@ -25,6 +26,7 @@ data class ExchangeItem(
     // can be null before exchange info in wallet-core was fully loaded
     val currency: String? = null,
     val paytoUris: List<String>,
+    val scopeInfo: ScopeInfo? = null,
 ) {
     val name: String get() = cleanExchange(exchangeBaseUrl)
 }
\ No newline at end of file
diff --git 
a/wallet/src/main/java/net/taler/wallet/payment/TransactionPaymentComposable.kt 
b/wallet/src/main/java/net/taler/wallet/payment/TransactionPaymentComposable.kt
index 5bbbd97..0f6d661 100644
--- 
a/wallet/src/main/java/net/taler/wallet/payment/TransactionPaymentComposable.kt
+++ 
b/wallet/src/main/java/net/taler/wallet/payment/TransactionPaymentComposable.kt
@@ -32,6 +32,7 @@ import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import net.taler.common.Amount
 import net.taler.common.ContractMerchant
+import net.taler.common.CurrencySpecification
 import net.taler.common.Timestamp
 import net.taler.common.toAbsoluteTime
 import net.taler.wallet.R
@@ -57,6 +58,7 @@ import net.taler.wallet.transactions.TransitionsComposable
 fun TransactionPaymentComposable(
     t: TransactionPayment,
     devMode: Boolean,
+    spec: CurrencySpecification?,
     onFulfill: (url: String) -> Unit,
     onTransition: (t: TransactionAction) -> Unit,
 ) {
@@ -76,7 +78,7 @@ fun TransactionPaymentComposable(
 
         TransactionAmountComposable(
             label = stringResource(id = R.string.transaction_order_total),
-            amount = t.amountRaw,
+            amount = t.amountRaw.withSpec(spec),
             amountType = AmountType.Neutral,
         )
 
@@ -84,14 +86,14 @@ fun TransactionPaymentComposable(
         if (!fee.isZero()) {
             TransactionAmountComposable(
                 label = stringResource(id = R.string.withdraw_fees),
-                amount = fee,
+                amount = fee.withSpec(spec),
                 amountType = AmountType.Negative,
             )
         }
 
         TransactionAmountComposable(
             label = stringResource(id = R.string.transaction_paid),
-            amount = t.amountEffective,
+            amount = t.amountEffective.withSpec(spec),
             amountType = AmountType.Negative,
         )
 
@@ -167,6 +169,6 @@ fun TransactionPaymentComposablePreview() {
         error = TalerErrorInfo(code = 
TalerErrorCode.WALLET_WITHDRAWAL_KYC_REQUIRED),
     )
     TalerSurface {
-        TransactionPaymentComposable(t = t, devMode = true, onFulfill = {}) {}
+        TransactionPaymentComposable(t = t, devMode = true, spec = null, 
onFulfill = {}) {}
     }
 }
diff --git 
a/wallet/src/main/java/net/taler/wallet/peer/OutgoingPullComposable.kt 
b/wallet/src/main/java/net/taler/wallet/peer/OutgoingPullComposable.kt
index d58b0b8..90b520e 100644
--- a/wallet/src/main/java/net/taler/wallet/peer/OutgoingPullComposable.kt
+++ b/wallet/src/main/java/net/taler/wallet/peer/OutgoingPullComposable.kt
@@ -152,7 +152,7 @@ fun OutgoingPullIntroComposable(
             val fee = state.amountRaw - state.amountEffective
             if (!fee.isZero()) TransactionAmountComposable(
                 label = stringResource(id = R.string.withdraw_fees),
-                amount = fee,
+                amount = fee.withSpec(amount.spec),
                 amountType = AmountType.Negative,
             )
         }
diff --git a/wallet/src/main/java/net/taler/wallet/peer/OutgoingPullFragment.kt 
b/wallet/src/main/java/net/taler/wallet/peer/OutgoingPullFragment.kt
index 0205ae0..8f2fb96 100644
--- a/wallet/src/main/java/net/taler/wallet/peer/OutgoingPullFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/peer/OutgoingPullFragment.kt
@@ -40,6 +40,7 @@ class OutgoingPullFragment : Fragment() {
     private val model: MainViewModel by activityViewModels()
     private val peerManager get() = model.peerManager
     private val transactionManager get() = model.transactionManager
+    private val balanceManager get() = model.balanceManager
 
     override fun onCreateView(
         inflater: LayoutInflater,
@@ -49,12 +50,15 @@ class OutgoingPullFragment : Fragment() {
         val amount = arguments?.getString("amount")?.let {
             Amount.fromJSONString(it)
         } ?: error("no amount passed")
+        val scopeInfo = transactionManager.selectedScope
+        val spec = scopeInfo?.let { balanceManager.getSpecForScopeInfo(it) }
+
         return ComposeView(requireContext()).apply {
             setContent {
                 TalerSurface {
                     val state = 
peerManager.pullState.collectAsStateLifecycleAware().value
                     OutgoingPullComposable(
-                        amount = amount,
+                        amount = amount.withSpec(spec),
                         state = state,
                         onCreateInvoice = 
this@OutgoingPullFragment::onCreateInvoice,
                         onClose = {
diff --git 
a/wallet/src/main/java/net/taler/wallet/peer/OutgoingPushComposable.kt 
b/wallet/src/main/java/net/taler/wallet/peer/OutgoingPushComposable.kt
index ea303d0..d39fdc8 100644
--- a/wallet/src/main/java/net/taler/wallet/peer/OutgoingPushComposable.kt
+++ b/wallet/src/main/java/net/taler/wallet/peer/OutgoingPushComposable.kt
@@ -93,7 +93,7 @@ fun OutgoingPushIntroComposable(
             val fee = state.amountEffective - state.amountRaw
             Text(
                 modifier = Modifier.padding(vertical = 16.dp),
-                text = stringResource(id = R.string.payment_fee, fee),
+                text = stringResource(id = R.string.payment_fee, 
fee.withSpec(amount.spec)),
                 softWrap = false,
                 color = MaterialTheme.colorScheme.error,
             )
diff --git a/wallet/src/main/java/net/taler/wallet/peer/OutgoingPushFragment.kt 
b/wallet/src/main/java/net/taler/wallet/peer/OutgoingPushFragment.kt
index 97dbcc2..01fb566 100644
--- a/wallet/src/main/java/net/taler/wallet/peer/OutgoingPushFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/peer/OutgoingPushFragment.kt
@@ -41,6 +41,7 @@ class OutgoingPushFragment : Fragment() {
     private val model: MainViewModel by activityViewModels()
     private val peerManager get() = model.peerManager
     private val transactionManager get() = model.transactionManager
+    private val balanceManager get() = model.balanceManager
 
     // hacky way to change back action until we have navigation for compose
     private val backPressedCallback = object : OnBackPressedCallback(false) {
@@ -57,6 +58,8 @@ class OutgoingPushFragment : Fragment() {
         val amount = arguments?.getString("amount")?.let {
             Amount.fromJSONString(it)
         } ?: error("no amount passed")
+        val scopeInfo = transactionManager.selectedScope
+        val spec = scopeInfo?.let { balanceManager.getSpecForScopeInfo(it) }
 
         requireActivity().onBackPressedDispatcher.addCallback(
             viewLifecycleOwner, backPressedCallback
@@ -67,7 +70,7 @@ class OutgoingPushFragment : Fragment() {
                 TalerSurface {
                     val state = 
peerManager.pushState.collectAsStateLifecycleAware().value
                     OutgoingPushComposable(
-                        amount = amount,
+                        amount = amount.withSpec(spec),
                         state = state,
                         onSend = this@OutgoingPushFragment::onSend,
                         onClose = {
diff --git 
a/wallet/src/main/java/net/taler/wallet/peer/TransactionPeerPullCredit.kt 
b/wallet/src/main/java/net/taler/wallet/peer/TransactionPeerPullCredit.kt
index 898ff69..3b15b6f 100644
--- a/wallet/src/main/java/net/taler/wallet/peer/TransactionPeerPullCredit.kt
+++ b/wallet/src/main/java/net/taler/wallet/peer/TransactionPeerPullCredit.kt
@@ -22,6 +22,7 @@ import androidx.compose.runtime.Composable
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.tooling.preview.Preview
 import net.taler.common.Amount
+import net.taler.common.CurrencySpecification
 import net.taler.common.Timestamp
 import net.taler.wallet.R
 import net.taler.wallet.backend.TalerErrorCode.EXCHANGE_GENERIC_KYC_REQUIRED
@@ -41,7 +42,7 @@ import net.taler.wallet.transactions.TransactionPeerPullCredit
 import net.taler.wallet.transactions.TransactionState
 
 @Composable
-fun ColumnScope.TransactionPeerPullCreditComposable(t: 
TransactionPeerPullCredit) {
+fun ColumnScope.TransactionPeerPullCreditComposable(t: 
TransactionPeerPullCredit, spec: CurrencySpecification?) {
     if (t.error == null) PeerQrCode(
         state = t.txState,
         talerUri = t.talerUri,
@@ -49,7 +50,7 @@ fun ColumnScope.TransactionPeerPullCreditComposable(t: 
TransactionPeerPullCredit
     
     TransactionAmountComposable(
         label = stringResource(id = R.string.receive_peer_amount_invoiced),
-        amount = t.amountRaw,
+        amount = t.amountRaw.withSpec(spec),
         amountType = AmountType.Neutral,
     )
 
@@ -57,14 +58,14 @@ fun ColumnScope.TransactionPeerPullCreditComposable(t: 
TransactionPeerPullCredit
     if (!fee.isZero()) {
         TransactionAmountComposable(
             label = stringResource(id = R.string.withdraw_fees),
-            amount = fee,
+            amount = fee.withSpec(spec),
             amountType = AmountType.Negative,
         )
     }
 
     TransactionAmountComposable(
         label = stringResource(id = R.string.amount_received),
-        amount = t.amountEffective,
+        amount = t.amountEffective.withSpec(spec),
         amountType = AmountType.Positive,
     )
 
@@ -93,7 +94,7 @@ fun TransactionPeerPullCreditPreview(loading: Boolean = 
false) {
         error = TalerErrorInfo(code = EXCHANGE_GENERIC_KYC_REQUIRED),
     )
     Surface {
-        TransactionPeerComposable(t, true) {}
+        TransactionPeerComposable(t, true, null) {}
     }
 }
 
diff --git 
a/wallet/src/main/java/net/taler/wallet/peer/TransactionPeerPullDebit.kt 
b/wallet/src/main/java/net/taler/wallet/peer/TransactionPeerPullDebit.kt
index 783907e..dadff4a 100644
--- a/wallet/src/main/java/net/taler/wallet/peer/TransactionPeerPullDebit.kt
+++ b/wallet/src/main/java/net/taler/wallet/peer/TransactionPeerPullDebit.kt
@@ -21,6 +21,7 @@ import androidx.compose.runtime.Composable
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.tooling.preview.Preview
 import net.taler.common.Amount
+import net.taler.common.CurrencySpecification
 import net.taler.common.Timestamp
 import net.taler.wallet.R
 import net.taler.wallet.backend.TalerErrorCode.EXCHANGE_GENERIC_KYC_REQUIRED
@@ -38,25 +39,25 @@ import 
net.taler.wallet.transactions.TransactionPeerPullDebit
 import net.taler.wallet.transactions.TransactionState
 
 @Composable
-fun TransactionPeerPullDebitComposable(t: TransactionPeerPullDebit) {
+fun TransactionPeerPullDebitComposable(t: TransactionPeerPullDebit, spec: 
CurrencySpecification?) {
     TransactionAmountComposable(
         label = stringResource(id = R.string.transaction_order_total),
-        amount = t.amountRaw,
+        amount = t.amountRaw.withSpec(spec),
         amountType = AmountType.Neutral,
     )
-    
+
     val fee = t.amountEffective - t.amountRaw
     if (!fee.isZero()) {
         TransactionAmountComposable(
             label = stringResource(id = R.string.withdraw_fees),
-            amount = fee,
+            amount = fee.withSpec(spec),
             amountType = AmountType.Negative,
         )
     }
 
     TransactionAmountComposable(
         label = stringResource(id = R.string.transaction_paid),
-        amount = t.amountEffective,
+        amount = t.amountEffective.withSpec(spec),
         amountType = AmountType.Negative,
     )
 
@@ -84,6 +85,6 @@ fun TransactionPeerPullDebitPreview() {
         error = TalerErrorInfo(code = EXCHANGE_GENERIC_KYC_REQUIRED),
     )
     Surface {
-        TransactionPeerComposable(t, true) {}
+        TransactionPeerComposable(t, true, null) {}
     }
 }
diff --git 
a/wallet/src/main/java/net/taler/wallet/peer/TransactionPeerPushCredit.kt 
b/wallet/src/main/java/net/taler/wallet/peer/TransactionPeerPushCredit.kt
index 75d299b..dbf0fb9 100644
--- a/wallet/src/main/java/net/taler/wallet/peer/TransactionPeerPushCredit.kt
+++ b/wallet/src/main/java/net/taler/wallet/peer/TransactionPeerPushCredit.kt
@@ -21,6 +21,7 @@ import androidx.compose.runtime.Composable
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.tooling.preview.Preview
 import net.taler.common.Amount
+import net.taler.common.CurrencySpecification
 import net.taler.common.Timestamp
 import net.taler.wallet.R
 import net.taler.wallet.backend.TalerErrorCode.EXCHANGE_GENERIC_KYC_REQUIRED
@@ -38,10 +39,10 @@ import 
net.taler.wallet.transactions.TransactionPeerPushCredit
 import net.taler.wallet.transactions.TransactionState
 
 @Composable
-fun TransactionPeerPushCreditComposable(t: TransactionPeerPushCredit) {
+fun TransactionPeerPushCreditComposable(t: TransactionPeerPushCredit, spec: 
CurrencySpecification?) {
     TransactionAmountComposable(
         label = stringResource(id = R.string.amount_sent),
-        amount = t.amountRaw,
+        amount = t.amountRaw.withSpec(spec),
         amountType = AmountType.Neutral,
     )
 
@@ -49,14 +50,14 @@ fun TransactionPeerPushCreditComposable(t: 
TransactionPeerPushCredit) {
     if (!fee.isZero()) {
         TransactionAmountComposable(
             label = stringResource(id = R.string.withdraw_fees),
-            amount = fee,
+            amount = fee.withSpec(spec),
             amountType = AmountType.Negative,
         )
     }
 
     TransactionAmountComposable(
         label = stringResource(id = R.string.amount_received),
-        amount = t.amountEffective,
+        amount = t.amountEffective.withSpec(spec),
         amountType = AmountType.Positive,
     )
 
@@ -84,6 +85,6 @@ fun TransactionPeerPushCreditPreview() {
         error = TalerErrorInfo(code = EXCHANGE_GENERIC_KYC_REQUIRED),
     )
     Surface {
-        TransactionPeerComposable(t, true) {}
+        TransactionPeerComposable(t, true, null) {}
     }
 }
diff --git 
a/wallet/src/main/java/net/taler/wallet/peer/TransactionPeerPushDebit.kt 
b/wallet/src/main/java/net/taler/wallet/peer/TransactionPeerPushDebit.kt
index 909fd47..e592c3e 100644
--- a/wallet/src/main/java/net/taler/wallet/peer/TransactionPeerPushDebit.kt
+++ b/wallet/src/main/java/net/taler/wallet/peer/TransactionPeerPushDebit.kt
@@ -30,6 +30,7 @@ import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import net.taler.common.Amount
+import net.taler.common.CurrencySpecification
 import net.taler.common.Timestamp
 import net.taler.wallet.R
 import net.taler.wallet.backend.TalerErrorCode.EXCHANGE_GENERIC_KYC_REQUIRED
@@ -52,7 +53,7 @@ import net.taler.wallet.transactions.TransactionPeerPushDebit
 import net.taler.wallet.transactions.TransactionState
 
 @Composable
-fun ColumnScope.TransactionPeerPushDebitComposable(t: 
TransactionPeerPushDebit) {
+fun ColumnScope.TransactionPeerPushDebitComposable(t: 
TransactionPeerPushDebit, spec: CurrencySpecification?) {
     if (t.error == null) PeerQrCode(
         state = t.txState,
         talerUri = t.talerUri,
@@ -60,7 +61,7 @@ fun ColumnScope.TransactionPeerPushDebitComposable(t: 
TransactionPeerPushDebit)
 
     TransactionAmountComposable(
         label = stringResource(id = R.string.transaction_order_total),
-        amount = t.amountRaw,
+        amount = t.amountRaw.withSpec(spec),
         amountType = AmountType.Neutral,
     )
 
@@ -68,14 +69,14 @@ fun ColumnScope.TransactionPeerPushDebitComposable(t: 
TransactionPeerPushDebit)
     if (!fee.isZero()) {
         TransactionAmountComposable(
             label = stringResource(id = R.string.withdraw_fees),
-            amount = fee,
+            amount = fee.withSpec(spec),
             amountType = AmountType.Negative,
         )
     }
 
     TransactionAmountComposable(
         label = stringResource(id = R.string.transaction_paid),
-        amount = t.amountEffective,
+        amount = t.amountEffective.withSpec(spec),
         amountType = AmountType.Negative,
     )
 
@@ -140,7 +141,7 @@ fun TransactionPeerPushDebitPreview(loading: Boolean = 
false) {
     )
 
     TalerSurface {
-        TransactionPeerComposable(t, true) {}
+        TransactionPeerComposable(t, true, null) {}
     }
 }
 
diff --git 
a/wallet/src/main/java/net/taler/wallet/refund/TransactionRefundComposable.kt 
b/wallet/src/main/java/net/taler/wallet/refund/TransactionRefundComposable.kt
index 82dceb5..637b41a 100644
--- 
a/wallet/src/main/java/net/taler/wallet/refund/TransactionRefundComposable.kt
+++ 
b/wallet/src/main/java/net/taler/wallet/refund/TransactionRefundComposable.kt
@@ -31,6 +31,7 @@ import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import net.taler.common.Amount
+import net.taler.common.CurrencySpecification
 import net.taler.common.Timestamp
 import net.taler.common.toAbsoluteTime
 import net.taler.wallet.R
@@ -54,6 +55,7 @@ import net.taler.wallet.transactions.TransitionsComposable
 fun TransactionRefundComposable(
     t: TransactionRefund,
     devMode: Boolean,
+    spec: CurrencySpecification?,
     onTransition: (t: TransactionAction) -> Unit,
 ) {
     val scrollState = rememberScrollState()
@@ -71,19 +73,19 @@ fun TransactionRefundComposable(
         )
         TransactionAmountComposable(
             label = stringResource(id = R.string.transaction_refund),
-            amount = t.amountEffective,
+            amount = t.amountEffective.withSpec(spec),
             amountType = AmountType.Positive,
         )
         TransactionAmountComposable(
             label = stringResource(id = R.string.transaction_order_total),
-            amount = t.amountRaw,
+            amount = t.amountRaw.withSpec(spec),
             amountType = AmountType.Neutral,
         )
         val fee = t.amountRaw - t.amountEffective
         if (!fee.isZero()) {
             TransactionAmountComposable(
                 label = stringResource(id = R.string.withdraw_fees),
-                amount = fee,
+                amount = fee.withSpec(spec),
                 amountType = AmountType.Negative,
             )
         }
@@ -116,6 +118,6 @@ fun TransactionRefundComposablePreview() {
         error = TalerErrorInfo(code = 
TalerErrorCode.WALLET_WITHDRAWAL_KYC_REQUIRED),
     )
     TalerSurface {
-        TransactionRefundComposable(t = t, devMode = true) {}
+        TransactionRefundComposable(t = t, devMode = true, spec = null) {}
     }
 }
diff --git 
a/wallet/src/main/java/net/taler/wallet/transactions/TransactionAdapter.kt 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionAdapter.kt
index c9ae889..22dcc3f 100644
--- a/wallet/src/main/java/net/taler/wallet/transactions/TransactionAdapter.kt
+++ b/wallet/src/main/java/net/taler/wallet/transactions/TransactionAdapter.kt
@@ -32,6 +32,7 @@ import androidx.recyclerview.selection.SelectionTracker
 import androidx.recyclerview.widget.RecyclerView
 import androidx.recyclerview.widget.RecyclerView.Adapter
 import androidx.recyclerview.widget.RecyclerView.ViewHolder
+import net.taler.common.CurrencySpecification
 import net.taler.common.exhaustive
 import net.taler.common.toRelativeTime
 import net.taler.wallet.R
@@ -47,6 +48,8 @@ internal class TransactionAdapter(
 ) : Adapter<TransactionViewHolder>() {
 
     private var transactions: List<Transaction> = ArrayList()
+    private var currencySpec: CurrencySpecification? = null
+
     lateinit var tracker: SelectionTracker<String>
     val keyProvider = TransactionKeyProvider()
 
@@ -67,6 +70,11 @@ internal class TransactionAdapter(
         holder.bind(transaction, tracker.isSelected(transaction.transactionId))
     }
 
+    fun setCurrencySpec(spec: CurrencySpecification?) {
+        this.currencySpec = spec
+        this.notifyDataSetChanged()
+    }
+
     fun update(updatedTransactions: List<Transaction>) {
         this.transactions = updatedTransactions
         this.notifyDataSetChanged()
@@ -183,7 +191,7 @@ internal class TransactionAdapter(
         }
 
         private fun bindAmount(transaction: Transaction) {
-            val amountStr = transaction.amountEffective.amountStr
+            val amountStr = 
transaction.amountEffective.withSpec(currencySpec).toString(showSymbol = false)
             when (transaction.amountType) {
                 AmountType.Positive -> {
                     amount.text = context.getString(R.string.amount_positive, 
amountStr)
diff --git 
a/wallet/src/main/java/net/taler/wallet/transactions/TransactionDepositFragment.kt
 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionDepositFragment.kt
index f23b8d7..d2be3cf 100644
--- 
a/wallet/src/main/java/net/taler/wallet/transactions/TransactionDepositFragment.kt
+++ 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionDepositFragment.kt
@@ -38,6 +38,7 @@ class TransactionDepositFragment : 
TransactionDetailFragment() {
                 if (t is TransactionDeposit) TransactionDepositComposable(
                     t = t,
                     devMode = devMode,
+                    spec = 
balanceManager.getSpecForCurrency(t.amountRaw.currency),
                 ) {
                     onTransitionButtonClicked(t, it)
                 }
diff --git 
a/wallet/src/main/java/net/taler/wallet/transactions/TransactionDetailFragment.kt
 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionDetailFragment.kt
index 78b728a..09ca05b 100644
--- 
a/wallet/src/main/java/net/taler/wallet/transactions/TransactionDetailFragment.kt
+++ 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionDetailFragment.kt
@@ -39,6 +39,7 @@ abstract class TransactionDetailFragment : Fragment() {
 
     private val model: MainViewModel by activityViewModels()
     protected val transactionManager by lazy { model.transactionManager }
+    protected val balanceManager by lazy { model.balanceManager }
     protected val devMode get() = model.devMode.value == true
 
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
diff --git 
a/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt
index 534ed6c..5399287 100644
--- a/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt
+++ b/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt
@@ -23,11 +23,15 @@ import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.switchMap
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.launch
+import kotlinx.serialization.encodeToString
+import kotlinx.serialization.json.Json
 import net.taler.wallet.TAG
 import net.taler.wallet.backend.TalerErrorInfo
 import net.taler.wallet.backend.WalletBackendApi
+import net.taler.wallet.balances.ScopeInfo
 import net.taler.wallet.transactions.TransactionAction.Delete
 import net.taler.wallet.transactions.TransactionMajorState.Pending
+import org.json.JSONObject
 import java.util.LinkedList
 
 sealed class TransactionsResult {
@@ -45,34 +49,34 @@ class TransactionManager(
 
     // FIXME if the app gets killed, this will not be restored and thus be 
unexpected null
     //  we should keep this in a savable, maybe using Hilt and 
SavedStateViewModel
-    var selectedCurrency: String? = null
+    var selectedScope: ScopeInfo? = null
 
     val searchQuery = MutableLiveData<String>(null)
     private val mSelectedTransaction = MutableLiveData<Transaction?>(null)
     val selectedTransaction: LiveData<Transaction?> = mSelectedTransaction
-    private val allTransactions = HashMap<String, List<Transaction>>()
-    private val mTransactions = HashMap<String, 
MutableLiveData<TransactionsResult>>()
+    private val allTransactions = HashMap<ScopeInfo, List<Transaction>>()
+    private val mTransactions = HashMap<ScopeInfo, 
MutableLiveData<TransactionsResult>>()
     val transactions: LiveData<TransactionsResult>
         @UiThread
         get() = searchQuery.switchMap { query ->
-            val currency = selectedCurrency
-            check(currency != null) { "Did not select currency before getting 
transactions" }
+            val scopeInfo = selectedScope
+            check(scopeInfo != null) { "Did not select scope before getting 
transactions" }
             loadTransactions(query)
-            mTransactions[currency]!! // non-null because filled in 
[loadTransactions]
+            mTransactions[scopeInfo]!! // non-null because filled in 
[loadTransactions]
         }
 
     @UiThread
     fun loadTransactions(searchQuery: String? = null) = scope.launch {
-        val currency = selectedCurrency ?: return@launch
-        val liveData = mTransactions.getOrPut(currency) { MutableLiveData() }
-        if (searchQuery == null && allTransactions.containsKey(currency)) {
-            liveData.value = 
TransactionsResult.Success(allTransactions[currency]!!)
+        val scopeInfo = selectedScope ?: return@launch
+        val liveData = mTransactions.getOrPut(scopeInfo) { MutableLiveData() }
+        if (searchQuery == null && allTransactions.containsKey(scopeInfo)) {
+            liveData.value = 
TransactionsResult.Success(allTransactions[scopeInfo]!!)
         }
         if (liveData.value == null) mProgress.value = true
 
         api.request("getTransactions", Transactions.serializer()) {
             if (searchQuery != null) put("search", searchQuery)
-            put("currency", currency)
+            put("scopeInfo", JSONObject(Json.encodeToString(scopeInfo)))
         }.onError {
             liveData.postValue(TransactionsResult.Error(it))
             mProgress.postValue(false)
@@ -91,8 +95,8 @@ class TransactionManager(
                 mSelectedTransaction.value = it
             }
 
-            // update all transactions on UiThread if there was a currency
-            if (searchQuery == null) allTransactions[currency] = transactions
+            // update all transactions on UiThread if there was a scope info
+            if (searchQuery == null) allTransactions[scopeInfo] = transactions
         }
     }
 
@@ -201,7 +205,7 @@ class TransactionManager(
         }
 
     fun deleteTransactions(transactionIds: List<String>, onError: (it: 
TalerErrorInfo) -> Unit) {
-        allTransactions[selectedCurrency]?.filter { transaction ->
+        allTransactions[selectedScope]?.filter { transaction ->
             transaction.transactionId in transactionIds
         }?.forEach { toBeDeletedTx ->
             if (Delete in toBeDeletedTx.txActions) {
diff --git 
a/wallet/src/main/java/net/taler/wallet/transactions/TransactionPaymentFragment.kt
 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionPaymentFragment.kt
index 27598ab..596a4a9 100644
--- 
a/wallet/src/main/java/net/taler/wallet/transactions/TransactionPaymentFragment.kt
+++ 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionPaymentFragment.kt
@@ -37,6 +37,7 @@ class TransactionPaymentFragment : 
TransactionDetailFragment() {
             TalerSurface {
                 val t = 
transactionManager.selectedTransaction.observeAsState().value
                 if (t is TransactionPayment) TransactionPaymentComposable(t, 
devMode,
+                    balanceManager.getSpecForCurrency(t.amountRaw.currency),
                     onFulfill = { url ->
                         launchInAppBrowser(requireContext(), url)
                     },
diff --git 
a/wallet/src/main/java/net/taler/wallet/transactions/TransactionPeerFragment.kt 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionPeerFragment.kt
index c934d89..27809a7 100644
--- 
a/wallet/src/main/java/net/taler/wallet/transactions/TransactionPeerFragment.kt
+++ 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionPeerFragment.kt
@@ -38,6 +38,7 @@ import androidx.compose.ui.res.colorResource
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
 import net.taler.common.Amount
+import net.taler.common.CurrencySpecification
 import net.taler.common.toAbsoluteTime
 import net.taler.wallet.R
 import net.taler.wallet.compose.TalerSurface
@@ -56,7 +57,9 @@ class TransactionPeerFragment : TransactionDetailFragment() {
         setContent {
             TalerSurface {
                 val t = 
transactionManager.selectedTransaction.observeAsState(null).value
-                if (t != null) TransactionPeerComposable(t, devMode) {
+                if (t != null) TransactionPeerComposable(t, devMode,
+                    balanceManager.getSpecForCurrency(t.amountRaw.currency),
+                ) {
                     onTransitionButtonClicked(t, it)
                 }
             }
@@ -68,6 +71,7 @@ class TransactionPeerFragment : TransactionDetailFragment() {
 fun TransactionPeerComposable(
     t: Transaction,
     devMode: Boolean,
+    spec: CurrencySpecification?,
     onTransition: (t: TransactionAction) -> Unit,
 ) {
     val scrollState = rememberScrollState()
@@ -84,10 +88,10 @@ fun TransactionPeerComposable(
             style = MaterialTheme.typography.bodyLarge,
         )
         when (t) {
-            is TransactionPeerPullCredit -> 
TransactionPeerPullCreditComposable(t)
-            is TransactionPeerPushCredit -> 
TransactionPeerPushCreditComposable(t)
-            is TransactionPeerPullDebit -> 
TransactionPeerPullDebitComposable(t)
-            is TransactionPeerPushDebit -> 
TransactionPeerPushDebitComposable(t)
+            is TransactionPeerPullCredit -> 
TransactionPeerPullCreditComposable(t, spec)
+            is TransactionPeerPushCredit -> 
TransactionPeerPushCreditComposable(t, spec)
+            is TransactionPeerPullDebit -> 
TransactionPeerPullDebitComposable(t, spec)
+            is TransactionPeerPushDebit -> 
TransactionPeerPushDebitComposable(t, spec)
             else -> error("unexpected transaction: ${t::class.simpleName}")
         }
         TransitionsComposable(t, devMode, onTransition)
@@ -106,7 +110,7 @@ fun TransactionAmountComposable(label: String, amount: 
Amount, amountType: Amoun
     )
     Text(
         modifier = Modifier.padding(top = 8.dp, start = 16.dp, end = 16.dp, 
bottom = 16.dp),
-        text = if (amountType == AmountType.Negative) "-$amount" else 
amount.toString(),
+        text = amount.toString(negative = amountType == AmountType.Negative),
         fontSize = 24.sp,
         color = when (amountType) {
             AmountType.Positive -> colorResource(R.color.green)
diff --git 
a/wallet/src/main/java/net/taler/wallet/transactions/TransactionRefreshFragment.kt
 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionRefreshFragment.kt
index da4b14d..8f474f9 100644
--- 
a/wallet/src/main/java/net/taler/wallet/transactions/TransactionRefreshFragment.kt
+++ 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionRefreshFragment.kt
@@ -38,6 +38,7 @@ import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import net.taler.common.Amount
+import net.taler.common.CurrencySpecification
 import net.taler.common.Timestamp
 import net.taler.common.toAbsoluteTime
 import net.taler.wallet.R
@@ -59,7 +60,9 @@ class TransactionRefreshFragment : 
TransactionDetailFragment() {
         setContent {
             TalerSurface {
                 val t = 
transactionManager.selectedTransaction.observeAsState().value
-                if (t is TransactionRefresh) TransactionRefreshComposable(t, 
devMode) {
+                if (t is TransactionRefresh) TransactionRefreshComposable(t, 
devMode,
+                    balanceManager.getSpecForCurrency(t.amountRaw.currency),
+                ) {
                     onTransitionButtonClicked(t, it)
                 }
             }
@@ -71,6 +74,7 @@ class TransactionRefreshFragment : 
TransactionDetailFragment() {
 private fun TransactionRefreshComposable(
     t: TransactionRefresh,
     devMode: Boolean,
+    spec: CurrencySpecification?,
     onTransition: (t: TransactionAction) -> Unit,
 ) {
     val scrollState = rememberScrollState()
@@ -88,7 +92,7 @@ private fun TransactionRefreshComposable(
         )
         TransactionAmountComposable(
             label = stringResource(id = R.string.withdraw_fees),
-            amount = t.amountEffective,
+            amount = t.amountEffective.withSpec(spec),
             amountType = AmountType.Negative,
         )
         TransitionsComposable(t, devMode, onTransition)
@@ -111,6 +115,6 @@ private fun TransactionRefreshComposablePreview() {
         error = TalerErrorInfo(code = 
TalerErrorCode.WALLET_WITHDRAWAL_KYC_REQUIRED),
     )
     Surface {
-        TransactionRefreshComposable(t, true) {}
+        TransactionRefreshComposable(t, true, null) {}
     }
 }
diff --git 
a/wallet/src/main/java/net/taler/wallet/transactions/TransactionRefundFragment.kt
 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionRefundFragment.kt
index cd50be7..7992565 100644
--- 
a/wallet/src/main/java/net/taler/wallet/transactions/TransactionRefundFragment.kt
+++ 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionRefundFragment.kt
@@ -35,7 +35,9 @@ class TransactionRefundFragment : TransactionDetailFragment() 
{
         setContent {
             TalerSurface {
                 val t = 
transactionManager.selectedTransaction.observeAsState().value
-                if (t is TransactionRefund) TransactionRefundComposable(t, 
devMode) {
+                if (t is TransactionRefund) TransactionRefundComposable(t, 
devMode,
+                    balanceManager.getSpecForCurrency(t.amountRaw.currency)
+                ) {
                     onTransitionButtonClicked(t, it)
                 }
             }
diff --git 
a/wallet/src/main/java/net/taler/wallet/transactions/TransactionWithdrawalFragment.kt
 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionWithdrawalFragment.kt
index 969db13..27e59bb 100644
--- 
a/wallet/src/main/java/net/taler/wallet/transactions/TransactionWithdrawalFragment.kt
+++ 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionWithdrawalFragment.kt
@@ -49,6 +49,7 @@ class TransactionWithdrawalFragment : 
TransactionDetailFragment(), ActionListene
                 if (t is TransactionWithdrawal) 
TransactionWithdrawalComposable(
                     t = t,
                     devMode = devMode,
+                    spec = 
balanceManager.getSpecForCurrency(t.amountRaw.currency),
                     actionListener = this@TransactionWithdrawalFragment,
                 ) {
                     onTransitionButtonClicked(t, it)
diff --git a/wallet/src/main/java/net/taler/wallet/transactions/Transactions.kt 
b/wallet/src/main/java/net/taler/wallet/transactions/Transactions.kt
index 9017854..be36a13 100644
--- a/wallet/src/main/java/net/taler/wallet/transactions/Transactions.kt
+++ b/wallet/src/main/java/net/taler/wallet/transactions/Transactions.kt
@@ -41,7 +41,7 @@ import net.taler.wallet.R
 import net.taler.wallet.TAG
 import net.taler.wallet.backend.TalerErrorCode
 import net.taler.wallet.backend.TalerErrorInfo
-import net.taler.wallet.balances.CurrencySpecification
+import net.taler.common.CurrencySpecification
 import net.taler.wallet.cleanExchange
 import net.taler.wallet.refund.RefundPaymentInfo
 import net.taler.wallet.transactions.TransactionMajorState.None
diff --git 
a/wallet/src/main/java/net/taler/wallet/transactions/TransactionsFragment.kt 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionsFragment.kt
index 3f610d3..5243427 100644
--- a/wallet/src/main/java/net/taler/wallet/transactions/TransactionsFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/transactions/TransactionsFragment.kt
@@ -37,7 +37,6 @@ import androidx.recyclerview.selection.StorageStrategy
 import androidx.recyclerview.widget.DividerItemDecoration
 import androidx.recyclerview.widget.LinearLayoutManager.VERTICAL
 import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import net.taler.common.Amount
 import net.taler.common.fadeIn
 import net.taler.common.fadeOut
 import net.taler.common.showError
@@ -56,10 +55,11 @@ class TransactionsFragment : Fragment(), 
OnTransactionClickListener, ActionMode.
 
     private val model: MainViewModel by activityViewModels()
     private val transactionManager by lazy { model.transactionManager }
+    private val balanceManager by lazy { model.balanceManager }
 
     private lateinit var ui: FragmentTransactionsBinding
     private val transactionAdapter by lazy { TransactionAdapter(this) }
-    private val currency by lazy { transactionManager.selectedCurrency!! }
+    private val scopeInfo by lazy { transactionManager.selectedScope!! }
     private var tracker: SelectionTracker<String>? = null
     private var actionMode: ActionMode? = null
 
@@ -108,13 +108,15 @@ class TransactionsFragment : Fragment(), 
OnTransactionClickListener, ActionMode.
             }
         })
 
-        model.balanceManager.state.observe(viewLifecycleOwner) { state ->
+        balanceManager.state.observe(viewLifecycleOwner) { state ->
             if (state !is Success) return@observe
             val balances = state.balances
             // hide extra fab when in single currency mode (uses 
MainFragment's FAB)
             if (balances.size == 1) ui.mainFab.visibility = INVISIBLE
-            balances.find { it.currency == currency }?.available?.let { 
amount: Amount ->
-                ui.amount.text = amount.amountStr
+
+            balances.find { it.scopeInfo == scopeInfo }?.let { balance ->
+                ui.amount.text = balance.available.toString(showSymbol = false)
+                transactionAdapter.setCurrencySpec(balance.available.spec)
             }
         }
         transactionManager.progress.observe(viewLifecycleOwner) { show ->
@@ -151,7 +153,7 @@ class TransactionsFragment : Fragment(), 
OnTransactionClickListener, ActionMode.
 
     override fun onStart() {
         super.onStart()
-        requireActivity().title = 
getString(R.string.transactions_detail_title_currency, currency)
+        requireActivity().title = 
getString(R.string.transactions_detail_title_currency, scopeInfo.currency)
     }
 
     private fun setupSearch(item: MenuItem) {
diff --git 
a/wallet/src/main/java/net/taler/wallet/withdraw/TransactionWithdrawalComposable.kt
 
b/wallet/src/main/java/net/taler/wallet/withdraw/TransactionWithdrawalComposable.kt
index fda1815..5155b5b 100644
--- 
a/wallet/src/main/java/net/taler/wallet/withdraw/TransactionWithdrawalComposable.kt
+++ 
b/wallet/src/main/java/net/taler/wallet/withdraw/TransactionWithdrawalComposable.kt
@@ -38,7 +38,7 @@ import net.taler.wallet.R
 import net.taler.wallet.backend.TalerErrorCode
 import net.taler.wallet.backend.TalerErrorInfo
 import net.taler.wallet.cleanExchange
-import net.taler.wallet.balances.CurrencySpecification
+import net.taler.common.CurrencySpecification
 import net.taler.wallet.transactions.ActionButton
 import net.taler.wallet.transactions.ActionListener
 import net.taler.wallet.transactions.AmountType
@@ -61,6 +61,7 @@ import 
net.taler.wallet.transactions.WithdrawalExchangeAccountDetails
 fun TransactionWithdrawalComposable(
     t: TransactionWithdrawal,
     devMode: Boolean,
+    spec: CurrencySpecification?,
     actionListener: ActionListener,
     onTransition: (t: TransactionAction) -> Unit,
 ) {
@@ -82,7 +83,7 @@ fun TransactionWithdrawalComposable(
 
         TransactionAmountComposable(
             label = stringResource(R.string.amount_chosen),
-            amount = t.amountRaw,
+            amount = t.amountRaw.withSpec(spec),
             amountType = AmountType.Neutral,
         )
 
@@ -90,14 +91,14 @@ fun TransactionWithdrawalComposable(
         if (!fee.isZero()) {
             TransactionAmountComposable(
                 label = stringResource(id = R.string.withdraw_fees),
-                amount = fee,
+                amount = fee.withSpec(spec),
                 amountType = AmountType.Negative,
             )
         }
 
         TransactionAmountComposable(
             label = stringResource(id = R.string.withdraw_total),
-            amount = t.amountEffective,
+            amount = t.amountEffective.withSpec(spec),
             amountType = AmountType.Positive,
         )
 
@@ -133,7 +134,7 @@ fun TransactionWithdrawalComposablePreview() {
                         numFractionalInputDigits = 2,
                         numFractionalNormalDigits = 2,
                         numFractionalTrailingZeroDigits = 2,
-                        altUnitNames = mapOf("0" to "NETZBON"),
+                        altUnitNames = mapOf(0 to "NETZBON"),
                     ),
                 ),
             ),
@@ -148,6 +149,6 @@ fun TransactionWithdrawalComposablePreview() {
     }
 
     Surface {
-        TransactionWithdrawalComposable(t, true, listener) {}
+        TransactionWithdrawalComposable(t, true, null, listener) {}
     }
 }
diff --git a/wallet/src/main/java/net/taler/wallet/withdraw/WithdrawManager.kt 
b/wallet/src/main/java/net/taler/wallet/withdraw/WithdrawManager.kt
index 4c9479b..e308b2a 100644
--- a/wallet/src/main/java/net/taler/wallet/withdraw/WithdrawManager.kt
+++ b/wallet/src/main/java/net/taler/wallet/withdraw/WithdrawManager.kt
@@ -31,6 +31,7 @@ import net.taler.common.toEvent
 import net.taler.wallet.TAG
 import net.taler.wallet.backend.TalerErrorInfo
 import net.taler.wallet.backend.WalletBackendApi
+import net.taler.wallet.balances.ScopeInfo
 import net.taler.wallet.exchanges.ExchangeFees
 import net.taler.wallet.exchanges.ExchangeItem
 import net.taler.wallet.transactions.WithdrawalExchangeAccountDetails
@@ -145,6 +146,7 @@ data class ManualWithdrawalDetails(
     val amountEffective: Amount,
     val withdrawalAccountsList: List<WithdrawalExchangeAccountDetails>,
     val ageRestrictionOptions: List<Int>? = null,
+    val scopeInfo: ScopeInfo,
 )
 
 @Serializable
diff --git 
a/wallet/src/main/java/net/taler/wallet/withdraw/manual/ManualWithdrawSuccessFragment.kt
 
b/wallet/src/main/java/net/taler/wallet/withdraw/manual/ManualWithdrawSuccessFragment.kt
index f09d275..63413c2 100644
--- 
a/wallet/src/main/java/net/taler/wallet/withdraw/manual/ManualWithdrawSuccessFragment.kt
+++ 
b/wallet/src/main/java/net/taler/wallet/withdraw/manual/ManualWithdrawSuccessFragment.kt
@@ -36,6 +36,7 @@ import net.taler.wallet.withdraw.WithdrawStatus
 class ManualWithdrawSuccessFragment : Fragment() {
     private val model: MainViewModel by activityViewModels()
     private val withdrawManager by lazy { model.withdrawManager }
+    private val balanceManager by lazy { model.balanceManager }
 
     private lateinit var status: WithdrawStatus.ManualTransferRequired
 
@@ -66,6 +67,7 @@ class ManualWithdrawSuccessFragment : Fragment() {
             TalerSurface {
                 ScreenTransfer(
                     status = status,
+                    spec = 
balanceManager.getSpecForCurrency(status.transactionAmountRaw.currency),
                     bankAppClick = { onBankAppClick(it) },
                     shareClick = { onShareClick(it) },
                 )
diff --git 
a/wallet/src/main/java/net/taler/wallet/withdraw/manual/ScreenTransfer.kt 
b/wallet/src/main/java/net/taler/wallet/withdraw/manual/ScreenTransfer.kt
index d75c685..35ff89c 100644
--- a/wallet/src/main/java/net/taler/wallet/withdraw/manual/ScreenTransfer.kt
+++ b/wallet/src/main/java/net/taler/wallet/withdraw/manual/ScreenTransfer.kt
@@ -47,8 +47,8 @@ import androidx.compose.ui.unit.dp
 import net.taler.common.Amount
 import net.taler.wallet.CURRENCY_BTC
 import net.taler.wallet.R
+import net.taler.common.CurrencySpecification
 import net.taler.wallet.compose.ShareButton
-import net.taler.wallet.balances.CurrencySpecification
 import net.taler.wallet.compose.copyToClipBoard
 import net.taler.wallet.transactions.AmountType
 import net.taler.wallet.transactions.TransactionAmountComposable
@@ -59,6 +59,7 @@ import net.taler.wallet.withdraw.WithdrawStatus
 @Composable
 fun ScreenTransfer(
     status: WithdrawStatus.ManualTransferRequired,
+    spec: CurrencySpecification?,
     bankAppClick: ((transfer: TransferData) -> Unit)?,
     shareClick: ((transfer: TransferData) -> Unit)?,
 ) {
@@ -98,14 +99,14 @@ fun ScreenTransfer(
                 is TransferData.IBAN -> TransferIBAN(
                     transfer = transfer,
                     exchangeBaseUrl = status.exchangeBaseUrl,
-                    transactionAmountRaw = status.transactionAmountRaw,
-                    transactionAmountEffective = 
status.transactionAmountEffective,
+                    transactionAmountRaw = 
status.transactionAmountRaw.withSpec(spec),
+                    transactionAmountEffective = 
status.transactionAmountEffective.withSpec(spec),
                 )
 
                 is TransferData.Bitcoin -> TransferBitcoin(
                     transfer = transfer,
-                    transactionAmountRaw = status.transactionAmountRaw,
-                    transactionAmountEffective = 
status.transactionAmountEffective,
+                    transactionAmountRaw = 
status.transactionAmountRaw.withSpec(spec),
+                    transactionAmountEffective = 
status.transactionAmountEffective.withSpec(spec),
                 )
             }
 
@@ -305,6 +306,7 @@ fun ScreenTransferPreview() {
                     )
                 ),
             ),
+            spec = null,
             bankAppClick = {},
             shareClick = {},
         )
diff --git 
a/wallet/src/main/java/net/taler/wallet/withdraw/manual/TransferBitcoin.kt 
b/wallet/src/main/java/net/taler/wallet/withdraw/manual/TransferBitcoin.kt
index 292f1d5..c21ca7e 100644
--- a/wallet/src/main/java/net/taler/wallet/withdraw/manual/TransferBitcoin.kt
+++ b/wallet/src/main/java/net/taler/wallet/withdraw/manual/TransferBitcoin.kt
@@ -60,7 +60,9 @@ fun TransferBitcoin(
             WithdrawalAmountTransfer(
                 amountRaw = transactionAmountRaw,
                 amountEffective = transactionAmountEffective,
-                conversionAmountRaw = amount,
+                conversionAmountRaw = amount.withSpec(
+                    transfer.withdrawalAccount.currencySpecification,
+                ),
             )
         }
     }
diff --git 
a/wallet/src/main/java/net/taler/wallet/withdraw/manual/TransferIBAN.kt 
b/wallet/src/main/java/net/taler/wallet/withdraw/manual/TransferIBAN.kt
index 1ebee4f..6c1b014 100644
--- a/wallet/src/main/java/net/taler/wallet/withdraw/manual/TransferIBAN.kt
+++ b/wallet/src/main/java/net/taler/wallet/withdraw/manual/TransferIBAN.kt
@@ -82,7 +82,9 @@ fun TransferIBAN(
             WithdrawalAmountTransfer(
                 amountRaw = transactionAmountRaw,
                 amountEffective = transactionAmountEffective,
-                conversionAmountRaw = amount,
+                conversionAmountRaw = amount.withSpec(
+                    transfer.withdrawalAccount.currencySpecification,
+                ),
             )
         }
     }
diff --git a/wallet/src/main/res/layout/list_item_balance.xml 
b/wallet/src/main/res/layout/list_item_balance.xml
index 82e663f..53e3d89 100644
--- a/wallet/src/main/res/layout/list_item_balance.xml
+++ b/wallet/src/main/res/layout/list_item_balance.xml
@@ -27,32 +27,20 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginEnd="8dp"
-        android:textSize="40sp"
-        app:layout_constraintEnd_toStartOf="@+id/balanceCurrencyView"
+        style="?textAppearanceDisplaySmall"
+        app:layout_constraintEnd_toStartOf="@+id/pendingView"
         app:layout_constraintHorizontal_bias="0.0"
         app:layout_constraintHorizontal_chainStyle="packed"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent"
         tools:text="100.50" />
 
-    <TextView
-        android:id="@+id/balanceCurrencyView"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginEnd="8dp"
-        android:textSize="20sp"
-        app:layout_constrainedWidth="true"
-        app:layout_constraintBottom_toBottomOf="@+id/balanceAmountView"
-        app:layout_constraintEnd_toStartOf="@+id/pendingView"
-        app:layout_constraintStart_toEndOf="@+id/balanceAmountView"
-        app:layout_constraintTop_toTopOf="@+id/balanceAmountView"
-        tools:text="TESTKUDOS" />
-
     <TextView
         android:id="@+id/scopeView"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
         android:layout_marginBottom="8dp"
+        style="?textAppearanceBodyMedium"
         android:visibility="gone"
         app:layout_constraintTop_toBottomOf="@id/balanceAmountView"
         app:layout_constraintBottom_toTopOf="@id/balanceInboundAmount"
@@ -67,6 +55,7 @@
         android:layout_height="wrap_content"
         android:textColor="@color/green"
         android:textSize="20sp"
+        style="?textAppearanceBodyLarge"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintEnd_toStartOf="@+id/balanceInboundLabel"
         app:layout_constraintHorizontal_bias="0.0"
@@ -83,6 +72,7 @@
         android:layout_marginStart="8dp"
         android:text="@string/balances_inbound_label"
         android:textColor="@color/green"
+        style="?textAppearanceBodyMedium"
         app:layout_constraintBottom_toBottomOf="@+id/balanceInboundAmount"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toEndOf="@+id/balanceInboundAmount"
diff --git a/wallet/src/main/res/values/strings.xml 
b/wallet/src/main/res/values/strings.xml
index 82a67b6..2ec3d40 100644
--- a/wallet/src/main/res/values/strings.xml
+++ b/wallet/src/main/res/values/strings.xml
@@ -87,7 +87,9 @@ GNU Taler is immune against many types of fraud, such as 
phishing of credit card
     <string name="transactions_title">Transactions</string>
     <string name="transactions_balance">Balance</string>
     <string name="transactions_send_funds">Send\nFunds</string>
+    <string name="transactions_send_funds_title">Send %1$s</string>
     <string name="transactions_receive_funds">Receive\nFunds</string>
+    <string name="transactions_receive_funds_title">Receive %1$s</string>
     <string name="transactions_empty">You don\'t have any transactions</string>
     <string name="transactions_empty_search">No transactions found. Try a 
different search.</string>
     <string name="transactions_error">Could not load 
transactions\n\n%s</string>

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

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