Updated on 2026-08-14
This commit is contained in:
commit
8adc79a8c3
12 changed files with 89 additions and 81 deletions
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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<TransactionData>,
|
||||
signer: TransactionSigner,
|
||||
sendMode: TransactionSender.MultipleTransactionSendMode,
|
||||
): Result<TransactionsSendResult> = Result.Failure(Exception(ID).toBlockchainSdkError())
|
||||
): Result<TransactionsSendResult> {
|
||||
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<Char> = ('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
|
||||
|
||||
|
|
|
|||
|
|
@ -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<TxStatusError, String> {
|
||||
return either {
|
||||
catch(
|
||||
block = {
|
||||
repository.getTxExploreUrl(userWalletId, network).ifEmpty {
|
||||
raise(TxStatusError.EmptyUrlError)
|
||||
}
|
||||
},
|
||||
catch = { raise(TxStatusError.DataError(it)) },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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()
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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() }
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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 ^
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue