Updated on 2026-08-14

This commit is contained in:
Tangem 2025-07-02 17:40:59 +04:00
parent 07c4b49e53
commit 16a190cbe7
9 changed files with 42 additions and 17 deletions

View file

@ -9,7 +9,7 @@ data class SolanaTransactionScanRequest(
@Json(name = "encoding") val encoding: String = "base64",
@Json(name = "chain") val chain: String,
@Json(name = "method") val method: String,
@Json(name = "options") val options: List<String> = listOf("simulation, validation"),
@Json(name = "options") val options: List<String> = listOf("simulation", "validation"),
@Json(name = "metadata") val metadata: TransactionMetadata,
@Json(name = "account_address") val accountAddress: String,
@Json(name = "transactions") val transactions: List<String>,

View file

@ -31,7 +31,6 @@ import com.tangem.domain.walletconnect.usecase.initialize.WcInitializeUseCase
import com.tangem.domain.walletconnect.usecase.pair.WcPairUseCase
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
import com.tangem.lib.crypto.UserWalletManager
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.Module
import dagger.Provides
@ -145,13 +144,13 @@ internal object WalletConnectDataModule {
namespaceConverter: WcSolanaNetwork.NamespaceConverter,
sessionsManager: WcSessionsManager,
factories: WcSolanaNetwork.Factories,
walletManager: UserWalletManager,
walletManagersFacade: WalletManagersFacade,
): WcSolanaNetwork = WcSolanaNetwork(
moshi = moshi,
sessionsManager = sessionsManager,
factories = factories,
namespaceConverter = namespaceConverter,
walletManager = walletManager,
walletManagersFacade = walletManagersFacade,
)
@Provides

View file

@ -0,0 +1,18 @@
package com.tangem.data.walletconnect.network.solana
import com.tangem.blockchain.extensions.decodeBase58
import com.tangem.data.walletconnect.utils.WC_TAG
import com.tangem.blockchain.extensions.encodeBase64NoWrap
import com.tangem.utils.converter.Converter
import timber.log.Timber
import javax.inject.Inject
internal class SolanaBlockAidAddressConverter @Inject constructor() : Converter<String, String?> {
override fun convert(value: String): String? {
return value.decodeBase58()?.encodeBase64NoWrap() ?: run {
Timber.tag(WC_TAG).e("Error while converting Solana transaction account address")
null
}
}
}

View file

@ -13,12 +13,13 @@ import com.tangem.data.walletconnect.request.WcRequestToUseCaseConverter.Compani
import com.tangem.data.walletconnect.sign.WcMethodUseCaseContext
import com.tangem.data.walletconnect.utils.WcNamespaceConverter
import com.tangem.domain.models.network.Network
import com.tangem.domain.walletconnect.model.WcSession
import com.tangem.domain.walletconnect.model.WcSolanaMethod
import com.tangem.domain.walletconnect.model.WcSolanaMethodName
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
import com.tangem.domain.walletconnect.repository.WcSessionsManager
import com.tangem.domain.walletconnect.usecase.method.WcMethodUseCase
import com.tangem.lib.crypto.UserWalletManager
import com.tangem.domain.walletmanager.WalletManagersFacade
import jakarta.inject.Inject
import timber.log.Timber
@ -27,7 +28,7 @@ internal class WcSolanaNetwork(
private val sessionsManager: WcSessionsManager,
private val factories: Factories,
private val namespaceConverter: NamespaceConverter,
private val walletManager: UserWalletManager,
private val walletManagersFacade: WalletManagersFacade,
) : WcRequestToUseCaseConverter {
override fun toWcMethodName(request: WcSdkSessionRequest): WcSolanaMethodName? {
@ -41,7 +42,7 @@ internal class WcSolanaNetwork(
val method: WcSolanaMethod = name.toMethod(request) ?: return null
val session = sessionsManager.findSessionByTopic(request.topic) ?: return null
val network = namespaceConverter.toNetwork(request.chainId.orEmpty(), session.wallet) ?: return null
val accountAddress = getAccountAddress(network)
val accountAddress = getAccountAddress(session, network)
val context = WcMethodUseCaseContext(
session = session,
rawSdkRequest = request,
@ -55,9 +56,9 @@ internal class WcSolanaNetwork(
}
}
private suspend fun getAccountAddress(network: Network): String? {
private suspend fun getAccountAddress(session: WcSession, network: Network): String? {
return try {
walletManager.getWalletAddress(network.rawId, network.derivationPath.value)
walletManagersFacade.getDefaultAddress(session.wallet.walletId, network)
} catch (exception: Exception) {
Timber.e(exception)
null

View file

@ -24,6 +24,7 @@ import okio.ByteString.Companion.decodeBase64
import org.json.JSONArray
import org.json.JSONObject
@Suppress("LongParameterList")
internal class WcSolanaSignAllTransactionUseCase @AssistedInject constructor(
override val respondService: WcRespondService,
override val analytics: AnalyticsEventHandler,
@ -31,6 +32,7 @@ internal class WcSolanaSignAllTransactionUseCase @AssistedInject constructor(
@Assisted override val context: WcMethodUseCaseContext,
@Assisted override val method: WcSolanaMethod.SignAllTransaction,
blockAidDelegate: BlockAidVerificationDelegate,
addressConverter: SolanaBlockAidAddressConverter,
) : BaseWcSignUseCase<Nothing, List<TransactionData>>(),
WcListTransactionUseCase {
@ -39,7 +41,7 @@ internal class WcSolanaSignAllTransactionUseCase @AssistedInject constructor(
method = method,
rawSdkRequest = rawSdkRequest,
session = session,
accountAddress = context.accountAddress,
accountAddress = addressConverter.convert(context.accountAddress),
).map { lce -> lce.map { result -> BlockAidTransactionCheck.Result.Plain(result) } }
override suspend fun SignCollector<List<TransactionData>>.onSign(state: WcSignState<List<TransactionData>>) {

View file

@ -22,6 +22,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import okio.ByteString.Companion.decodeBase64
@Suppress("LongParameterList")
internal class WcSolanaSignTransactionUseCase @AssistedInject constructor(
override val respondService: WcRespondService,
override val analytics: AnalyticsEventHandler,
@ -29,6 +30,7 @@ internal class WcSolanaSignTransactionUseCase @AssistedInject constructor(
@Assisted override val context: WcMethodUseCaseContext,
@Assisted override val method: WcSolanaMethod.SignTransaction,
blockAidDelegate: BlockAidVerificationDelegate,
addressConverter: SolanaBlockAidAddressConverter,
) : BaseWcSignUseCase<Nothing, TransactionData>(),
WcTransactionUseCase {
@ -37,7 +39,7 @@ internal class WcSolanaSignTransactionUseCase @AssistedInject constructor(
method = method,
rawSdkRequest = rawSdkRequest,
session = session,
accountAddress = context.accountAddress,
accountAddress = addressConverter.convert(context.accountAddress),
).map { lce -> lce.map { result -> BlockAidTransactionCheck.Result.Plain(result) } }
override suspend fun SignCollector<TransactionData>.onSign(state: WcSignState<TransactionData>) {

View file

@ -48,11 +48,14 @@ internal class WcSendTransactionComponent(
@Composable
override fun BottomSheet() {
val content by model.uiState.collectAsStateWithLifecycle()
val state = content?.transaction
if (content != null) {
if (state != null) {
val feeSelectorBlock =
if (state.feeState !is WcTransactionFeeState.None) feeSelectorBlockComponent else null
WcSendTransactionModalBottomSheet(
state = content!!.transaction,
feeSelectorBlockComponent = feeSelectorBlockComponent,
state = state,
feeSelectorBlockComponent = feeSelectorBlock,
onClickTransactionRequest = model::showTransactionRequest,
onBack = router::pop,
onDismiss = ::dismiss,

View file

@ -23,7 +23,7 @@ internal fun WcSendTransactionItems(
walletName: String,
networkInfo: WcNetworkInfoUM,
feeState: WcTransactionFeeState,
feeSelectorBlockComponent: FeeSelectorBlockComponent,
feeSelectorBlockComponent: FeeSelectorBlockComponent?,
modifier: Modifier = Modifier,
address: String? = null,
) {
@ -63,7 +63,7 @@ internal fun WcSendTransactionItems(
}
DividerWithPadding(start = 40.dp, end = 12.dp)
if (feeState != WcTransactionFeeState.None) {
feeSelectorBlockComponent.Content(
feeSelectorBlockComponent?.Content(
modifier = if (onFeeBlockClicked != null) {
Modifier.clickableSingle(onClick = onFeeBlockClicked)
} else {

View file

@ -47,7 +47,7 @@ import kotlinx.collections.immutable.persistentListOf
@Composable
internal fun WcSendTransactionModalBottomSheet(
state: WcSendTransactionItemUM,
feeSelectorBlockComponent: FeeSelectorBlockComponent,
feeSelectorBlockComponent: FeeSelectorBlockComponent?,
onClickTransactionRequest: () -> Unit,
onBack: () -> Unit,
onDismiss: () -> Unit,