diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WcSessionRequestConverter.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WcSessionRequestConverter.kt index 16eaf90e60..90de1f8b12 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WcSessionRequestConverter.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect2/domain/WcSessionRequestConverter.kt @@ -1,5 +1,6 @@ package com.tangem.tap.domain.walletconnect2.domain +import com.tangem.blockchain.blockchains.solana.SolanaTransactionHelper import com.tangem.domain.walletconnect.model.legacy.WalletConnectSessionsRepository import com.tangem.tap.domain.walletconnect.WalletConnectSdkHelper import com.tangem.tap.domain.walletconnect2.domain.models.BnbData @@ -150,10 +151,8 @@ internal class WcSessionRequestConverter( * Input transaction in Base64 string */ private fun String.prepareSolanaTransaction(): ByteArray { - return this.decodeBase64() - ?.toByteArray() - ?.drop(SOLANA_SIGNATURE_PLACEHOLDER_LENGTH) - ?.toByteArray() ?: ByteArray(0) + val transaction = this.decodeBase64()?.toByteArray() ?: ByteArray(0) + return SolanaTransactionHelper.removeSignaturesPlaceholders(transaction) } private fun getWalletAddress(request: WcRequest): String? { @@ -182,8 +181,4 @@ internal class WcSessionRequestConverter( (walletAddress == null || it.walletAddress.lowercase() == walletAddress.lowercase()) }?.derivationPath } - - companion object { - private const val SOLANA_SIGNATURE_PLACEHOLDER_LENGTH = 65 - } } \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/utils/RequestPushPermission.kt b/core/ui/src/main/java/com/tangem/core/ui/utils/RequestPushPermission.kt index f70452b5f7..4f6cc6d0df 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/utils/RequestPushPermission.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/utils/RequestPushPermission.kt @@ -1,9 +1,7 @@ package com.tangem.core.ui.utils import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import com.google.accompanist.permissions.ExperimentalPermissionsApi -import com.google.accompanist.permissions.isGranted import com.google.accompanist.permissions.rememberPermissionState /** @@ -13,24 +11,18 @@ import com.google.accompanist.permissions.rememberPermissionState @Suppress("LongParameterList") @OptIn(ExperimentalPermissionsApi::class) @Composable -fun requestPushPermission( - pushPermission: String?, - isClicked: Boolean, - onAllow: () -> Unit, - onDeny: () -> Unit, -): () -> Unit { +fun requestPushPermission(pushPermission: String?, onAllow: () -> Unit, onDeny: () -> Unit): () -> Unit { val permissionState = pushPermission?.let { permission -> - rememberPermissionState(permission = permission) - } - - // Check if user granted permission and close bottom sheet - LaunchedEffect(key1 = permissionState?.status, isClicked) { - if (!isClicked) return@LaunchedEffect - if (permissionState?.status?.isGranted == true) { - onAllow() - } else { - onDeny() - } + rememberPermissionState( + permission = permission, + onPermissionResult = { isGranted -> + if (isGranted) { + onAllow() + } else { + onDeny() + } + }, + ) } return if (permissionState == null) { diff --git a/domain/demo/src/main/java/com/tangem/domain/demo/DemoTransactionSender.kt b/domain/demo/src/main/java/com/tangem/domain/demo/DemoTransactionSender.kt index 81a09ca897..5c667f1f53 100644 --- a/domain/demo/src/main/java/com/tangem/domain/demo/DemoTransactionSender.kt +++ b/domain/demo/src/main/java/com/tangem/domain/demo/DemoTransactionSender.kt @@ -7,6 +7,8 @@ import com.tangem.blockchain.common.transaction.TransactionSendResult import com.tangem.blockchain.common.transaction.TransactionsSendResult import com.tangem.blockchain.extensions.Result import com.tangem.common.CompletionResult +import java.math.BigDecimal +import java.math.BigInteger import kotlin.random.Random class DemoTransactionSender(private val walletManager: WalletManager) : TransactionSender { @@ -15,9 +17,9 @@ class DemoTransactionSender(private val walletManager: WalletManager) : Transact val blockchain = walletManager.wallet.blockchain return Result.Success( TransactionFee.Choosable( - minimum = Fee.Common(Amount(minimumFee, blockchain)), - normal = Fee.Common(Amount(normalFee, blockchain)), - priority = Fee.Common(Amount(priorityFee, blockchain)), + minimum = blockchain.getStubFee(minimumFee), + normal = blockchain.getStubFee(normalFee), + priority = blockchain.getStubFee(priorityFee), ), ) } @@ -44,7 +46,16 @@ class DemoTransactionSender(private val walletManager: WalletManager) : Transact transactionDataList: List, signer: TransactionSigner, sendMode: TransactionSender.MultipleTransactionSendMode, - ): Result = Result.Failure(Exception(ID).toBlockchainSdkError()) + ): Result { + val signerResponse = signer.sign( + hash = getDataToSign(), + publicKey = walletManager.wallet.publicKey, + ) + return when (signerResponse) { + is CompletionResult.Success -> Result.Failure(Exception(ID).toBlockchainSdkError()) + is CompletionResult.Failure -> Result.fromTangemSdkError(signerResponse.error) + } + } private fun getDataToSign(): ByteArray { val charPool: List = ('a'..'z') + ('A'..'Z') + ('0'..'9') @@ -55,6 +66,23 @@ class DemoTransactionSender(private val walletManager: WalletManager) : Transact .toByteArray() } + private fun Blockchain.getStubFee(fee: BigDecimal) = when (this) { + Blockchain.Ethereum -> Fee.Ethereum.EIP1559( + amount = Amount(fee, this), + gasLimit = BigInteger.ONE, + maxFeePerGas = BigInteger.ONE, + priorityFee = BigInteger.ONE, + ) + Blockchain.Dogecoin, + Blockchain.Bitcoin, + -> Fee.Bitcoin( + amount = Amount(fee, this), + satoshiPerByte = BigDecimal.ONE, + txSize = BigDecimal.ONE, + ) + else -> Fee.Common(Amount(normalFee, this)) + } + companion object { val ID: String = DemoTransactionSender::class.java.simpleName diff --git a/domain/txhistory/src/main/kotlin/com/tangem/domain/txhistory/usecase/GetExplorerTransactionUrlUseCase.kt b/domain/txhistory/src/main/kotlin/com/tangem/domain/txhistory/usecase/GetExplorerTransactionUrlUseCase.kt index 991475bef2..974d439c7e 100644 --- a/domain/txhistory/src/main/kotlin/com/tangem/domain/txhistory/usecase/GetExplorerTransactionUrlUseCase.kt +++ b/domain/txhistory/src/main/kotlin/com/tangem/domain/txhistory/usecase/GetExplorerTransactionUrlUseCase.kt @@ -6,7 +6,6 @@ import arrow.core.raise.either import com.tangem.domain.tokens.model.Network import com.tangem.domain.txhistory.models.TxStatusError import com.tangem.domain.txhistory.repository.TxHistoryRepository -import com.tangem.domain.wallets.models.UserWalletId class GetExplorerTransactionUrlUseCase( private val repository: TxHistoryRepository, @@ -23,17 +22,4 @@ class GetExplorerTransactionUrlUseCase( ) } } - - suspend operator fun invoke(userWalletId: UserWalletId, network: Network): Either { - return either { - catch( - block = { - repository.getTxExploreUrl(userWalletId, network).ifEmpty { - raise(TxStatusError.EmptyUrlError) - } - }, - catch = { raise(TxStatusError.DataError(it)) }, - ) - } - } } \ No newline at end of file diff --git a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/presentation/ui/PushNotificationsScreen.kt b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/presentation/ui/PushNotificationsScreen.kt index 01d07a68ab..76d8ea97f8 100644 --- a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/presentation/ui/PushNotificationsScreen.kt +++ b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/presentation/ui/PushNotificationsScreen.kt @@ -19,9 +19,7 @@ internal fun PushNotificationsScreen( onAllowPermission: () -> Unit, onDenyPermission: () -> Unit, ) { - var isClicked by remember { mutableStateOf(false) } val requestPushPermission = requestPushPermission( - isClicked = isClicked, onAllow = onAllowPermission, onDeny = onDenyPermission, pushPermission = getPushPermissionOrNull(), @@ -43,7 +41,6 @@ internal fun PushNotificationsScreen( primaryButton = ShowcaseButtonModel( buttonText = resourceReference(R.string.common_allow), onClick = { - isClicked = true onRequest() requestPushPermission() }, diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/DefaultSendComponent.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/DefaultSendComponent.kt index 1f12ff1fdd..645441fe6e 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/DefaultSendComponent.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/DefaultSendComponent.kt @@ -24,6 +24,7 @@ import com.tangem.features.send.v2.common.PredefinedValues import com.tangem.features.send.v2.common.ui.SendContent import com.tangem.features.send.v2.common.ui.state.ConfirmUM import com.tangem.features.send.v2.send.analytics.SendAnalyticEvents +import com.tangem.features.send.v2.send.analytics.SendAnalyticEvents.SendScreenSource import com.tangem.features.send.v2.send.confirm.SendConfirmComponent import com.tangem.features.send.v2.send.model.SendModel import com.tangem.features.send.v2.subcomponents.amount.SendAmountComponent @@ -161,7 +162,20 @@ internal class DefaultSendComponent @AssistedInject constructor( cryptoCurrencyStatus = model.cryptoCurrencyStatus, callback = model, predefinedValues = model.predefinedValues, - onBackClick = ::onChildBack, + onBackClick = { + if (route.isEditMode) { + onChildBack() + } else { + analyticsEventHandler.send( + SendAnalyticEvents.CloseButtonClicked( + source = SendScreenSource.Amount, + isFromSummary = false, + isValid = model.uiState.value.amountUM.isPrimaryButtonEnabled, + ), + ) + router.pop() + } + }, onNextClick = { if (route.isEditMode) { onChildBack() diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/confirm/model/SendConfirmModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/confirm/model/SendConfirmModel.kt index c2483f978f..1cf654f799 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/confirm/model/SendConfirmModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/confirm/model/SendConfirmModel.kt @@ -378,10 +378,10 @@ internal class SendConfirmModel @Inject constructor( } } - private suspend fun updateTransactionStatus(txData: TransactionData.Uncompiled) { + private fun updateTransactionStatus(txData: TransactionData.Uncompiled) { val txUrl = getExplorerTransactionUrlUseCase( - userWalletId = userWallet.walletId, - network = cryptoCurrency.network, + txHash = txData.hash.orEmpty(), + networkId = cryptoCurrency.network.id, ).getOrElse { "" } _uiState.update(SendConfirmSentStateTransformer(txData, txUrl)) } diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/amount/model/SendAmountModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/amount/model/SendAmountModel.kt index 6210bce628..7e82ea275e 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/amount/model/SendAmountModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/amount/model/SendAmountModel.kt @@ -223,13 +223,12 @@ internal class SendAmountModel @Inject constructor( NavigationUM.Content( title = resourceReference(R.string.send_amount_label), subtitle = null, - backIconRes = R.drawable.ic_back_24, - backIconClick = { - if (!route.isEditMode) { - saveResult() - } - params.onBackClick() + backIconRes = if (route.isEditMode) { + R.drawable.ic_back_24 + } else { + R.drawable.ic_close_24 }, + backIconClick = { params.onBackClick() }, primaryButton = ButtonsUM.PrimaryButtonUM( text = if (route.isEditMode) { resourceReference(R.string.common_continue) diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/destination/model/SendDestinationModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/destination/model/SendDestinationModel.kt index f61949ffd7..e9ff9401a2 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/destination/model/SendDestinationModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/destination/model/SendDestinationModel.kt @@ -78,22 +78,11 @@ internal class SendDestinationModel @Inject constructor( private var validationJobHolder = JobHolder() init { - initSenderAddress() configDestinationNavigation() subscribeOnQRScannerResult() initialState() } - private fun initSenderAddress() { - modelScope.launch { - senderAddresses.value = getNetworkAddressesUseCase.invokeSync(userWalletId, cryptoCurrency.network) - .filter { cryptoCurrency.id == it.cryptoCurrency.id } - } - senderAddresses.onEach { - getWalletsAndRecent() - }.launchIn(modelScope) - } - private fun initialState() { if ((uiState.value as? DestinationUM.Content)?.isInitialized == false || uiState.value is DestinationUM.Empty) { _uiState.update( @@ -112,6 +101,7 @@ internal class SendDestinationModel @Inject constructor( ), ) } + initSenderAddress() } } @@ -150,6 +140,16 @@ internal class SendDestinationModel @Inject constructor( ) } + private fun initSenderAddress() { + modelScope.launch { + senderAddresses.value = getNetworkAddressesUseCase.invokeSync(userWalletId, cryptoCurrency.network) + .filter { cryptoCurrency.id == it.cryptoCurrency.id } + } + senderAddresses.onEach { + getWalletsAndRecent() + }.launchIn(modelScope) + } + private fun subscribeOnQRScannerResult() { listenToQrScanningUseCase(SourceType.SEND) .getOrElse { emptyFlow() } diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/model/SendModel.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/model/SendModel.kt index 882cbbae9a..9f4e696e39 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/model/SendModel.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/model/SendModel.kt @@ -515,13 +515,13 @@ internal class SendModel @Inject constructor( when (currentState.type) { SendUiStateType.Fee, SendUiStateType.EditFee, - -> if (uiState.value.feeState?.isPrimaryButtonEnabled == false) return + -> if (uiState.value.getFeeState(isFromEdit)?.isPrimaryButtonEnabled == false) return SendUiStateType.Amount, SendUiStateType.EditAmount, - -> if (!uiState.value.amountState.isPrimaryButtonEnabled) return + -> if (!uiState.value.getAmountState(isFromEdit).isPrimaryButtonEnabled) return SendUiStateType.Recipient, SendUiStateType.EditRecipient, - -> if (uiState.value.recipientState?.isPrimaryButtonEnabled == false) return + -> if (uiState.value.getRecipientState(isFromEdit)?.isPrimaryButtonEnabled == false) return SendUiStateType.Send -> if (uiState.value.sendState?.isPrimaryButtonEnabled == false) return SendUiStateType.None -> return } @@ -995,10 +995,10 @@ internal class SendModel @Inject constructor( } } - private suspend fun updateTransactionStatus(txData: TransactionData.Uncompiled) { + private fun updateTransactionStatus(txData: TransactionData.Uncompiled) { val txUrl = getExplorerTransactionUrlUseCase( - userWalletId = userWalletId, - network = cryptoCurrency.network, + txHash = txData.hash.orEmpty(), + networkId = cryptoCurrency.network.id, ).getOrElse { "" } uiState.value = stateFactory.getTransactionSendState(txData, txUrl) } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/PushNotificationsBottomSheet.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/PushNotificationsBottomSheet.kt index 67fec39547..e61ceddcbf 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/PushNotificationsBottomSheet.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/PushNotificationsBottomSheet.kt @@ -6,13 +6,13 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.padding -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import com.tangem.core.ui.components.PrimaryButton import com.tangem.core.ui.components.SecondaryButton -import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheet import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig +import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheet import com.tangem.core.ui.components.showcase.ShowcaseContent import com.tangem.core.ui.components.showcase.model.ShowcaseItemModel import com.tangem.core.ui.extensions.resourceReference @@ -34,10 +34,8 @@ internal fun PushNotificationsBottomSheet(config: TangemBottomSheetConfig) { @Composable private fun PushNotificationsSheetContent(content: PushNotificationsBottomSheetConfig, onDismiss: () -> Unit) { - var isClicked by remember { mutableStateOf(false) } val requestPushPermission = requestPushPermission( pushPermission = getPushPermissionOrNull(), - isClicked = isClicked, onAllow = { content.onAllow() onDismiss() @@ -84,7 +82,6 @@ private fun PushNotificationsSheetContent(content: PushNotificationsBottomSheetC PrimaryButton( text = stringResourceSafe(R.string.common_allow), onClick = { - isClicked = true content.onRequest() requestPushPermission() }, diff --git a/gradle/tangem_dependencies.toml b/gradle/tangem_dependencies.toml index a32c8679a0..7698d4b61b 100644 --- a/gradle/tangem_dependencies.toml +++ b/gradle/tangem_dependencies.toml @@ -5,7 +5,7 @@ # https://github.com/tangem/tangem-sdk-android/ # https://github.com/tangem/vico -tangemBlockchainSdk = "develop-1027" +tangemBlockchainSdk = "develop-1033" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "develop-455" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^