mirror of
https://codeberg.org/anoncontributorxmr/mysu.git
synced 2024-11-21 23:12:26 +00:00
feat: remove automatic donations, add donate to mysu label
This commit is contained in:
parent
4ee0e3134b
commit
8a769d0e23
10 changed files with 98 additions and 152 deletions
|
@ -2,6 +2,8 @@ package net.mynero.wallet.fragment.dialog
|
|||
|
||||
import android.app.Activity
|
||||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
@ -78,6 +80,7 @@ class SendBottomSheetDialog : BottomSheetDialogFragment() {
|
|||
private var scanAddressImageButton: ImageButton? = null
|
||||
private var feeRadioGroup: RadioGroup? = null
|
||||
private var donateTextView: TextView? = null
|
||||
private var donatingTextView: TextView? = null
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
|
@ -103,11 +106,28 @@ class SendBottomSheetDialog : BottomSheetDialogFragment() {
|
|||
feeRadioGroupLabelTextView = view.findViewById(R.id.tx_fee_radiogroup_label_textview)
|
||||
selectedUtxosValueTextView = view.findViewById(R.id.selected_utxos_value_textview)
|
||||
donateTextView = view.findViewById(R.id.donate_label_textview)
|
||||
donatingTextView = view.findViewById(R.id.donating_label_textview)
|
||||
donateTextView?.setOnClickListener {
|
||||
addressEditText?.setText(
|
||||
Constants.DONATE_ADDRESS
|
||||
)
|
||||
}
|
||||
donatingTextView?.setOnClickListener {
|
||||
addressEditText?.setText("")
|
||||
}
|
||||
addressEditText?.addTextChangedListener(object : TextWatcher {
|
||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
||||
override fun afterTextChanged(s: Editable) {
|
||||
if (s.toString() == Constants.DONATE_ADDRESS) {
|
||||
donatingTextView?.visibility = View.VISIBLE
|
||||
donateTextView?.visibility = View.INVISIBLE
|
||||
} else {
|
||||
donatingTextView?.visibility = View.INVISIBLE
|
||||
donateTextView?.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
})
|
||||
if (uriData != null) {
|
||||
addressEditText?.setText(uriData?.address)
|
||||
if (uriData?.hasAmount() == true) {
|
||||
|
|
|
@ -31,6 +31,7 @@ import net.mynero.wallet.model.PendingTransaction
|
|||
import net.mynero.wallet.model.Wallet
|
||||
import net.mynero.wallet.service.BalanceService
|
||||
import net.mynero.wallet.service.TxService
|
||||
import net.mynero.wallet.util.Constants
|
||||
import net.mynero.wallet.util.Helper
|
||||
import net.mynero.wallet.util.UriData
|
||||
|
||||
|
@ -270,19 +271,22 @@ class SendFragment : Fragment() {
|
|||
val removeOutputImageButton =
|
||||
entryView.findViewById<ImageButton>(R.id.remove_output_imagebutton)
|
||||
val addressField = entryView.findViewById<EditText>(R.id.address_edittext)
|
||||
val donateTextView = entryView.findViewById<TextView>(R.id.donate_label)
|
||||
val donatingTextView = entryView.findViewById<TextView>(R.id.donating_label)
|
||||
donateTextView.setOnClickListener {
|
||||
addressField.setText(
|
||||
Constants.DONATE_ADDRESS
|
||||
)
|
||||
}
|
||||
donatingTextView.setOnClickListener {
|
||||
addressField.setText("")
|
||||
}
|
||||
addressField.addTextChangedListener(object : TextWatcher {
|
||||
override fun beforeTextChanged(
|
||||
charSequence: CharSequence,
|
||||
i: Int,
|
||||
i1: Int,
|
||||
i2: Int
|
||||
) {
|
||||
}
|
||||
|
||||
override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
|
||||
override fun afterTextChanged(editable: Editable) {
|
||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
||||
override fun afterTextChanged(s: Editable) {
|
||||
val currentOutputs: Int = destCount
|
||||
val uriData = UriData.parse(editable.toString())
|
||||
val uriData = UriData.parse(s.toString())
|
||||
if (uriData != null) {
|
||||
// we have valid address
|
||||
val hasPaymentId = uriData.hasPaymentId()
|
||||
|
@ -302,6 +306,14 @@ class SendFragment : Fragment() {
|
|||
// when send-all is false and this is our only dest and address is invalid, then show add output button
|
||||
mViewModel?.setShowAddOutputButton(true)
|
||||
}
|
||||
|
||||
if (s.toString() == Constants.DONATE_ADDRESS) {
|
||||
donateTextView.visibility = View.INVISIBLE
|
||||
donatingTextView.visibility = View.VISIBLE
|
||||
} else {
|
||||
donateTextView.visibility = View.VISIBLE
|
||||
donatingTextView.visibility = View.INVISIBLE
|
||||
}
|
||||
}
|
||||
})
|
||||
entryView.findViewById<View>(R.id.paste_amount_imagebutton)
|
||||
|
|
|
@ -47,7 +47,6 @@ class SettingsFragment : Fragment(), PasswordListener, NodeSelectionDialogListen
|
|||
private var selectNodeButton: Button? = null
|
||||
private var streetModeSwitch: SwitchCompat? = null
|
||||
private var monerochanSwitch: SwitchCompat? = null
|
||||
private var donationSwitch: SwitchCompat? = null
|
||||
private var useBundledTor: CheckBox? = null
|
||||
private var displaySeedButton: Button? = null
|
||||
private var displayUtxosButton: Button? = null
|
||||
|
@ -68,7 +67,6 @@ class SettingsFragment : Fragment(), PasswordListener, NodeSelectionDialogListen
|
|||
selectNodeButton = view.findViewById(R.id.select_node_button)
|
||||
streetModeSwitch = view.findViewById(R.id.street_mode_switch)
|
||||
monerochanSwitch = view.findViewById(R.id.monerochan_switch)
|
||||
donationSwitch = view.findViewById(R.id.donate_per_tx_switch)
|
||||
torSwitch = view.findViewById(R.id.tor_switch)
|
||||
val proxySettingsLayout = view.findViewById<ConstraintLayout>(R.id.wallet_proxy_settings_layout)
|
||||
walletProxyAddressEditText = view.findViewById(R.id.wallet_proxy_address_edittext)
|
||||
|
@ -88,8 +86,6 @@ class SettingsFragment : Fragment(), PasswordListener, NodeSelectionDialogListen
|
|||
PrefService.instance?.getBoolean(Constants.PREF_STREET_MODE, false) == true
|
||||
monerochanSwitch?.isChecked =
|
||||
PrefService.instance?.getBoolean(Constants.PREF_MONEROCHAN, Constants.DEFAULT_PREF_MONEROCHAN) == true
|
||||
donationSwitch?.isChecked =
|
||||
PrefService.instance?.getBoolean(Constants.PREF_DONATE_PER_TX, false) == true
|
||||
useBundledTor?.isChecked = cachedUsingBundledTor
|
||||
torSwitch?.isChecked = cachedUsingProxy
|
||||
updateProxy(cachedProxyAddress, cachedProxyPort)
|
||||
|
@ -110,10 +106,6 @@ class SettingsFragment : Fragment(), PasswordListener, NodeSelectionDialogListen
|
|||
}
|
||||
activity?.onBackPressedDispatcher?.addCallback(viewLifecycleOwner, onBackPressedCallback)
|
||||
|
||||
donationSwitch?.setOnCheckedChangeListener { _: CompoundButton?, b: Boolean ->
|
||||
PrefService.instance?.edit()?.putBoolean(Constants.PREF_DONATE_PER_TX, b)?.apply()
|
||||
}
|
||||
|
||||
streetModeSwitch?.setOnCheckedChangeListener { _: CompoundButton?, b: Boolean ->
|
||||
PrefService.instance?.edit()?.putBoolean(Constants.PREF_STREET_MODE, b)?.apply()
|
||||
BalanceService.instance?.refreshBalance()
|
||||
|
|
|
@ -21,12 +21,9 @@ import net.mynero.wallet.model.PendingTransaction
|
|||
import net.mynero.wallet.model.TransactionOutput
|
||||
import net.mynero.wallet.model.Wallet
|
||||
import net.mynero.wallet.model.Wallet.Companion.getAmountFromString
|
||||
import net.mynero.wallet.model.Wallet.Companion.getPaymentIdFromAddress
|
||||
import net.mynero.wallet.model.Wallet.ConnectionStatus
|
||||
import net.mynero.wallet.model.WalletListener
|
||||
import net.mynero.wallet.model.WalletManager
|
||||
import net.mynero.wallet.util.Constants
|
||||
import java.security.SecureRandom
|
||||
|
||||
/**
|
||||
* Handy class for starting a new thread that has a looper. The looper can then be
|
||||
|
@ -158,65 +155,7 @@ class MoneroHandlerThread(name: String, val listener: Listener?, wallet: Wallet)
|
|||
val address = dest.component1()
|
||||
return wallet.createSweepTransaction(address, feePriority, preferredInputs)
|
||||
}
|
||||
val finalOutputs = maybeAddDonationOutputs(totalAmount, outputs, preferredInputs)
|
||||
return wallet.createTransactionMultDest(finalOutputs, feePriority, preferredInputs)
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
private fun maybeAddDonationOutputs(
|
||||
amount: Long,
|
||||
outputs: List<TransactionOutput>,
|
||||
preferredInputs: List<String>
|
||||
): List<TransactionOutput> {
|
||||
val newOutputs = ArrayList(outputs)
|
||||
val networkType = WalletManager.instance?.networkType ?: return newOutputs
|
||||
val mainDestination =
|
||||
outputs[0] // at this point, for now, we should only have one item in the list. TODO: add multi-dest/pay-to-many feature in the UI
|
||||
val paymentId =
|
||||
getPaymentIdFromAddress(mainDestination.destination, networkType.value)
|
||||
val donatePerTx = PrefService.instance?.getBoolean(Constants.PREF_DONATE_PER_TX, false)
|
||||
if (donatePerTx == true && paymentId?.isEmpty() == true) { // only attach donation when no payment id is needed (i.e. integrated address)
|
||||
val rand = SecureRandom()
|
||||
val randomDonatePct = getRandomDonateAmount(
|
||||
0.005f,
|
||||
0.03f
|
||||
) // occasionally attaches a 0.5% to 3% donation. It is random so that not even I know how much exactly you are sending.
|
||||
/*
|
||||
It's also not entirely "per tx". It won't always attach it so as to not have a consistently uncommon fingerprint on-chain. When it does attach a donation,
|
||||
it will periodically split it up into multiple outputs instead of one.
|
||||
*/
|
||||
val attachDonationRoll = rand.nextInt(100)
|
||||
if (attachDonationRoll > 90) { // 10% chance of being added
|
||||
val splitDonationRoll = rand.nextInt(100)
|
||||
val donateAmount = (amount * randomDonatePct).toLong()
|
||||
if (splitDonationRoll > 50) { // 50% chance of being split
|
||||
// split
|
||||
val split = genRandomDonationSplit(
|
||||
1,
|
||||
4
|
||||
) // splits into at most 4 outputs, for a total of 6 outputs in the transaction (real dest + change. we don't add donations to send-all/sweep transactions)
|
||||
val splitAmount = donateAmount / split
|
||||
for (i in 0 until split) {
|
||||
// TODO this can be expanded upon into the future to perform an auto-splitting/auto-churning for the user if their wallet is fresh and has few utxos.
|
||||
// randomly split between multiple wallets
|
||||
val randomDonationAddress = rand.nextInt(Constants.DONATION_ADDRESSES.size)
|
||||
val donationAddress = Constants.DONATION_ADDRESSES[randomDonationAddress]
|
||||
newOutputs.add(TransactionOutput(donationAddress, splitAmount))
|
||||
}
|
||||
} else {
|
||||
// just add one output, for a total of 3 (real dest + change)
|
||||
newOutputs.add(TransactionOutput(Constants.DONATE_ADDRESS, donateAmount))
|
||||
}
|
||||
val total = amount + donateAmount
|
||||
checkSelectedAmounts(
|
||||
preferredInputs,
|
||||
total,
|
||||
false
|
||||
) // check that the selected UTXOs satisfy the new amount total
|
||||
}
|
||||
}
|
||||
newOutputs.shuffle() // shuffle the outputs just in case. i think the monero library handles this for us anyway
|
||||
return newOutputs
|
||||
return wallet.createTransactionMultDest(outputs, feePriority, preferredInputs)
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
|
@ -240,16 +179,6 @@ class MoneroHandlerThread(name: String, val listener: Listener?, wallet: Wallet)
|
|||
return pendingTx.commit("", true)
|
||||
}
|
||||
|
||||
private fun getRandomDonateAmount(min: Float, max: Float): Float {
|
||||
val rand = SecureRandom()
|
||||
return rand.nextFloat() * (max - min) + min
|
||||
}
|
||||
|
||||
private fun genRandomDonationSplit(min: Int, max: Int): Int {
|
||||
val rand = SecureRandom()
|
||||
return rand.nextInt(max) + min
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
fun onRefresh(walletSynced: Boolean)
|
||||
fun onConnectionFail()
|
||||
|
|
|
@ -126,7 +126,7 @@ class UTXOService(thread: MoneroHandlerThread?) : ServiceBase(thread) {
|
|||
val destinations = ArrayList<Pair<String, Long>>()
|
||||
destinations.add(
|
||||
Pair(
|
||||
"87MRtZPrWUCVUgcFHdsVb5MoZUcLtqfD3FvQVGwftFb8eSdMnE39JhAJcbuSW8X2vRaRsB9RQfuCpFciybJFHaz3QYPhCLw",
|
||||
Constants.DONATE_ADDRESS,
|
||||
amount
|
||||
)
|
||||
)
|
||||
|
|
|
@ -11,7 +11,6 @@ object Constants {
|
|||
const val PREF_USES_OFFSET = "pref_uses_offset"
|
||||
const val PREF_STREET_MODE = "pref_street_mode"
|
||||
const val PREF_MONEROCHAN = "pref_monerochan"
|
||||
const val PREF_DONATE_PER_TX = "pref_donate_per_tx"
|
||||
const val PREF_FROZEN_COINS = "pref_frozen_coins"
|
||||
const val PREF_USE_BUNDLED_TOR = "pref_use_bundled_tor"
|
||||
|
||||
|
@ -23,11 +22,7 @@ object Constants {
|
|||
|
||||
const val DEFAULT_PREF_MONEROCHAN = false
|
||||
|
||||
val DONATION_ADDRESSES = arrayOf(
|
||||
"87BqQYkugEzh6Tuyotm2uc3DzJzKM6MuZaC161e6u1TsQxxPmXVPHpdNRyK47JY4d1hhbe25YVz4e9vTXCLDxvHkRXEAeBC", // primary Mysu Donation address
|
||||
"89QoPxs4cQSGbJrJddwzV3Ca7s2gVYHE1Xd1hGZafuVJVyNKt2LCQhxUdBF57PemxQiX3dmGUZLRRAzfeYyh9pq3GiWsDVo", // second Mysu Donation address
|
||||
"855acibBehTQJdC1f41BHWGq1FiQ5ztiAU7LiJgDUmmyJfDtRpJoo6Mc1en73duUScdeUYjLirACnZpv2C6pPbcZKgumdCS" // third Mysu Donation address
|
||||
)
|
||||
// Donation address is also specified in strings.xml, it is used as a tooltip in address fields
|
||||
const val DONATE_ADDRESS =
|
||||
"87BqQYkugEzh6Tuyotm2uc3DzJzKM6MuZaC161e6u1TsQxxPmXVPHpdNRyK47JY4d1hhbe25YVz4e9vTXCLDxvHkRXEAeBC"
|
||||
}
|
|
@ -87,68 +87,20 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/display_seed_button" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/transaction_settings_textview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginTop="32dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:text="@string/transactions"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/display_utxos_button" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/donate_per_tx_label_textview"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="24dp"
|
||||
android:text="@string/option_donate_per_tx"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/donate_per_tx_switch"
|
||||
app:layout_constraintEnd_toStartOf="@id/donate_per_tx_switch"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/donate_per_tx_switch" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/donate_per_tx_desc_textview"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:text="@string/option_donate_per_tx_desc"
|
||||
android:textColor="@color/oled_addressListColor"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/donate_per_tx_switch" />
|
||||
|
||||
<androidx.appcompat.widget.SwitchCompat
|
||||
android:id="@+id/donate_per_tx_switch"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:minWidth="48dp"
|
||||
android:minHeight="48dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/transaction_settings_textview" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/appearance_settings_textview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginTop="32dp"
|
||||
android:layout_marginTop="24dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:text="@string/appearance"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="1.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/donate_per_tx_desc_textview" />
|
||||
app:layout_constraintTop_toBottomOf="@+id/display_utxos_button" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/street_mode_label_textview"
|
||||
|
|
|
@ -69,6 +69,22 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/address_edittext" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/donating_label_textview"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:text="@string/donating_label"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toTopOf="@id/amount_edittext"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/address_edittext"
|
||||
app:layout_constraintVertical_bias="1.0"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/paste_address_imagebutton"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
@ -5,6 +5,37 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/donate_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="48dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:text="@string/donate_label"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintBottom_toTopOf="@id/amount_edittext"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/address_edittext"
|
||||
app:layout_constraintVertical_bias="0.0" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/donating_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="48dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:text="@string/donating_label"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toTopOf="@id/amount_edittext"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/address_edittext"
|
||||
app:layout_constraintVertical_bias="0.0"
|
||||
tools:visibility="invisible" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/amount_edittext"
|
||||
android:layout_width="0dp"
|
||||
|
|
|
@ -35,12 +35,10 @@
|
|||
<string name="copied_to_clipboard">Copied to clipboard</string>
|
||||
<string name="street_mode">Street mode (hide balances)</string>
|
||||
<string name="option_hide_xmrchan">Show Monerochan</string>
|
||||
<string name="option_donate_per_tx">Add occasional donation</string>
|
||||
<string name="option_donate_per_tx_desc" formatted="false">When enabled, there is a 10% chance when sending coins to add a 0.5%-3% donation to Mysu. These transaction fingerprints and donation amounts are randomized to preserve anonymity and privacy.</string>
|
||||
<string name="display_recovery_phrase">Display wallet keys</string>
|
||||
<string name="tor_switch_label">SOCKS Proxy</string>
|
||||
<string name="connection_failed">Failed to connect. Retrying…</string>
|
||||
<string name="address">87MRtZPrWUCVUgcFHdsVb5MoZUcLtqfD3FvQVGwftFb8eSdMnE39JhAJcbuSW8X2vRaRsB9RQfuCpFciybJFHaz3QYPhCLw</string>
|
||||
<string name="address">87BqQYkugEzh6Tuyotm2uc3DzJzKM6MuZaC161e6u1TsQxxPmXVPHpdNRyK47JY4d1hhbe25YVz4e9vTXCLDxvHkRXEAeBC</string>
|
||||
<string name="amount">0.00</string>
|
||||
<string name="sending_all">SENDING ALL</string>
|
||||
<string name="send">Send</string>
|
||||
|
@ -131,6 +129,7 @@
|
|||
<string name="subbaddress_info_subtitle" translatable="false">#%1$d: %2$s</string>
|
||||
<string name="previous_addresses">Previous addresses</string>
|
||||
<string name="donate_label">Donate to Mysu</string>
|
||||
<string name="donating_label">Donating to Mysu. Thank you!</string>
|
||||
<string name="transactions">Transactions</string>
|
||||
<string name="auth">[ auth ]</string>
|
||||
<string name="trusted">[ trusted ]</string>
|
||||
|
|
Loading…
Reference in a new issue