WalletConnect / WalletConnectKotlinV2

WalletConnect Kotlin SDK v2
Apache License 2.0
197 stars 70 forks source link

Approve session callback `onError ` callback called after `onSuccess` #1376

Open kamilargent opened 4 months ago

kamilargent commented 4 months ago

Describe the bug Web3Wallet#approveSession onError callback sometimes get called right after onSuccess.

SDK Version

To Reproduce Steps to reproduce the behavior:

  1. Initiate a connection with a dapp
  2. Approve session
  3. ???

Full steps to reproduce are unknown. We only notice this behaviour for few users.

Expected behavior Approve session callbacks should be called only once, and if onSucess is called onError should not be called

Device (please complete the following information):

Additional context We are wrapping the callbacks into coroutines and it's unexpected behaviour that we had to patch, that coroutine is resumed again

jakubuid commented 4 months ago

Hey! Thanks for the report. What's the error message returned by a callback?

kamilargent commented 4 months ago

Hey! Thanks for the report. What's the error message returned by a callback?

Hey. Unfortunately the exception was not included here because it was a crash from a coroutine. This is the full stacktrace if it helps:

Fatal Exception: java.lang.IllegalStateException: Already resumed
       at kotlin.coroutines.SafeContinuation.resumeWith(SafeContinuationJvm.kt:44)
       at im.argent.contractwalletclient.walletConnect.v2.Wc2ClientImpl$approveSession$2$1.invoke(Wc2Client.kt:106)
       at im.argent.contractwalletclient.walletConnect.v2.Wc2ClientImpl$approveSession$2$1.invoke(Wc2Client.kt:104)
       at com.walletconnect.web3.wallet.client.Web3Wallet$approveSession$2.invoke(Web3Wallet.kt:174)
       at com.walletconnect.web3.wallet.client.Web3Wallet$approveSession$2.invoke(Web3Wallet.kt:174)
       at com.walletconnect.web3.wallet.client.Web3Wallet$approveSession$2.invoke(Web3Wallet.kt:174)
       at com.walletconnect.web3.wallet.client.Web3Wallet$approveSession$2.invoke(Web3Wallet.kt:174)
       at com.walletconnect.sign.client.SignProtocol$approveSession$1$1.invoke(SignProtocol.kt:212)
       at com.walletconnect.sign.client.SignProtocol$approveSession$1$1.invoke(SignProtocol.kt:209)
       at com.walletconnect.sign.engine.use_case.calls.ApproveSessionUseCase$approve$2$sessionSettle$1.invoke(ApproveSessionUseCase.kt:76)
       at com.walletconnect.sign.engine.use_case.calls.ApproveSessionUseCase$approve$2$sessionSettle$1.invoke(ApproveSessionUseCase.kt:72)
       at com.walletconnect.android.internal.common.json_rpc.domain.JsonRpcInteractor$publishJsonRpcRequest$1.invoke(JsonRpcInteractor.kt:103)
       at com.walletconnect.android.internal.common.json_rpc.domain.JsonRpcInteractor$publishJsonRpcRequest$1.invoke(JsonRpcInteractor.kt:101)
       at com.walletconnect.foundation.network.BaseRelayClient$observePublishResult$1$1$invokeSuspend$$inlined$collect$1.emit(Collect.kt:136)
       at kotlinx.coroutines.flow.FlowKt__TransformKt.filter(FlowKt__Transform.kt:21)
       at com.walletconnect.foundation.network.BaseRelayClient$observePublishResult$1$1$invokeSuspend$$inlined$filter$1$2.emit(Collect.kt:134)
       at com.walletconnect.foundation.network.BaseRelayClient$observePublishResult$1$1$invokeSuspend$$inlined$filterIsInstance$1$2.emit(Collect.kt:135)
       at kotlinx.coroutines.flow.SharedFlowImpl.collect$suspendImpl(SharedFlow.kt:382)
       at kotlinx.coroutines.flow.SharedFlowImpl$collect$1.invokeSuspend(SharedFlow.kt)
       at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
       at kotlinx.coroutines.CoroutineContextKt.withContinuationContext(CoroutineContext.kt:108)
       at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:90)
       at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
       at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:115)
       at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:103)
       at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684)
jasonwyatt commented 2 months ago

We are also experiencing this. Here's some sample code where it can be exhibited:

suspendCoroutine { cont ->
    Web3Wallet.approveSession(
        params = Wallet.Params.SessionApprove(
            proposerPublicKey = sessionProposal.proposerPublicKey,
            namespaces = Web3Wallet.generateApprovedNamespaces(
                sessionProposal = sessionProposal,
                supportedNamespaces = supportedNamespaces
            ),
            relayProtocol = sessionProposal.relayProtocol
        ),
        onSuccess = { 
            cont.resume(Unit) 
        },
        onError = { 
            cont.resumeWithException(it.throwable) 
        }
    )
}