diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/TransactionExtrasReducer.kt b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/TransactionExtrasReducer.kt index 4215143301..71000abec1 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/TransactionExtrasReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/TransactionExtrasReducer.kt @@ -3,8 +3,19 @@ package com.tangem.tap.features.send.redux.reducers import com.tangem.blockchain.blockchains.stellar.StellarMemo import com.tangem.blockchain.common.Blockchain import com.tangem.tap.features.send.redux.SendScreenAction -import com.tangem.tap.features.send.redux.TransactionExtrasAction.* -import com.tangem.tap.features.send.redux.states.* +import com.tangem.tap.features.send.redux.TransactionExtrasAction.BinanceMemo +import com.tangem.tap.features.send.redux.TransactionExtrasAction.Prepare +import com.tangem.tap.features.send.redux.TransactionExtrasAction.Release +import com.tangem.tap.features.send.redux.TransactionExtrasAction.XlmMemo +import com.tangem.tap.features.send.redux.TransactionExtrasAction.XrpDestinationTag +import com.tangem.tap.features.send.redux.states.BinanceMemoState +import com.tangem.tap.features.send.redux.states.InputViewValue +import com.tangem.tap.features.send.redux.states.SendState +import com.tangem.tap.features.send.redux.states.TransactionExtraError +import com.tangem.tap.features.send.redux.states.TransactionExtrasState +import com.tangem.tap.features.send.redux.states.XlmMemoState +import com.tangem.tap.features.send.redux.states.XlmMemoType +import com.tangem.tap.features.send.redux.states.XrpDestinationTagState /** [REDACTED_AUTHOR] @@ -53,42 +64,33 @@ class TransactionExtrasReducer : SendInternalReducer { } private fun handleXlmMemo( - action: XlmMemo, - sendState: SendState, - infoState: TransactionExtrasState, + action: XlmMemo, + sendState: SendState, + infoState: TransactionExtrasState, ): SendState { fun clearMemo(memo: XlmMemoState): XlmMemoState = memo.copy(text = null, id = null, error = null) val result = when (action) { -// is XlmMemo.ChangeSelectedMemo -> { -// val inputViewValue = InputViewValue("", false) -// val memo = infoState.xlmMemo?.copy( -// viewFieldValue = inputViewValue, -// selectedMemoType = action.memoType, -// ) ?: XlmMemoState(inputViewValue, action.memoType) -// -// infoState.copy(xlmMemo = clearMemo(memo)) -// } is XlmMemo.HandleUserInput -> { val inputViewValue = InputViewValue(action.data, true) var memo = infoState.xlmMemo?.copy(viewFieldValue = inputViewValue) - ?: XlmMemoState(inputViewValue) + ?: XlmMemoState(inputViewValue) memo = clearMemo(memo) - memo = when (infoState.xlmMemo?.selectedMemoType) { - XlmMemoType.TEXT -> memo.copy(text = StellarMemo.Text(action.data)) - XlmMemoType.ID -> { - val id = action.data.toBigIntegerOrNull() - if (id != null) { - if (id > XlmMemoState.MAX_NUMBER) { - memo.copy(error = TransactionExtraError.INVALID_XLM_MEMO) - } else { - memo.copy(id = StellarMemo.Id(id)) - } + memo = when (memo.selectedMemoType) { + XlmMemoType.TEXT -> { + if (XlmMemoState.isAssignableValue(action.data)) { + memo.copy(text = StellarMemo.Text(action.data)) } else { - memo + memo.copy(error = TransactionExtraError.INVALID_XLM_MEMO) + } + } + XlmMemoType.ID -> { + if (XlmMemoState.isAssignableValue(action.data)) { + memo.copy(id = StellarMemo.Id(action.data.toBigInteger())) + } else { + memo.copy(error = TransactionExtraError.INVALID_XLM_MEMO) } } - null -> memo } infoState.copy(xlmMemo = memo) } @@ -117,16 +119,16 @@ class TransactionExtrasReducer : SendInternalReducer { } private fun handleXrpTag( - action: XrpDestinationTag, - sendState: SendState, - infoState: TransactionExtrasState, + action: XrpDestinationTag, + sendState: SendState, + infoState: TransactionExtrasState, ): SendState { val result = when (action) { is XrpDestinationTag.HandleUserInput -> { val tag = action.data.toLongOrNull() if (tag != null) { val input = InputViewValue(action.data, true) - val tagState = if (tag <= XrpDestinationTagState.MAX_NUMBER){ + val tagState = if (tag <= XrpDestinationTagState.MAX_NUMBER) { XrpDestinationTagState(input, tag) } else { XrpDestinationTagState(input, error = TransactionExtraError.INVALID_DESTINATION_TAG) diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/states/AddressPayIdState.kt b/app/src/main/java/com/tangem/tap/features/send/redux/states/AddressPayIdState.kt index e4f816c106..30fe37f60a 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/states/AddressPayIdState.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/states/AddressPayIdState.kt @@ -1,19 +1,20 @@ package com.tangem.tap.features.send.redux.states +import androidx.core.text.isDigitsOnly import com.tangem.blockchain.blockchains.stellar.StellarMemo import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction import java.math.BigInteger data class AddressPayIdState( - val viewFieldValue: InputViewValue = InputViewValue(""), - val normalFieldValue: String? = null, - val truncatedFieldValue: String? = null, - val destinationWalletAddress: String? = null, - val error: AddressPayIdVerifyAction.Error? = null, - val truncateHandler: ((String) -> String)? = null, - val sendingToPayIdEnabled: Boolean = false, - val pasteIsEnabled: Boolean = false, - val inputIsEnabled: Boolean = true + val viewFieldValue: InputViewValue = InputViewValue(""), + val normalFieldValue: String? = null, + val truncatedFieldValue: String? = null, + val destinationWalletAddress: String? = null, + val error: AddressPayIdVerifyAction.Error? = null, + val truncateHandler: ((String) -> String)? = null, + val sendingToPayIdEnabled: Boolean = false, + val pasteIsEnabled: Boolean = false, + val inputIsEnabled: Boolean = true, ) : SendScreenState { override val stateId: StateId = StateId.ADDRESS_PAY_ID @@ -26,9 +27,9 @@ data class AddressPayIdState( } data class TransactionExtrasState( - val xlmMemo: XlmMemoState? = null, - val binanceMemo: BinanceMemoState? = null, - val xrpDestinationTag: XrpDestinationTagState? = null + val xlmMemo: XlmMemoState? = null, + val binanceMemo: BinanceMemoState? = null, + val xrpDestinationTag: XrpDestinationTagState? = null, ) : IdStateHolder { override val stateId: StateId = StateId.TRANSACTION_EXTRAS } @@ -38,11 +39,10 @@ enum class XlmMemoType { } data class XlmMemoState( - val viewFieldValue: InputViewValue = InputViewValue(""), - val selectedMemoType: XlmMemoType = XlmMemoType.ID, - val text: StellarMemo.Text? = null, - val id: StellarMemo.Id? = null, - val error: TransactionExtraError? = null, + val viewFieldValue: InputViewValue = InputViewValue(""), + val text: StellarMemo.Text? = null, + val id: StellarMemo.Id? = null, + val error: TransactionExtraError? = null, ) { val memo: StellarMemo? get() = when (selectedMemoType) { @@ -50,16 +50,37 @@ data class XlmMemoState( XlmMemoType.ID -> id } + val selectedMemoType: XlmMemoType + get() = determineMemoType(viewFieldValue.value) + companion object { - val MAX_NUMBER: BigInteger = BigInteger("FFFFFFFFFFFFFFFF", 16) + fun determineMemoType(value: String): XlmMemoType = when { + value.isNotEmpty() && value.isDigitsOnly() -> XlmMemoType.ID + else -> XlmMemoType.TEXT + } + + fun isAssignableValue(value: String): Boolean = when (determineMemoType(value)) { + XlmMemoType.TEXT -> { + // from org.stellar.sdk.MemoText + value.toByteArray().size <= 28 + } + XlmMemoType.ID -> { + try { + // from com.tangem.blockchain.blockchains.stellar.StellarMemo.toStellarSdkMemo + value.toBigInteger() in BigInteger.ZERO..(Long.MAX_VALUE.toBigInteger() * 2.toBigInteger()) + } catch (ex: NumberFormatException) { + false + } + } + } } } data class BinanceMemoState( val viewFieldValue: InputViewValue = InputViewValue(""), val memo: BigInteger? = null, - val error: TransactionExtraError? = null - ) { + val error: TransactionExtraError? = null, +) { companion object { val MAX_NUMBER: BigInteger = BigInteger("FFFFFFFFFFFFFFFF", 16) } @@ -67,9 +88,9 @@ data class BinanceMemoState( // tag must contains only digits data class XrpDestinationTagState( - val viewFieldValue: InputViewValue = InputViewValue(""), - val tag: Long? = null, - val error: TransactionExtraError? = null + val viewFieldValue: InputViewValue = InputViewValue(""), + val tag: Long? = null, + val error: TransactionExtraError? = null, ) { companion object { const val MAX_NUMBER: Long = 4294967295 diff --git a/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt b/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt index 96624950c0..31fa218cfd 100644 --- a/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt +++ b/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt @@ -2,7 +2,6 @@ package com.tangem.tap.features.send.ui.stateSubscribers import android.app.Dialog import android.content.Context -import android.text.InputType import android.text.SpannableStringBuilder import android.view.View import android.view.ViewGroup @@ -31,7 +30,6 @@ import com.tangem.tap.features.send.redux.states.SendState import com.tangem.tap.features.send.redux.states.StateId import com.tangem.tap.features.send.redux.states.TransactionExtraError import com.tangem.tap.features.send.redux.states.TransactionExtrasState -import com.tangem.tap.features.send.redux.states.XlmMemoType import com.tangem.tap.features.send.ui.FeeUiHelper import com.tangem.tap.features.send.ui.SendFragment import com.tangem.tap.features.send.ui.dialogs.RequestFeeErrorDialog @@ -80,14 +78,10 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : showView(binanceMemoContainer, infoState.binanceMemo) infoState.xlmMemo?.let { - etXlmMemo.inputType = when (it.selectedMemoType) { - XlmMemoType.TEXT -> InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS - XlmMemoType.ID -> InputType.TYPE_CLASS_NUMBER - } if (!it.viewFieldValue.isFromUserInput) etXlmMemo.setText(it.viewFieldValue.value) if (it.error != null) { if (it.error == TransactionExtraError.INVALID_XLM_MEMO) { - tilXlmMemo.error = fg.getText(R.string.send_error_invalid_memo_id) + tilXlmMemo.error = fg.getText(R.string.send_error_invalid_memo) } } else { tilXlmMemo.error = null @@ -109,7 +103,7 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : infoState.binanceMemo?.let { if (infoState.binanceMemo.error != null) { if (infoState.binanceMemo.error == TransactionExtraError.INVALID_BINANCE_MEMO) { - tilBinanceMemo.error = fg.getText(R.string.send_error_invalid_memo_id) + tilBinanceMemo.error = fg.getText(R.string.send_error_invalid_memo) } } else { tilBinanceMemo.error = null diff --git a/app/src/main/res/layout/layout_send_address_payid.xml b/app/src/main/res/layout/layout_send_address_payid.xml index 232b778f22..b16e59b974 100644 --- a/app/src/main/res/layout/layout_send_address_payid.xml +++ b/app/src/main/res/layout/layout_send_address_payid.xml @@ -153,6 +153,7 @@ android:layout_height="wrap_content" android:background="@color/backgroundLightGray" android:ellipsize="middle" + android:inputType="text|textNoSuggestions" android:paddingStart="0dp" android:paddingEnd="0dp" android:singleLine="true" diff --git a/app/src/main/res/values-de/strings_final.xml b/app/src/main/res/values-de/strings_final.xml index 4243136291..7e585b36f2 100644 --- a/app/src/main/res/values-de/strings_final.xml +++ b/app/src/main/res/values-de/strings_final.xml @@ -86,5 +86,9 @@ Reset to Factory Settings Factory Reset will completely delete the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. Select network + Memo + Tag + Invalid Memo. It won\'t be added to the transaction + Invalid Tag. It won\'t be added to the transaction %s network has a concept of Existential Deposit. If your account drops below %s %s it will be deactivated and any remaining funds will be destroyed. \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings_final.xml b/app/src/main/res/values-fr/strings_final.xml index 6e840c3e83..5d8b24ed0f 100644 --- a/app/src/main/res/values-fr/strings_final.xml +++ b/app/src/main/res/values-fr/strings_final.xml @@ -86,5 +86,9 @@ Reset to Factory Settings Factory Reset will completely delete the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. Select network + Memo + Tag + Invalid Memo. It won\'t be added to the transaction + Invalid Tag. It won\'t be added to the transaction %s network has a concept of Existential Deposit. If your account drops below %s %s it will be deactivated and any remaining funds will be destroyed. \ No newline at end of file diff --git a/app/src/main/res/values-it/strings_final.xml b/app/src/main/res/values-it/strings_final.xml index 6e840c3e83..5d8b24ed0f 100644 --- a/app/src/main/res/values-it/strings_final.xml +++ b/app/src/main/res/values-it/strings_final.xml @@ -86,5 +86,9 @@ Reset to Factory Settings Factory Reset will completely delete the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. Select network + Memo + Tag + Invalid Memo. It won\'t be added to the transaction + Invalid Tag. It won\'t be added to the transaction %s network has a concept of Existential Deposit. If your account drops below %s %s it will be deactivated and any remaining funds will be destroyed. \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index c0059a0e36..9c7aef46d4 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -147,10 +147,6 @@ Добавить Удалить Поиск - Памятка - Тег назначения - Недопустимый тег назначения. Он не будет добавлен в транзакцию. - Недопустимый идентификатор памятки. Он не будет добавлен в транзакцию. Приложение Отправить отзыв Успешно отправлено diff --git a/app/src/main/res/values-ru/strings_final.xml b/app/src/main/res/values-ru/strings_final.xml index 0f2737c2bb..4bc89187dc 100644 --- a/app/src/main/res/values-ru/strings_final.xml +++ b/app/src/main/res/values-ru/strings_final.xml @@ -97,5 +97,9 @@ Сброс к заводским настройкам Сброс к заводским настройкам приведет к полному удалению кошелька с выбранной карты. Вы не сможете восстановить текущий кошелек или использовать эту карту для восстановления кода доступа. Выберите сеть + Memo + Tag + Недопустимый Memo. Он не будет добавлен в транзакцию. + Недопустимый Tag. Он не будет добавлен в транзакцию. Сеть %s использует концепцию экзистенциального депозита. Если баланс вашего счета опустится ниже %s %s, он будет деактивирован, а все оставшиеся средства будут уничтожены. diff --git a/app/src/main/res/values/strings_final.xml b/app/src/main/res/values/strings_final.xml index c3c6f58fe1..fa691840a2 100644 --- a/app/src/main/res/values/strings_final.xml +++ b/app/src/main/res/values/strings_final.xml @@ -99,5 +99,9 @@ Reset to Factory Settings Factory Reset will completely delete the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. Select network + Memo + Tag + Invalid Memo. It won\'t be added to the transaction + Invalid Tag. It won\'t be added to the transaction %s network has a concept of Existential Deposit. If your account drops below %s %s it will be deactivated and any remaining funds will be destroyed. diff --git a/app/src/main/res/values/strings_untranslated.xml b/app/src/main/res/values/strings_untranslated.xml index 55c6923133..cc9e1a3cf3 100644 --- a/app/src/main/res/values/strings_untranslated.xml +++ b/app/src/main/res/values/strings_untranslated.xml @@ -40,12 +40,6 @@ Remove Search - - Memo - Destination tag - Invalid destination tag. It won\'t be added to the transaction - Invalid Memo ID. It won\'t be added to the transaction - App Send feedback Sent successfully