Updated on 2026-08-14

This commit is contained in:
Tangem 2025-09-10 16:57:31 +03:00
commit 83ab0146ec
4 changed files with 39 additions and 5 deletions

View file

@ -1,6 +1,8 @@
package com.tangem.data.walletconnect.request package com.tangem.data.walletconnect.request
import com.reown.walletkit.client.Wallet 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.WcRespondService
import com.tangem.data.walletconnect.utils.WC_TAG import com.tangem.data.walletconnect.utils.WC_TAG
import com.tangem.data.walletconnect.utils.WcSdkObserver import com.tangem.data.walletconnect.utils.WcSdkObserver
@ -9,8 +11,9 @@ import com.tangem.domain.walletconnect.WcRequestService
import com.tangem.domain.walletconnect.model.WcMethodName import com.tangem.domain.walletconnect.model.WcMethodName
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.*
import kotlinx.coroutines.flow.receiveAsFlow import org.joda.time.DateTime
import org.joda.time.Duration
import timber.log.Timber import timber.log.Timber
internal class DefaultWcRequestService( internal class DefaultWcRequestService(
@ -18,8 +21,12 @@ internal class DefaultWcRequestService(
private val respondService: WcRespondService, private val respondService: WcRespondService,
) : WcSdkObserver, WcRequestService { ) : 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) private val _wcRequest: Channel<Pair<WcMethodName, WcSdkSessionRequest>> = Channel(Channel.BUFFERED)
override val wcRequest: Flow<Pair<WcMethodName, WcSdkSessionRequest>> = _wcRequest.receiveAsFlow() override val wcRequest: Flow<Pair<WcMethodName, WcSdkSessionRequest>> = _wcRequest.receiveAsFlow()
.filter { filterDuplicateRequest(request = it.second) }
.onEach { saveRequest(request = it.second) }
override fun onSessionRequest( override fun onSessionRequest(
sessionRequest: Wallet.Model.SessionRequest, sessionRequest: Wallet.Model.SessionRequest,
@ -42,4 +49,25 @@ internal class DefaultWcRequestService(
} }
_wcRequest.trySend(name to sr) _wcRequest.trySend(name to sr)
} }
private fun filterDuplicateRequest(request: WcSdkSessionRequest): Boolean {
val hash = request.request.params.calculateSha256().toHexString()
val now = DateTime.now().millis
val expiredMillis = now - expireDuration.millis
val cachedRequest = cachedRequest.updateAndGet {
it.filterTo(mutableSetOf()) { (millis, _) -> millis > expiredMillis }
}
val noHaveCached = cachedRequest.none { (_, hashParams) -> hash == hashParams }
if (!noHaveCached) {
Timber.tag(WC_TAG).i("filter request $request")
}
return noHaveCached
}
private fun saveRequest(request: WcSdkSessionRequest) {
val hash = request.request.params.calculateSha256().toHexString()
val now = DateTime.now().millis
cachedRequest.update { it + (now to hash) }
}
} }

View file

@ -36,7 +36,12 @@ internal class DefaultWcRespondService : WcRespondService {
} }
is Wallet.Model.JsonRpcResponse.JsonRpcResult -> { is Wallet.Model.JsonRpcResponse.JsonRpcResult -> {
Timber.tag(WC_TAG).i("Successful respond $response for request $request") Timber.tag(WC_TAG).i("Successful respond $response for request $request")
response.result.right() if (response.result == null) {
Timber.tag(WC_TAG).e(
"Response result is null, but it should be String. Casted to empty",
)
}
(response.result ?: "").right()
} }
} }
continuation.resume(result) continuation.resume(result)

View file

@ -56,6 +56,7 @@ internal class DefaultWcPairUseCaseTest {
proposerPublicKey = "", proposerPublicKey = "",
relayProtocol = "", relayProtocol = "",
relayData = "", relayData = "",
scopedProperties = null,
) )
private val sdkVerifyContext: Wallet.Model.VerifyContext private val sdkVerifyContext: Wallet.Model.VerifyContext
get() = Wallet.Model.VerifyContext( get() = Wallet.Model.VerifyContext(

View file

@ -79,8 +79,8 @@ zxingQrCode = "3.5.1"
kotlinSerialization = "1.8.0" kotlinSerialization = "1.8.0"
kotlinDatetime = "0.6.2" kotlinDatetime = "0.6.2"
arrow = "1.2.4" # 2.0.1 breaks the build arrow = "1.2.4" # 2.0.1 breaks the build
reownCore = "1.1.2" reownCore = "1.4.9"
reownWeb3 = "1.1.2" reownWeb3 = "1.4.9"
prettyLogger = "2.2.0" prettyLogger = "2.2.0"
okHttp-prettyLogging = "3.1.0" okHttp-prettyLogging = "3.1.0"
chucker = "4.0.0" chucker = "4.0.0"