Updated on 2026-08-14
This commit is contained in:
parent
638a9a4930
commit
f8a1ee8ad2
7 changed files with 54 additions and 28 deletions
|
|
@ -10,7 +10,7 @@ package com.tangem.core.ui.components.bottomsheets
|
|||
data class TangemBottomSheetConfig(
|
||||
val isShown: Boolean,
|
||||
val onDismissRequest: () -> Unit,
|
||||
val dismissOnClickOutside: () -> Boolean = { true },
|
||||
val dismissOnClickOutside: (() -> Boolean)? = null,
|
||||
val content: TangemBottomSheetConfigContent,
|
||||
) {
|
||||
|
||||
|
|
|
|||
|
|
@ -88,17 +88,22 @@ inline fun <reified T : TangemBottomSheetConfigContent> DefaultModalBottomSheetW
|
|||
noinline footer: @Composable (BoxScope.(T) -> Unit)?,
|
||||
) {
|
||||
var isVisible by remember { mutableStateOf(value = config.isShown) }
|
||||
val sheetState = rememberModalBottomSheetState(
|
||||
skipPartiallyExpanded = skipPartiallyExpanded,
|
||||
confirmValueChange = { sheetValue ->
|
||||
if (config.dismissOnClickOutside().not()) {
|
||||
// Ignore transitions to hidden (prevents dismiss on outside click/back press)
|
||||
sheetValue != SheetValue.Hidden
|
||||
} else {
|
||||
true
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
val sheetState = if (config.dismissOnClickOutside == null) {
|
||||
rememberModalBottomSheetState(skipPartiallyExpanded = skipPartiallyExpanded)
|
||||
} else {
|
||||
rememberModalBottomSheetState(
|
||||
skipPartiallyExpanded = skipPartiallyExpanded,
|
||||
confirmValueChange = { sheetValue ->
|
||||
if (config.dismissOnClickOutside().not()) {
|
||||
// Ignore transitions to hidden (prevents dismiss on outside click/back press)
|
||||
sheetValue != SheetValue.Hidden
|
||||
} else {
|
||||
true
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
if (isVisible && config.content is T) {
|
||||
BasicModalBottomSheetWithFooter<T>(
|
||||
|
|
|
|||
|
|
@ -124,7 +124,10 @@ internal object WalletConnectDataModule {
|
|||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun defaultWcRequestService(diHelperBox: DiHelperBox, respondService: WcRespondService): DefaultWcRequestService {
|
||||
fun defaultWcRequestService(
|
||||
diHelperBox: DiHelperBox,
|
||||
respondService: DefaultWcRespondService,
|
||||
): DefaultWcRequestService {
|
||||
return DefaultWcRequestService(
|
||||
requestConverters = diHelperBox.handlers,
|
||||
respondService = respondService,
|
||||
|
|
@ -133,7 +136,11 @@ internal object WalletConnectDataModule {
|
|||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun wcRespondService(): WcRespondService = DefaultWcRespondService()
|
||||
fun wcDefaultWcRespondService(): DefaultWcRespondService = DefaultWcRespondService()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun wcRespondService(default: DefaultWcRespondService): WcRespondService = default
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
package com.tangem.data.walletconnect.request
|
||||
|
||||
import com.reown.walletkit.client.Wallet
|
||||
import com.tangem.common.extensions.calculateSha256
|
||||
import com.tangem.common.extensions.toHexString
|
||||
import com.tangem.data.walletconnect.respond.WcRespondService
|
||||
import com.tangem.data.walletconnect.respond.DefaultWcRespondService
|
||||
import com.tangem.data.walletconnect.utils.WC_TAG
|
||||
import com.tangem.data.walletconnect.utils.WcSdkObserver
|
||||
import com.tangem.data.walletconnect.utils.WcSdkSessionRequestConverter
|
||||
|
|
@ -14,16 +12,13 @@ import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
|
|||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.*
|
||||
import org.joda.time.DateTime
|
||||
import org.joda.time.Duration
|
||||
import timber.log.Timber
|
||||
|
||||
internal class DefaultWcRequestService(
|
||||
private val requestConverters: Set<WcRequestToUseCaseConverter>,
|
||||
private val respondService: WcRespondService,
|
||||
private val respondService: DefaultWcRespondService,
|
||||
) : WcSdkObserver, WcRequestService {
|
||||
|
||||
private val expireDuration = Duration.standardSeconds(120)
|
||||
private val cachedRequest = MutableStateFlow<Set<Pair<Long, String>>>(setOf())
|
||||
private val _wcRequest: Channel<Pair<WcMethodName, WcSdkSessionRequest>> = Channel(Channel.BUFFERED)
|
||||
override val wcRequest: Flow<Pair<WcMethodName, WcSdkSessionRequest>> = _wcRequest.receiveAsFlow()
|
||||
.filter { filterDuplicateRequest(request = it.second) }
|
||||
|
|
@ -52,10 +47,10 @@ internal class DefaultWcRequestService(
|
|||
}
|
||||
|
||||
private fun filterDuplicateRequest(request: WcSdkSessionRequest): Boolean {
|
||||
val hash = request.request.params.calculateSha256().toHexString()
|
||||
val hash = respondService.sessionRequestHash(request)
|
||||
val now = DateTime.now().millis
|
||||
val expiredMillis = now - expireDuration.millis
|
||||
val cachedRequest = cachedRequest.updateAndGet {
|
||||
val expiredMillis = now - respondService.expireDuration.millis
|
||||
val cachedRequest = respondService.cachedRequest.updateAndGet {
|
||||
it.filterTo(mutableSetOf()) { (millis, _) -> millis > expiredMillis }
|
||||
}
|
||||
|
||||
|
|
@ -67,8 +62,8 @@ internal class DefaultWcRequestService(
|
|||
}
|
||||
|
||||
private fun saveRequest(request: WcSdkSessionRequest) {
|
||||
val hash = request.request.params.calculateSha256().toHexString()
|
||||
val hash = respondService.sessionRequestHash(request)
|
||||
val now = DateTime.now().millis
|
||||
cachedRequest.update { it + (now to hash) }
|
||||
respondService.cachedRequest.update { it + (now to hash) }
|
||||
}
|
||||
}
|
||||
|
|
@ -5,15 +5,27 @@ import arrow.core.left
|
|||
import arrow.core.right
|
||||
import com.reown.walletkit.client.Wallet
|
||||
import com.reown.walletkit.client.WalletKit
|
||||
import com.tangem.common.extensions.calculateSha256
|
||||
import com.tangem.common.extensions.toHexString
|
||||
import com.tangem.data.walletconnect.utils.WC_TAG
|
||||
import com.tangem.domain.walletconnect.model.WcRequestError
|
||||
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
import org.joda.time.Duration
|
||||
import timber.log.Timber
|
||||
import kotlin.coroutines.resume
|
||||
|
||||
internal class DefaultWcRespondService : WcRespondService {
|
||||
|
||||
internal val expireDuration = Duration.standardSeconds(120)
|
||||
internal val cachedRequest = MutableStateFlow<Set<Pair<Long, String>>>(emptySet())
|
||||
|
||||
internal fun sessionRequestHash(request: WcSdkSessionRequest): String {
|
||||
return request.request.params.calculateSha256().toHexString()
|
||||
}
|
||||
|
||||
override suspend fun respond(request: WcSdkSessionRequest, response: String): Either<WcRequestError, String> =
|
||||
suspendCancellableCoroutine { continuation ->
|
||||
WalletKit.respondSessionRequest(
|
||||
|
|
@ -56,6 +68,7 @@ internal class DefaultWcRespondService : WcRespondService {
|
|||
|
||||
override fun rejectRequestNonBlock(request: WcSdkSessionRequest, message: String) {
|
||||
Timber.tag(WC_TAG).i("reject request $request")
|
||||
removeCachedRequest(request)
|
||||
WalletKit.respondSessionRequest(
|
||||
params = Wallet.Params.SessionRequestResponse(
|
||||
sessionTopic = request.topic,
|
||||
|
|
@ -69,4 +82,10 @@ internal class DefaultWcRespondService : WcRespondService {
|
|||
onError = {},
|
||||
)
|
||||
}
|
||||
|
||||
private fun removeCachedRequest(request: WcSdkSessionRequest) {
|
||||
cachedRequest.update { set ->
|
||||
set.filterTo(mutableSetOf()) { (_, hash) -> hash != sessionRequestHash(request) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -27,7 +27,7 @@ internal fun getWcCommonScreen(
|
|||
is WcTransactionRoutes.Transaction -> transactionScreenConverter()
|
||||
is WcTransactionRoutes.Alert -> AlertsComponentV2(
|
||||
appComponentContext = appComponentContext,
|
||||
messageUM = createCommonTransactionAppInfoAlertUM(config.type),
|
||||
messageUM = createCommonTransactionAppInfoAlertUM(config.alertType),
|
||||
)
|
||||
is WcTransactionRoutes.TransactionRequestInfo -> WcTransactionRequestInfoComponent(
|
||||
appComponentContext = appComponentContext,
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ internal sealed class WcTransactionRoutes : TangemBottomSheetConfigContent, Rout
|
|||
data object SelectFee : WcTransactionRoutes()
|
||||
|
||||
@Serializable
|
||||
data class Alert(val type: Type) : WcTransactionRoutes() {
|
||||
data class Alert(val alertType: Type) : WcTransactionRoutes() {
|
||||
@Serializable
|
||||
sealed class Type {
|
||||
data class Verified(val appName: String) : Type()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue