Updated on 2026-08-14
This commit is contained in:
parent
69fec5dc58
commit
af243495bd
6 changed files with 47 additions and 25 deletions
|
|
@ -28,7 +28,7 @@ internal class AssociateNetworksDelegate(
|
|||
}
|
||||
}
|
||||
|
||||
@Throws(WcPairError.UnsupportedNetworks::class)
|
||||
@Throws(WcPairError.UnsupportedBlockchains::class)
|
||||
suspend fun associate(sessionProposal: Wallet.Model.SessionProposal): Map<UserWallet, ProposalNetwork> {
|
||||
val userWallets = getWallets.invokeSync().filter { it.isMultiCurrency }
|
||||
val requiredNamespaces: Set<String> = sessionProposal.requiredNamespaces.setOfChainId()
|
||||
|
|
@ -74,7 +74,7 @@ internal class AssociateNetworksDelegate(
|
|||
notAdded.add(wcNetwork)
|
||||
}
|
||||
}
|
||||
if (unknownRequired.isNotEmpty()) throw WcPairError.UnsupportedNetworks(unknownRequired)
|
||||
if (unknownRequired.isNotEmpty()) throw WcPairError.UnsupportedBlockchains(unknownRequired)
|
||||
return ProposalNetwork(
|
||||
wallet = wallet,
|
||||
missingRequired = missingRequired,
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ internal class DefaultWcPairUseCase @AssistedInject constructor(
|
|||
// check unsupported dApps, just local constant for now, finish if unsupported
|
||||
if (sdkSessionProposal.name in unsupportedDApps) {
|
||||
Timber.tag(WC_TAG).i("Unsupported DApp ${sdkSessionProposal.name}")
|
||||
val error = WcPairState.Error(WcPairError.UnsupportedDApp)
|
||||
val error = WcPairState.Error(WcPairError.UnsupportedDomain)
|
||||
emit(error)
|
||||
return@flow
|
||||
}
|
||||
|
|
@ -104,7 +104,7 @@ internal class DefaultWcPairUseCase @AssistedInject constructor(
|
|||
)
|
||||
newSession
|
||||
}.onLeft {
|
||||
analytics.send(WcAnalyticEvents.DAppConnectionFailed(it.message))
|
||||
analytics.send(WcAnalyticEvents.DAppConnectionFailed(it.code))
|
||||
Timber.tag(WC_TAG).e(it, "Failed to approve session ${sdkSessionProposal.name}")
|
||||
}
|
||||
emit(WcPairState.Approving.Result(sessionForApprove, either))
|
||||
|
|
|
|||
|
|
@ -27,7 +27,11 @@ internal class WcPairSdkDelegate : WcSdkObserver {
|
|||
|
||||
val pairCall = async { sdkPair(url) }
|
||||
val proposal = async { proposalCallback() }
|
||||
pairCall.await().map { proposal.await() }
|
||||
pairCall.await().onLeft {
|
||||
proposal.cancel()
|
||||
return@coroutineScope it.left()
|
||||
}
|
||||
proposal.await().right()
|
||||
}
|
||||
|
||||
suspend fun approve(
|
||||
|
|
@ -40,11 +44,14 @@ internal class WcPairSdkDelegate : WcSdkObserver {
|
|||
val approveCall = async { sdkApprove(sessionApprove) }
|
||||
val approveCallback = async { approveCallback() }
|
||||
approveCall.await()
|
||||
.onLeft { return@coroutineScope it.left() }
|
||||
.onLeft {
|
||||
approveCallback.cancel()
|
||||
return@coroutineScope it.left()
|
||||
}
|
||||
when (val result = approveCallback.await()) {
|
||||
is Wallet.Model.SettledSessionResponse.Result -> result.right()
|
||||
is Wallet.Model.SettledSessionResponse.Error ->
|
||||
WcPairError.ExternalApprovalError(result.errorMessage).left()
|
||||
WcPairError.ApprovalFailed(result.errorMessage).left()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -77,7 +84,7 @@ internal class WcPairSdkDelegate : WcSdkObserver {
|
|||
WalletKit.approveSession(
|
||||
params = sessionApprove,
|
||||
onSuccess = { continuation.resume(Unit.right()) },
|
||||
onError = { continuation.resume(it.throwable.toPairError()) },
|
||||
onError = { continuation.resume(it.throwable.toApproveError()) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -87,10 +94,20 @@ internal class WcPairSdkDelegate : WcSdkObserver {
|
|||
WalletKit.pair(
|
||||
params = Wallet.Params.Pair(uri),
|
||||
onSuccess = { continuation.resume(Unit.right()) },
|
||||
onError = { continuation.resume(it.throwable.toPairError()) },
|
||||
onError = { continuation.resume(it.throwable.toPairError().left()) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Throwable.toPairError() = WcPairError.ExternalApprovalError(this.localizedMessage.orEmpty()).left()
|
||||
private fun Throwable.toPairError() = when {
|
||||
pairingExpiredMessages.any { message.orEmpty().contains(it) } -> WcPairError.UriAlreadyUsed(message.orEmpty())
|
||||
else -> WcPairError.PairingFailed(this.localizedMessage.orEmpty())
|
||||
}
|
||||
|
||||
private fun Throwable.toApproveError() = WcPairError.ApprovalFailed(this.localizedMessage.orEmpty()).left()
|
||||
|
||||
companion object {
|
||||
// com.reown.android.pairing.engine.domain.PairingEngine.pair
|
||||
private val pairingExpiredMessages = listOf("Pairing URI expired", "Pairing expired")
|
||||
}
|
||||
}
|
||||
|
|
@ -196,7 +196,7 @@ internal class DefaultWcPairUseCaseTest {
|
|||
@Test
|
||||
fun `success pair and reject unsupported dApp`() = runTest {
|
||||
coEvery { sdkDelegate.pair(url) } returns unsupportedSdkProposal.right()
|
||||
val unsupportedDAppError = WcPairState.Error(WcPairError.UnsupportedDApp)
|
||||
val unsupportedDAppError = WcPairState.Error(WcPairError.UnsupportedDomain)
|
||||
|
||||
val useCase = useCaseFactory()
|
||||
useCase.invoke().test {
|
||||
|
|
@ -211,7 +211,7 @@ internal class DefaultWcPairUseCaseTest {
|
|||
|
||||
@Test
|
||||
fun `complete on pair error`() = runTest {
|
||||
val error = WcPairError.ExternalApprovalError("error")
|
||||
val error = WcPairError.PairingFailed("error")
|
||||
coEvery { sdkDelegate.pair(url) } returns error.left()
|
||||
val errorState = WcPairState.Error(error)
|
||||
|
||||
|
|
@ -229,7 +229,7 @@ internal class DefaultWcPairUseCaseTest {
|
|||
@Test
|
||||
fun `complete on approve error`() = runTest {
|
||||
val approveLoading = WcPairState.Approving.Loading(sessionForApprove)
|
||||
val error = WcPairError.ExternalApprovalError("error").left()
|
||||
val error = WcPairError.ApprovalFailed("error").left()
|
||||
coEvery { sdkDelegate.pair(url) } returns sdkProposal.right()
|
||||
coEvery { sdkDelegate.approve(sdkApprove) } returns error
|
||||
coEvery { blockAidVerifier.verifyDApp(any()) } returns Either.catch { CheckDAppResult.SAFE }
|
||||
|
|
|
|||
|
|
@ -1,15 +1,19 @@
|
|||
package com.tangem.domain.walletconnect.model
|
||||
|
||||
sealed class WcPairError(override val message: String) : Exception(message) {
|
||||
sealed class WcPairError(
|
||||
val code: String,
|
||||
override val message: String = "",
|
||||
) : Exception() {
|
||||
|
||||
data object UnsupportedDApp : WcPairError("UnsupportedDApp")
|
||||
data class UnsupportedNetworks(
|
||||
val chains: Set<String>,
|
||||
) : WcPairError("ApprovalErrorMissingNetworks")
|
||||
|
||||
data class ExternalApprovalError(
|
||||
override val message: String,
|
||||
) : WcPairError("ExternalApprovalError")
|
||||
data class UriAlreadyUsed(override val message: String) : WcPairError("107 001 001")
|
||||
data class PairingFailed(override val message: String) : WcPairError("107 001 002")
|
||||
data object InvalidDomainURL : WcPairError("107 001 003")
|
||||
data object UnsupportedDomain : WcPairError("107 001 004")
|
||||
data class UnsupportedBlockchains(val chains: Set<String>) : WcPairError("107 001 005")
|
||||
|
||||
data object InvalidConnectionRequest : WcPairError("107 002 001")
|
||||
data object ProposalExpired : WcPairError("107 002 002")
|
||||
data class ApprovalFailed(override val message: String) : WcPairError("107 002 003")
|
||||
data object RejectionFailed : WcPairError("107 002 004")
|
||||
data class Unknown(override val message: String) : WcPairError(message)
|
||||
}
|
||||
|
|
@ -13,6 +13,7 @@ import com.tangem.core.decompose.ui.UiMessageSender
|
|||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.message.ToastMessage
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.walletconnect.model.WcPairError
|
||||
import com.tangem.domain.walletconnect.model.WcPairRequest
|
||||
import com.tangem.domain.walletconnect.model.WcSessionApprove
|
||||
import com.tangem.domain.walletconnect.model.WcSessionProposal
|
||||
|
|
@ -32,7 +33,6 @@ import com.tangem.features.walletconnect.connections.model.transformers.WcDAppVe
|
|||
import com.tangem.features.walletconnect.connections.routes.WcAppInfoRoutes
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.*
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
import kotlin.properties.Delegates
|
||||
import com.tangem.utils.transformer.update as transformerUpdate
|
||||
|
|
@ -78,6 +78,7 @@ internal class WcPairModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun loadDAppInfo() {
|
||||
fun errorToast(error: WcPairError) = messageSender.send(ToastMessage(message = stringReference(error.message)))
|
||||
wcPairUseCase()
|
||||
.onEach { pairState ->
|
||||
when (pairState) {
|
||||
|
|
@ -88,14 +89,14 @@ internal class WcPairModel @Inject constructor(
|
|||
appInfoUiState.transformerUpdate(
|
||||
WcConnectButtonProgressTransformer(showProgress = false),
|
||||
)
|
||||
pairState.result.onLeft(::errorToast)
|
||||
router.pop()
|
||||
}
|
||||
is WcPairState.Error -> {
|
||||
appInfoUiState.transformerUpdate(
|
||||
WcConnectButtonProgressTransformer(showProgress = false),
|
||||
)
|
||||
messageSender.send(ToastMessage(message = stringReference(pairState.error.message)))
|
||||
Timber.e(pairState.error)
|
||||
errorToast(pairState.error)
|
||||
}
|
||||
is WcPairState.Loading -> appInfoUiState.update { createLoadingState() }
|
||||
is WcPairState.Proposal -> {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue