Updated on 2026-08-14
This commit is contained in:
parent
67457f0746
commit
63a718d771
25 changed files with 186 additions and 85 deletions
|
|
@ -36,7 +36,7 @@ import java.math.BigInteger
|
|||
internal class DefaultTransactionRepository(
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
private val walletManagersStore: WalletManagersStore,
|
||||
private val coroutineDispatcherProvider: CoroutineDispatcherProvider,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : TransactionRepository {
|
||||
|
||||
override suspend fun createTransaction(
|
||||
|
|
@ -47,7 +47,7 @@ internal class DefaultTransactionRepository(
|
|||
userWalletId: UserWalletId,
|
||||
network: Network,
|
||||
txExtras: TransactionExtras?,
|
||||
): TransactionData.Uncompiled = withContext(coroutineDispatcherProvider.io) {
|
||||
): TransactionData.Uncompiled = withContext(dispatchers.io) {
|
||||
val blockchain = network.toBlockchain()
|
||||
val walletManager = walletManagersFacade.getOrCreateWalletManager(
|
||||
userWalletId = userWalletId,
|
||||
|
|
@ -84,7 +84,7 @@ internal class DefaultTransactionRepository(
|
|||
userWalletId: UserWalletId,
|
||||
network: Network,
|
||||
nonce: BigInteger?,
|
||||
): TransactionData.Uncompiled = withContext(coroutineDispatcherProvider.io) {
|
||||
): TransactionData.Uncompiled = withContext(dispatchers.io) {
|
||||
val blockchain = network.toBlockchain()
|
||||
val walletManager = walletManagersFacade.getOrCreateWalletManager(
|
||||
userWalletId = userWalletId,
|
||||
|
|
@ -138,7 +138,7 @@ internal class DefaultTransactionRepository(
|
|||
spenderAddress: String,
|
||||
userWalletId: UserWalletId,
|
||||
network: Network,
|
||||
): TransactionData.Uncompiled = withContext(coroutineDispatcherProvider.io) {
|
||||
): TransactionData.Uncompiled = withContext(dispatchers.io) {
|
||||
val blockchain = network.toBlockchain()
|
||||
|
||||
val extras = createTransactionDataExtras(
|
||||
|
|
@ -171,7 +171,7 @@ internal class DefaultTransactionRepository(
|
|||
destinationAddress: String,
|
||||
userWalletId: UserWalletId,
|
||||
network: Network,
|
||||
): TransactionData.Uncompiled = withContext(coroutineDispatcherProvider.io) {
|
||||
): TransactionData.Uncompiled = withContext(dispatchers.io) {
|
||||
val blockchain = network.toBlockchain()
|
||||
|
||||
// For now transfer one nft asset at a time
|
||||
|
|
@ -229,7 +229,7 @@ internal class DefaultTransactionRepository(
|
|||
destination: String,
|
||||
userWalletId: UserWalletId,
|
||||
network: Network,
|
||||
): Result<Unit> = withContext(coroutineDispatcherProvider.io) {
|
||||
): Result<Unit> = withContext(dispatchers.io) {
|
||||
val blockchain = network.toBlockchain()
|
||||
val walletManager = walletManagersStore.getSyncOrNull(
|
||||
userWalletId = userWalletId,
|
||||
|
|
@ -260,7 +260,7 @@ internal class DefaultTransactionRepository(
|
|||
signer: TransactionSigner,
|
||||
userWalletId: UserWalletId,
|
||||
network: Network,
|
||||
) = withContext(coroutineDispatcherProvider.io) {
|
||||
) = withContext(dispatchers.io) {
|
||||
val blockchain = network.toBlockchain()
|
||||
val walletManager = walletManagersFacade.getOrCreateWalletManager(
|
||||
userWalletId = userWalletId,
|
||||
|
|
@ -276,7 +276,7 @@ internal class DefaultTransactionRepository(
|
|||
userWalletId: UserWalletId,
|
||||
network: Network,
|
||||
sendMode: TransactionSender.MultipleTransactionSendMode,
|
||||
) = withContext(coroutineDispatcherProvider.io) {
|
||||
) = withContext(dispatchers.io) {
|
||||
val blockchain = network.toBlockchain()
|
||||
val walletManager = walletManagersFacade.getOrCreateWalletManager(
|
||||
userWalletId = userWalletId,
|
||||
|
|
@ -366,13 +366,9 @@ internal class DefaultTransactionRepository(
|
|||
signer: TransactionSigner,
|
||||
userWalletId: UserWalletId,
|
||||
network: Network,
|
||||
): Result<ByteArray> = withContext(coroutineDispatcherProvider.io) {
|
||||
) = withContext(dispatchers.io) {
|
||||
val preparer = getPreparer(network, userWalletId)
|
||||
|
||||
when (val prepareForSend = preparer.prepareForSend(transactionData, signer)) {
|
||||
is com.tangem.blockchain.extensions.Result.Failure -> Result.failure(prepareForSend.error)
|
||||
is com.tangem.blockchain.extensions.Result.Success -> Result.success(prepareForSend.data)
|
||||
}
|
||||
preparer.prepareForSend(transactionData, signer)
|
||||
}
|
||||
|
||||
override suspend fun prepareForSendMultiple(
|
||||
|
|
@ -380,13 +376,9 @@ internal class DefaultTransactionRepository(
|
|||
signer: TransactionSigner,
|
||||
userWalletId: UserWalletId,
|
||||
network: Network,
|
||||
): Result<List<ByteArray>> = withContext(coroutineDispatcherProvider.io) {
|
||||
) = withContext(dispatchers.io) {
|
||||
val preparer = getPreparer(network, userWalletId)
|
||||
|
||||
when (val prepareForSend = preparer.prepareForSendMultiple(transactionData, signer)) {
|
||||
is com.tangem.blockchain.extensions.Result.Failure -> Result.failure(prepareForSend.error)
|
||||
is com.tangem.blockchain.extensions.Result.Success -> Result.success(prepareForSend.data)
|
||||
}
|
||||
preparer.prepareForSendMultiple(transactionData, signer)
|
||||
}
|
||||
|
||||
private suspend fun getPreparer(network: Network, userWalletId: UserWalletId): TransactionPreparer {
|
||||
|
|
|
|||
|
|
@ -24,12 +24,12 @@ internal object TransactionDataModule {
|
|||
fun providesTransactionRepository(
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
walletManagersStore: WalletManagersStore,
|
||||
coroutineDispatcherProvider: CoroutineDispatcherProvider,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): TransactionRepository {
|
||||
return DefaultTransactionRepository(
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
walletManagersStore = walletManagersStore,
|
||||
coroutineDispatcherProvider = coroutineDispatcherProvider,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.tangem.data.walletconnect.respond.WcRespondService
|
|||
import com.tangem.data.walletconnect.sign.WcMethodUseCaseContext
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.walletconnect.model.WcEthMethod
|
||||
import com.tangem.domain.walletconnect.model.WcRequestError
|
||||
import com.tangem.domain.walletconnect.model.WcSession
|
||||
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcAddNetworkUseCase
|
||||
|
|
@ -27,7 +28,7 @@ internal class WcEthAddNetworkUseCase @AssistedInject constructor(
|
|||
override val walletAddress: String
|
||||
get() = context.accountAddress
|
||||
|
||||
override suspend fun approve(): Either<Throwable, Unit> {
|
||||
override suspend fun approve(): Either<WcRequestError, String> {
|
||||
return respondService.respond(rawSdkRequest, "")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import com.tangem.data.walletconnect.sign.SignStateConverter.toResult
|
|||
import com.tangem.data.walletconnect.sign.WcMethodUseCaseContext
|
||||
import com.tangem.data.walletconnect.utils.BlockAidVerificationDelegate
|
||||
import com.tangem.domain.transaction.usecase.SignUseCase
|
||||
import com.tangem.domain.walletconnect.error.parseTangemSdkError
|
||||
import com.tangem.domain.walletconnect.model.WcEthMethod
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcMessageSignUseCase
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcSignState
|
||||
|
|
@ -59,7 +60,7 @@ internal class WcEthMessageSignUseCase @AssistedInject constructor(
|
|||
?: return
|
||||
|
||||
val signedHash = signUseCase(hashToSign, userWallet, network)
|
||||
.onLeft { emit(state.toResult(it.left())) }
|
||||
.onLeft { emit(state.toResult(parseTangemSdkError(it).left())) }
|
||||
.getOrNull() ?: return
|
||||
|
||||
val respond = prepareToSendMessageData(signedHash, hashToSign, walletManager)
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import com.tangem.data.walletconnect.utils.BlockAidVerificationDelegate
|
|||
import com.tangem.domain.core.lce.LceFlow
|
||||
import com.tangem.domain.tokens.model.Amount
|
||||
import com.tangem.domain.transaction.usecase.SendTransactionUseCase
|
||||
import com.tangem.domain.walletconnect.error.parseSendError
|
||||
import com.tangem.domain.walletconnect.model.WcApprovedAmount
|
||||
import com.tangem.domain.walletconnect.model.WcEthMethod
|
||||
import com.tangem.domain.walletconnect.usecase.method.*
|
||||
|
|
@ -80,8 +81,7 @@ internal class WcEthSendTransactionUseCase @AssistedInject constructor(
|
|||
override suspend fun SignCollector<TransactionData>.onSign(state: WcSignState<TransactionData>) {
|
||||
val hash = sendTransaction(state.signModel, wallet, network)
|
||||
.onLeft { error ->
|
||||
val sendError = IllegalArgumentException(error.toString()) // todo(wc) use domain error
|
||||
emit(state.toResult(sendError.left()))
|
||||
emit(state.toResult(parseSendError(error).left()))
|
||||
}
|
||||
.getOrNull() ?: return
|
||||
val respondResult = respondService.respond(rawSdkRequest, hash.formatHex())
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import com.tangem.data.walletconnect.sign.WcMethodUseCaseContext
|
|||
import com.tangem.data.walletconnect.utils.BlockAidVerificationDelegate
|
||||
import com.tangem.domain.tokens.model.Amount
|
||||
import com.tangem.domain.transaction.usecase.PrepareForSendUseCase
|
||||
import com.tangem.domain.walletconnect.error.parseSendError
|
||||
import com.tangem.domain.walletconnect.model.WcApprovedAmount
|
||||
import com.tangem.domain.walletconnect.model.WcEthMethod
|
||||
import com.tangem.domain.walletconnect.usecase.method.*
|
||||
|
|
@ -82,7 +83,7 @@ internal class WcEthSignTransactionUseCase @AssistedInject constructor(
|
|||
val hash = prepareForSend(state.signModel, wallet, network)
|
||||
.map { it.toHexString().formatHex() }
|
||||
.onLeft { error ->
|
||||
emit(state.toResult(error.left()))
|
||||
emit(state.toResult(parseSendError(error).left()))
|
||||
}
|
||||
.getOrNull()
|
||||
?: return
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import com.tangem.data.walletconnect.sign.SignStateConverter.toResult
|
|||
import com.tangem.data.walletconnect.sign.WcMethodUseCaseContext
|
||||
import com.tangem.data.walletconnect.utils.BlockAidVerificationDelegate
|
||||
import com.tangem.domain.transaction.usecase.SignUseCase
|
||||
import com.tangem.domain.walletconnect.error.parseTangemSdkError
|
||||
import com.tangem.domain.walletconnect.model.WcEthMethod
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcMessageSignUseCase
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcSignState
|
||||
|
|
@ -51,7 +52,7 @@ internal class WcEthSignTypedDataUseCase @AssistedInject constructor(
|
|||
?: return
|
||||
|
||||
val signedHash = signUseCase(hashToSign, userWallet, network)
|
||||
.onLeft { emit(state.toResult(it.left())) }
|
||||
.onLeft { emit(state.toResult(parseTangemSdkError(it).left())) }
|
||||
.getOrNull() ?: return
|
||||
|
||||
val respond = prepareToSendMessageData(signedHash, hashToSign, walletManager)
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.tangem.data.walletconnect.sign.SignStateConverter.toResult
|
|||
import com.tangem.data.walletconnect.sign.WcMethodUseCaseContext
|
||||
import com.tangem.domain.core.lce.LceFlow
|
||||
import com.tangem.domain.transaction.usecase.SignUseCase
|
||||
import com.tangem.domain.walletconnect.error.parseTangemSdkError
|
||||
import com.tangem.domain.walletconnect.model.WcSolanaMethod
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcMessageSignUseCase
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcSignState
|
||||
|
|
@ -40,7 +41,7 @@ internal class WcSolanaMessageSignUseCase @AssistedInject constructor(
|
|||
val userWallet = session.wallet
|
||||
|
||||
val signedHash = signUseCase(hashToSign, userWallet, network)
|
||||
.onLeft { emit(state.toResult(it.left())) }
|
||||
.onLeft { emit(state.toResult(parseTangemSdkError(it).left())) }
|
||||
.getOrNull() ?: return
|
||||
|
||||
val respond = "{ signature: \"${signedHash.encodeBase58()}\" }"
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import com.tangem.data.walletconnect.sign.SignStateConverter.toResult
|
|||
import com.tangem.data.walletconnect.sign.WcMethodUseCaseContext
|
||||
import com.tangem.data.walletconnect.utils.BlockAidVerificationDelegate
|
||||
import com.tangem.domain.transaction.usecase.PrepareForSendUseCase
|
||||
import com.tangem.domain.walletconnect.error.parseSendError
|
||||
import com.tangem.domain.walletconnect.model.WcSolanaMethod
|
||||
import com.tangem.domain.walletconnect.usecase.method.BlockAidTransactionCheck
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcListTransactionUseCase
|
||||
|
|
@ -47,7 +48,7 @@ internal class WcSolanaSignAllTransactionUseCase @AssistedInject constructor(
|
|||
override suspend fun SignCollector<List<TransactionData>>.onSign(state: WcSignState<List<TransactionData>>) {
|
||||
val hash = prepareForSend.invoke(transactionData = state.signModel, userWallet = wallet, network = network)
|
||||
.onLeft { error ->
|
||||
emit(state.toResult(error.left()))
|
||||
emit(state.toResult(parseSendError(error).left()))
|
||||
}
|
||||
.getOrNull()
|
||||
?: return
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import com.tangem.data.walletconnect.sign.SignStateConverter.toResult
|
|||
import com.tangem.data.walletconnect.sign.WcMethodUseCaseContext
|
||||
import com.tangem.data.walletconnect.utils.BlockAidVerificationDelegate
|
||||
import com.tangem.domain.transaction.usecase.PrepareForSendUseCase
|
||||
import com.tangem.domain.walletconnect.error.parseSendError
|
||||
import com.tangem.domain.walletconnect.model.WcSolanaMethod
|
||||
import com.tangem.domain.walletconnect.usecase.method.BlockAidTransactionCheck
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcSignState
|
||||
|
|
@ -45,7 +46,7 @@ internal class WcSolanaSignTransactionUseCase @AssistedInject constructor(
|
|||
override suspend fun SignCollector<TransactionData>.onSign(state: WcSignState<TransactionData>) {
|
||||
val hash = prepareForSend.invoke(transactionData = state.signModel, userWallet = wallet, network = network)
|
||||
.onLeft { error ->
|
||||
emit(state.toResult(error.left()))
|
||||
emit(state.toResult(parseSendError(error).left()))
|
||||
}
|
||||
.getOrNull()
|
||||
?: return
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import arrow.core.right
|
|||
import com.reown.walletkit.client.Wallet
|
||||
import com.reown.walletkit.client.WalletKit
|
||||
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.suspendCancellableCoroutine
|
||||
import timber.log.Timber
|
||||
|
|
@ -13,7 +14,7 @@ import kotlin.coroutines.resume
|
|||
|
||||
internal class DefaultWcRespondService : WcRespondService {
|
||||
|
||||
override suspend fun respond(request: WcSdkSessionRequest, response: String): Either<Throwable, Unit> =
|
||||
override suspend fun respond(request: WcSdkSessionRequest, response: String): Either<WcRequestError, String> =
|
||||
suspendCancellableCoroutine { continuation ->
|
||||
WalletKit.respondSessionRequest(
|
||||
params = Wallet.Params.SessionRequestResponse(
|
||||
|
|
@ -26,12 +27,19 @@ internal class DefaultWcRespondService : WcRespondService {
|
|||
onSuccess = {
|
||||
if (continuation.isCompleted) return@respondSessionRequest
|
||||
Timber.tag(WC_TAG).i("Successful respond for request $request")
|
||||
continuation.resume(Unit.right())
|
||||
val result = when (val response = it.jsonRpcResponse) {
|
||||
is Wallet.Model.JsonRpcResponse.JsonRpcError -> WcRequestError.WcRespondError(
|
||||
code = response.code,
|
||||
message = response.message,
|
||||
).left()
|
||||
is Wallet.Model.JsonRpcResponse.JsonRpcResult -> response.result.right()
|
||||
}
|
||||
continuation.resume(result)
|
||||
},
|
||||
onError = {
|
||||
if (continuation.isCompleted) return@respondSessionRequest
|
||||
Timber.tag(WC_TAG).e(it.throwable, "Failed respond for request $request")
|
||||
continuation.resume(it.throwable.left())
|
||||
continuation.resume(WcRequestError.UnknownError(it.throwable).left())
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
package com.tangem.data.walletconnect.respond
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.domain.walletconnect.model.WcRequestError
|
||||
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
|
||||
|
||||
interface WcRespondService {
|
||||
suspend fun respond(request: WcSdkSessionRequest, response: String): Either<Throwable, Unit>
|
||||
suspend fun respond(request: WcSdkSessionRequest, response: String): Either<WcRequestError, String>
|
||||
fun rejectRequestNonBlock(request: WcSdkSessionRequest, message: String = "")
|
||||
}
|
||||
|
|
@ -1,16 +1,12 @@
|
|||
package com.tangem.data.walletconnect.sign
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.domain.walletconnect.model.WcRequestError
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcSignState
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcSignStep
|
||||
|
||||
object SignStateConverter {
|
||||
|
||||
internal fun <M> preSign(signModel: M) = WcSignState(signModel, WcSignStep.PreSign)
|
||||
internal fun <M> signing(signModel: M) = WcSignState(signModel, WcSignStep.Signing)
|
||||
internal fun <M> result(result: Either<Throwable, Unit>, signModel: M) =
|
||||
WcSignState(signModel, WcSignStep.Result(result))
|
||||
|
||||
internal fun <M> WcSignState<M>.toPreSign(signModel: M = this.signModel) = copy(
|
||||
signModel = signModel,
|
||||
domainStep = WcSignStep.PreSign,
|
||||
|
|
@ -21,8 +17,9 @@ object SignStateConverter {
|
|||
signModel = signModel,
|
||||
)
|
||||
|
||||
internal fun <M> WcSignState<M>.toResult(result: Either<Throwable, Unit>, signModel: M = this.signModel) = copy(
|
||||
domainStep = WcSignStep.Result(result),
|
||||
signModel = signModel,
|
||||
)
|
||||
internal fun <M> WcSignState<M>.toResult(result: Either<WcRequestError, String>, signModel: M = this.signModel) =
|
||||
copy(
|
||||
domainStep = WcSignStep.Result(result),
|
||||
signModel = signModel,
|
||||
)
|
||||
}
|
||||
|
|
@ -6,6 +6,8 @@ import com.tangem.data.walletconnect.sign.SignStateConverter.toPreSign
|
|||
import com.tangem.data.walletconnect.sign.SignStateConverter.toResult
|
||||
import com.tangem.data.walletconnect.sign.SignStateConverter.toSigning
|
||||
import com.tangem.domain.walletconnect.WcAnalyticEvents
|
||||
import com.tangem.domain.walletconnect.model.WcRequestError
|
||||
import com.tangem.domain.walletconnect.model.WcRequestError.Companion.code
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcSignState
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcSignStep
|
||||
import kotlinx.coroutines.Job
|
||||
|
|
@ -62,18 +64,19 @@ internal class WcSignUseCaseDelegate<MiddleAction, SignModel>(
|
|||
fun signFlow() = flow { onSign(state.updateAndGet { it.toSigning() }) }
|
||||
.onEach { newState -> state.update { newState } }
|
||||
.catch { exception ->
|
||||
val errorResult = state.value.toResult(exception.left())
|
||||
val errorResult = state.value
|
||||
.toResult(WcRequestError.UnknownError(exception).left())
|
||||
state.update { errorResult }
|
||||
}
|
||||
.onEach { state ->
|
||||
val step = state.domainStep as? WcSignStep.Result ?: return@onEach
|
||||
val event = step.result.fold(
|
||||
ifLeft = {
|
||||
ifLeft = { error ->
|
||||
WcAnalyticEvents.SignatureRequestFailed(
|
||||
session = context.session,
|
||||
rawRequest = context.rawSdkRequest,
|
||||
network = context.network,
|
||||
it.message.orEmpty(),
|
||||
errorCode = error.code() ?: error::class.simpleName.orEmpty(),
|
||||
)
|
||||
},
|
||||
ifRight = {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import com.tangem.core.analytics.api.AnalyticsEventHandler
|
|||
import com.tangem.data.walletconnect.sign.*
|
||||
import com.tangem.data.walletconnect.sign.SignStateConverter.toResult
|
||||
import com.tangem.data.walletconnect.sign.SignStateConverter.toSigning
|
||||
import com.tangem.domain.walletconnect.model.WcRequestError
|
||||
import com.tangem.domain.walletconnect.model.WcSession
|
||||
import com.tangem.domain.walletconnect.model.sdkcopy.WcAppMetaData
|
||||
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSession
|
||||
|
|
@ -32,6 +33,7 @@ internal class WcSignUseCaseDelegateTest {
|
|||
object : FinalActionCollector<TestSignModel> {}
|
||||
private val initSignModel = TestSignModel()
|
||||
private val analytics: AnalyticsEventHandler = mockk<AnalyticsEventHandler>(relaxed = true)
|
||||
private val simpleResult = "hex".right()
|
||||
private val rawRequestMock = WcSdkSessionRequest(
|
||||
topic = "",
|
||||
chainId = "",
|
||||
|
|
@ -64,14 +66,14 @@ internal class WcSignUseCaseDelegateTest {
|
|||
|
||||
private val initState = WcSignState(initSignModel, WcSignStep.PreSign)
|
||||
private val signing = initState.toSigning()
|
||||
private val result = signing.toResult(Unit.right())
|
||||
private val testException = RuntimeException("test")
|
||||
private val result = signing.toResult(simpleResult)
|
||||
private val testException = WcRequestError.UnknownError(RuntimeException("test"))
|
||||
|
||||
private val successSign: suspend FlowCollector<WcSignState<TestSignModel>>.(
|
||||
currentState: WcSignState<TestSignModel>,
|
||||
) -> Unit = { state ->
|
||||
delay(2)
|
||||
emit(state.toResult(Unit.right()))
|
||||
emit(state.toResult(simpleResult))
|
||||
}
|
||||
|
||||
private val failedSign: suspend FlowCollector<WcSignState<TestSignModel>>.(
|
||||
|
|
@ -161,8 +163,9 @@ internal class WcSignUseCaseDelegateTest {
|
|||
|
||||
@Test
|
||||
fun `failed sign and catch unknown exception`() = runTest {
|
||||
val exception = RuntimeException("asd")
|
||||
val expectedErrorState = signing.toResult(exception.left())
|
||||
val exception = RuntimeException("test")
|
||||
val testException = WcRequestError.UnknownError(exception)
|
||||
val expectedErrorState = signing.toResult(testException.left())
|
||||
finalActionCollector = object : FinalActionCollector<TestSignModel> {
|
||||
override suspend fun SignCollector<TestSignModel>.onSign(state: WcSignState<TestSignModel>) {
|
||||
delay(2)
|
||||
|
|
|
|||
|
|
@ -101,12 +101,12 @@ interface TransactionRepository {
|
|||
signer: TransactionSigner,
|
||||
userWalletId: UserWalletId,
|
||||
network: Network,
|
||||
): Result<ByteArray>
|
||||
): com.tangem.blockchain.extensions.Result<ByteArray>
|
||||
|
||||
suspend fun prepareForSendMultiple(
|
||||
transactionData: List<TransactionData>,
|
||||
signer: TransactionSigner,
|
||||
userWalletId: UserWalletId,
|
||||
network: Network,
|
||||
): Result<List<ByteArray>>
|
||||
): com.tangem.blockchain.extensions.Result<List<ByteArray>>
|
||||
}
|
||||
|
|
@ -5,11 +5,13 @@ import arrow.core.left
|
|||
import arrow.core.right
|
||||
import com.tangem.blockchain.common.TransactionData
|
||||
import com.tangem.blockchain.common.TransactionSigner
|
||||
import com.tangem.blockchain.extensions.Result
|
||||
import com.tangem.domain.card.models.TwinKey
|
||||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.domain.common.TapWorkarounds.isTangemTwins
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.transaction.TransactionRepository
|
||||
import com.tangem.domain.transaction.error.SendTransactionError
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
|
||||
|
|
@ -21,30 +23,36 @@ class PrepareForSendUseCase(
|
|||
transactionData: TransactionData,
|
||||
userWallet: UserWallet,
|
||||
network: Network,
|
||||
): Either<Throwable, ByteArray> {
|
||||
): Either<SendTransactionError, ByteArray> {
|
||||
val signer = createSigner(userWallet)
|
||||
return transactionRepository.prepareForSend(
|
||||
val result = transactionRepository.prepareForSend(
|
||||
transactionData = transactionData,
|
||||
userWalletId = userWallet.walletId,
|
||||
network = network,
|
||||
signer = signer,
|
||||
)
|
||||
.fold(onSuccess = { it.right() }, onFailure = { it.left() })
|
||||
return when (result) {
|
||||
is Result.Failure -> SendTransactionUseCase.handleError(result).left()
|
||||
is Result.Success -> result.data.right()
|
||||
}
|
||||
}
|
||||
|
||||
suspend operator fun invoke(
|
||||
transactionData: List<TransactionData>,
|
||||
userWallet: UserWallet,
|
||||
network: Network,
|
||||
): Either<Throwable, List<ByteArray>> {
|
||||
): Either<SendTransactionError, List<ByteArray>> {
|
||||
val signer = createSigner(userWallet)
|
||||
return transactionRepository.prepareForSendMultiple(
|
||||
val result = transactionRepository.prepareForSendMultiple(
|
||||
transactionData = transactionData,
|
||||
userWalletId = userWallet.walletId,
|
||||
network = network,
|
||||
signer = signer,
|
||||
)
|
||||
.fold(onSuccess = { it.right() }, onFailure = { it.left() })
|
||||
return when (result) {
|
||||
is Result.Failure -> SendTransactionUseCase.handleError(result).left()
|
||||
is Result.Success -> result.data.right()
|
||||
}
|
||||
}
|
||||
|
||||
private fun createSigner(userWallet: UserWallet): TransactionSigner {
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ class SendTransactionUseCase(
|
|||
userWallet: UserWallet,
|
||||
network: Network,
|
||||
sendMode: TransactionSender.MultipleTransactionSendMode,
|
||||
): Either<SendTransactionError?, List<String>> {
|
||||
): Either<SendTransactionError, List<String>> {
|
||||
userWallet.requireColdWallet() // TODO [REDACTED_TASK_KEY]
|
||||
|
||||
val card = userWallet.scanResponse.card
|
||||
|
|
@ -101,7 +101,7 @@ class SendTransactionUseCase(
|
|||
txData: TransactionData,
|
||||
userWallet: UserWallet,
|
||||
network: Network,
|
||||
): Either<SendTransactionError?, String> {
|
||||
): Either<SendTransactionError, String> {
|
||||
return invoke(listOf(txData), userWallet, network, TransactionSender.MultipleTransactionSendMode.DEFAULT)
|
||||
.map { it.first() }
|
||||
}
|
||||
|
|
@ -127,27 +127,29 @@ class SendTransactionUseCase(
|
|||
}
|
||||
}
|
||||
|
||||
private fun handleError(result: Result.Failure): SendTransactionError {
|
||||
if (ResultChecker.isNetworkError(result)) {
|
||||
return SendTransactionError.NetworkError(
|
||||
code = result.error.message,
|
||||
message = result.error.customMessage,
|
||||
)
|
||||
}
|
||||
val error = result.error as? BlockchainSdkError ?: return SendTransactionError.UnknownError()
|
||||
return when (error) {
|
||||
is BlockchainSdkError.WrappedTangemError -> parseWrappedError(error)
|
||||
is BlockchainSdkError.CreateAccountUnderfunded -> {
|
||||
val minAmount = error.minReserve
|
||||
val minValue = minAmount.value?.format { simple(minAmount.decimals) }.orEmpty()
|
||||
SendTransactionError.CreateAccountUnderfunded(minValue)
|
||||
}
|
||||
else -> {
|
||||
SendTransactionError.BlockchainSdkError(
|
||||
code = error.code,
|
||||
message = error.customMessage,
|
||||
companion object {
|
||||
internal fun handleError(result: Result.Failure): SendTransactionError {
|
||||
if (ResultChecker.isNetworkError(result)) {
|
||||
return SendTransactionError.NetworkError(
|
||||
code = result.error.message,
|
||||
message = result.error.customMessage,
|
||||
)
|
||||
}
|
||||
val error = result.error as? BlockchainSdkError ?: return SendTransactionError.UnknownError()
|
||||
return when (error) {
|
||||
is BlockchainSdkError.WrappedTangemError -> parseWrappedError(error)
|
||||
is BlockchainSdkError.CreateAccountUnderfunded -> {
|
||||
val minAmount = error.minReserve
|
||||
val minValue = minAmount.value?.format { simple(minAmount.decimals) }.orEmpty()
|
||||
SendTransactionError.CreateAccountUnderfunded(minValue)
|
||||
}
|
||||
else -> {
|
||||
SendTransactionError.BlockchainSdkError(
|
||||
code = error.code,
|
||||
message = error.customMessage,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -16,6 +16,8 @@ dependencies {
|
|||
implementation(projects.domain.tokens.models)
|
||||
implementation(projects.domain.wallets.models)
|
||||
implementation(projects.domain.walletConnect.models)
|
||||
implementation(projects.domain.transaction)
|
||||
implementation(projects.domain.transaction.models)
|
||||
|
||||
/* Project - Core */
|
||||
implementation(projects.core.analytics)
|
||||
|
|
@ -25,4 +27,5 @@ dependencies {
|
|||
|
||||
/* Tangem libraries */
|
||||
implementation(tangemDeps.blockchain)
|
||||
implementation(tangemDeps.card.core)
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@ dependencies {
|
|||
implementation(projects.domain.wallets.models)
|
||||
implementation(projects.domain.tokens.models)
|
||||
implementation(projects.domain.blockaid.models)
|
||||
implementation(projects.domain.transaction.models)
|
||||
|
||||
/* Other */
|
||||
implementation(deps.moshi)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
package com.tangem.domain.walletconnect.model
|
||||
|
||||
import com.tangem.domain.transaction.error.SendTransactionError
|
||||
|
||||
sealed class WcRequestError {
|
||||
|
||||
data class WrappedSendError(
|
||||
val sendTransactionError: SendTransactionError,
|
||||
) : WcRequestError()
|
||||
|
||||
data class WcRespondError(
|
||||
val code: Int,
|
||||
val message: String,
|
||||
) : WcRequestError()
|
||||
|
||||
data class UnknownError(val ex: Throwable? = null) : WcRequestError()
|
||||
|
||||
companion object {
|
||||
|
||||
fun WcRequestError.message(): String? = when (this) {
|
||||
is UnknownError -> ex?.message
|
||||
is WcRespondError -> message
|
||||
is WrappedSendError -> sendTransactionError.message()
|
||||
}
|
||||
|
||||
fun WcRequestError.code(): String? = when (this) {
|
||||
is UnknownError -> null
|
||||
is WcRespondError -> this.code.toString()
|
||||
is WrappedSendError -> sendTransactionError.code()
|
||||
}
|
||||
|
||||
private fun SendTransactionError.code(): String? = when (this) {
|
||||
is SendTransactionError.BlockchainSdkError -> code.toString()
|
||||
is SendTransactionError.NetworkError -> code
|
||||
is SendTransactionError.TangemSdkError -> code.toString()
|
||||
is SendTransactionError.DataError,
|
||||
SendTransactionError.DemoCardError,
|
||||
is SendTransactionError.UnknownError,
|
||||
SendTransactionError.UserCancelledError,
|
||||
is SendTransactionError.CreateAccountUnderfunded,
|
||||
-> null
|
||||
}
|
||||
|
||||
private fun SendTransactionError.message(): String? = when (this) {
|
||||
is SendTransactionError.BlockchainSdkError -> message
|
||||
is SendTransactionError.NetworkError -> message
|
||||
is SendTransactionError.DataError -> message
|
||||
is SendTransactionError.UnknownError -> ex?.message
|
||||
is SendTransactionError.TangemSdkError,
|
||||
SendTransactionError.DemoCardError,
|
||||
SendTransactionError.UserCancelledError,
|
||||
is SendTransactionError.CreateAccountUnderfunded,
|
||||
-> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package com.tangem.domain.walletconnect.error
|
||||
|
||||
import com.tangem.blockchain.common.BlockchainSdkError
|
||||
import com.tangem.common.core.TangemError
|
||||
import com.tangem.domain.transaction.error.SendTransactionError
|
||||
import com.tangem.domain.transaction.error.parseWrappedError
|
||||
import com.tangem.domain.walletconnect.model.WcRequestError
|
||||
|
||||
fun parseSendError(error: SendTransactionError): WcRequestError.WrappedSendError {
|
||||
return WcRequestError.WrappedSendError(error)
|
||||
}
|
||||
|
||||
fun parseTangemSdkError(error: TangemError): WcRequestError.WrappedSendError {
|
||||
val sendError = parseWrappedError(BlockchainSdkError.WrappedTangemError(error))
|
||||
return parseSendError(sendError)
|
||||
}
|
||||
|
|
@ -1,11 +1,12 @@
|
|||
package com.tangem.domain.walletconnect.usecase.method
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.domain.walletconnect.model.WcRequestError
|
||||
|
||||
interface WcAddNetworkUseCase :
|
||||
WcMethodUseCase,
|
||||
WcMethodContext {
|
||||
|
||||
suspend fun approve(): Either<Throwable, Unit>
|
||||
suspend fun approve(): Either<WcRequestError, String>
|
||||
fun reject()
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ package com.tangem.domain.walletconnect.usecase.method
|
|||
import arrow.core.Either
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.walletconnect.model.WcMethod
|
||||
import com.tangem.domain.walletconnect.model.WcRequestError
|
||||
import com.tangem.domain.walletconnect.model.WcSession
|
||||
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
|
|
@ -38,5 +39,5 @@ data class WcSignState<SignModel>(
|
|||
sealed interface WcSignStep {
|
||||
data object PreSign : WcSignStep
|
||||
data object Signing : WcSignStep
|
||||
data class Result(val result: Either<Throwable, Unit>) : WcSignStep
|
||||
data class Result(val result: Either<WcRequestError, String>) : WcSignStep
|
||||
}
|
||||
|
|
@ -22,6 +22,8 @@ import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
|||
import com.tangem.domain.transaction.error.GetFeeError
|
||||
import com.tangem.domain.transaction.usecase.GetFeeUseCase
|
||||
import com.tangem.domain.walletconnect.WcRequestUseCaseFactory
|
||||
import com.tangem.domain.walletconnect.model.WcRequestError
|
||||
import com.tangem.domain.walletconnect.model.WcRequestError.Companion.message
|
||||
import com.tangem.domain.walletconnect.usecase.method.*
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.features.send.v2.api.callbacks.FeeSelectorModelCallback
|
||||
|
|
@ -252,10 +254,10 @@ internal class WcSendTransactionModel @Inject constructor(
|
|||
return false
|
||||
}
|
||||
|
||||
private fun handleSigningError(result: Either<Throwable, Unit>, useCase: WcSignUseCase<*>) {
|
||||
private fun handleSigningError(result: Either<WcRequestError, String>, useCase: WcSignUseCase<*>) {
|
||||
if (result.isLeft()) {
|
||||
val error = WcTransactionRoutes.Alert.Type.UnknownError(
|
||||
errorMessage = result.leftOrNull()?.message,
|
||||
errorMessage = result.leftOrNull()?.message(),
|
||||
onDismiss = { cancel(useCase) },
|
||||
)
|
||||
stackNavigation.pushNew(WcTransactionRoutes.Alert(error))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue