Updated on 2026-08-14
This commit is contained in:
parent
21961aaa74
commit
84022714e7
3 changed files with 133 additions and 41 deletions
|
|
@ -2,6 +2,7 @@ package com.tangem.tap.features.send.redux.middlewares
|
|||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.Wallet
|
||||
import com.tangem.blockchain.common.WalletManager
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Token.Send.AddressEntered
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
|
|
@ -9,6 +10,8 @@ import com.tangem.tap.features.send.redux.*
|
|||
import com.tangem.tap.features.send.redux.AddressVerifyAction.AddressVerification.SetAddressError
|
||||
import com.tangem.tap.features.send.redux.AddressVerifyAction.AddressVerification.SetWalletAddress
|
||||
import com.tangem.tap.features.send.redux.AddressVerifyAction.Error
|
||||
import com.tangem.tap.scope
|
||||
import kotlinx.coroutines.*
|
||||
import org.rekotlin.Action
|
||||
import org.rekotlin.DispatchFunction
|
||||
|
||||
|
|
@ -17,6 +20,8 @@ import org.rekotlin.DispatchFunction
|
|||
*/
|
||||
internal class AddressMiddleware {
|
||||
|
||||
val addressValidator = AddressValidator()
|
||||
|
||||
fun handle(action: AddressActionUi, appState: AppState?, dispatch: (Action) -> Unit) {
|
||||
when (action) {
|
||||
is AddressActionUi.HandleUserInput -> handleUserInput(action.data, appState, dispatch)
|
||||
|
|
@ -54,13 +59,13 @@ internal class AddressMiddleware {
|
|||
dispatch: (Action) -> Unit,
|
||||
) {
|
||||
val sendState = appState?.sendState ?: return
|
||||
val wallet = sendState.walletManager?.wallet ?: return
|
||||
val walletManager = sendState.walletManager ?: return
|
||||
val address = sendState.addressState.normalFieldValue ?: return
|
||||
val isUserInput = sendState.addressState.viewFieldValue.isFromUserInput
|
||||
|
||||
verifyAddress(
|
||||
address = address,
|
||||
wallet = wallet,
|
||||
walletManager = walletManager,
|
||||
isUserInput = isUserInput,
|
||||
dispatch = dispatch,
|
||||
sourceType = sourceType,
|
||||
|
|
@ -68,6 +73,38 @@ internal class AddressMiddleware {
|
|||
}
|
||||
|
||||
private fun verifyAddress(
|
||||
address: String,
|
||||
walletManager: WalletManager,
|
||||
sourceType: AddressEntered.SourceType?,
|
||||
isUserInput: Boolean,
|
||||
dispatch: (Action) -> Unit,
|
||||
) {
|
||||
val wallet = walletManager.wallet
|
||||
|
||||
scope.launch(Dispatchers.Main) {
|
||||
val failReason = withContext(Dispatchers.IO) {
|
||||
addressValidator.validateAddress(walletManager, address)
|
||||
}
|
||||
|
||||
if (failReason == null) {
|
||||
dispatchSuccessValidationActions(
|
||||
address = address,
|
||||
wallet = wallet,
|
||||
sourceType = sourceType,
|
||||
isUserInput = isUserInput,
|
||||
dispatch = dispatch,
|
||||
)
|
||||
} else {
|
||||
dispatchFailedValidationActions(
|
||||
failReason = failReason,
|
||||
sourceType = sourceType,
|
||||
dispatch = dispatch,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun dispatchSuccessValidationActions(
|
||||
address: String,
|
||||
wallet: Wallet,
|
||||
sourceType: AddressEntered.SourceType?,
|
||||
|
|
@ -113,57 +150,49 @@ internal class AddressMiddleware {
|
|||
|
||||
val supposedAddress = noSchemeAddress.removeShareUriQuery() // TODO: parse query?
|
||||
|
||||
val failReason = isValidBlockchainAddressAndNotTheSameAsWallet(wallet, supposedAddress)
|
||||
if (failReason == null) {
|
||||
noSchemeAddress.getQueryParameter("amount")?.toBigDecimalOrNull()?.let {
|
||||
dispatch(AmountAction.SetAmount(it, false))
|
||||
dispatch(AmountActionUi.CheckAmountToSend)
|
||||
}
|
||||
dispatch(SetWalletAddress(supposedAddress, isUserInput))
|
||||
dispatch(TransactionExtrasAction.Prepare(wallet.blockchain, address, null))
|
||||
dispatch(FeeAction.RequestFee)
|
||||
sourceType?.let {
|
||||
Analytics.send(
|
||||
event = AddressEntered(
|
||||
sourceType = sourceType,
|
||||
validationResult = AddressEntered.ValidationResult.Success,
|
||||
),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
dispatch(SetAddressError(failReason))
|
||||
dispatch(TransactionExtrasAction.Release)
|
||||
sourceType?.let {
|
||||
Analytics.send(
|
||||
event = AddressEntered(
|
||||
sourceType = sourceType,
|
||||
validationResult = AddressEntered.ValidationResult.Fail,
|
||||
),
|
||||
)
|
||||
}
|
||||
noSchemeAddress.getQueryParameter("amount")?.toBigDecimalOrNull()?.let {
|
||||
dispatch(AmountAction.SetAmount(it, false))
|
||||
dispatch(AmountActionUi.CheckAmountToSend)
|
||||
}
|
||||
dispatch(SetWalletAddress(supposedAddress, isUserInput))
|
||||
dispatch(TransactionExtrasAction.Prepare(wallet.blockchain, address, null))
|
||||
dispatch(FeeAction.RequestFee)
|
||||
sourceType?.let {
|
||||
Analytics.send(
|
||||
event = AddressEntered(
|
||||
sourceType = sourceType,
|
||||
validationResult = AddressEntered.ValidationResult.Success,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isValidBlockchainAddressAndNotTheSameAsWallet(wallet: Wallet, address: String): Error? {
|
||||
return if (wallet.blockchain.validateAddress(address)) {
|
||||
if (wallet.addresses.all { it.value != address }) {
|
||||
null
|
||||
} else {
|
||||
Error.ADDRESS_SAME_AS_WALLET
|
||||
}
|
||||
} else {
|
||||
Error.ADDRESS_INVALID_OR_UNSUPPORTED_BY_BLOCKCHAIN
|
||||
private fun dispatchFailedValidationActions(
|
||||
failReason: AddressVerifyAction.Error,
|
||||
sourceType: AddressEntered.SourceType?,
|
||||
dispatch: (Action) -> Unit,
|
||||
) {
|
||||
dispatch(SetAddressError(failReason))
|
||||
dispatch(TransactionExtrasAction.Release)
|
||||
sourceType?.let {
|
||||
Analytics.send(
|
||||
event = AddressEntered(
|
||||
sourceType = sourceType,
|
||||
validationResult = AddressEntered.ValidationResult.Fail,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun String.removeShareUriQuery(): String = this.substringBefore("?")
|
||||
|
||||
private fun String.getQueryParameter(name: String): String? {
|
||||
return this.substringAfter("?").splitToMap("&", "=")[name]
|
||||
}
|
||||
|
||||
private fun verifyClipboard(input: String?, appState: AppState?, dispatch: DispatchFunction) {
|
||||
val address = input ?: return
|
||||
val wallet = appState?.sendState?.walletManager?.wallet ?: return
|
||||
val walletManager = appState?.sendState?.walletManager ?: return
|
||||
|
||||
val internalDispatcher: (Action) -> Unit = {
|
||||
when (it) {
|
||||
|
|
@ -178,7 +207,7 @@ internal class AddressMiddleware {
|
|||
|
||||
verifyAddress(
|
||||
address = address,
|
||||
wallet = wallet,
|
||||
walletManager = walletManager,
|
||||
sourceType = null,
|
||||
isUserInput = false,
|
||||
dispatch = internalDispatcher,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
package com.tangem.tap.features.send.redux.middlewares
|
||||
|
||||
import com.tangem.blockchain.blockchains.near.NearWalletManager
|
||||
import com.tangem.blockchain.blockchains.near.network.NearAccount
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.Wallet
|
||||
import com.tangem.blockchain.common.WalletManager
|
||||
import com.tangem.blockchain.extensions.Result
|
||||
import com.tangem.tap.features.send.redux.AddressVerifyAction
|
||||
|
||||
class AddressValidator {
|
||||
|
||||
suspend fun validateAddress(walletManager: WalletManager, address: String): AddressVerifyAction.Error? {
|
||||
val blockchain = walletManager.wallet.blockchain
|
||||
val wallet = walletManager.wallet
|
||||
return if ((blockchain == Blockchain.Near || blockchain == Blockchain.NearTestnet) &&
|
||||
address.length != NEAR_IMPLICIT_ADDRESS_LENGTH
|
||||
) {
|
||||
validateNearAddress(walletManager, address)
|
||||
} else {
|
||||
validateAddress(wallet, address)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun validateNearAddress(
|
||||
walletManager: WalletManager,
|
||||
address: String,
|
||||
): AddressVerifyAction.Error? {
|
||||
val result = (walletManager as? NearWalletManager)?.getAccount(address)
|
||||
return if (result is Result.Success && result.data is NearAccount.Full) {
|
||||
null
|
||||
} else {
|
||||
AddressVerifyAction.Error.ADDRESS_INVALID_OR_UNSUPPORTED_BY_BLOCKCHAIN
|
||||
}
|
||||
}
|
||||
|
||||
private fun validateAddress(wallet: Wallet, address: String): AddressVerifyAction.Error? {
|
||||
return if (wallet.blockchain.validateAddress(address)) {
|
||||
if (wallet.addresses.all { it.value != address }) {
|
||||
null
|
||||
} else {
|
||||
AddressVerifyAction.Error.ADDRESS_SAME_AS_WALLET
|
||||
}
|
||||
} else {
|
||||
AddressVerifyAction.Error.ADDRESS_INVALID_OR_UNSUPPORTED_BY_BLOCKCHAIN
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val NEAR_IMPLICIT_ADDRESS_LENGTH = 64
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue