diff --git a/app/src/main/java/com/tangem/tap/features/main/MainViewModel.kt b/app/src/main/java/com/tangem/tap/features/main/MainViewModel.kt index 832de3675c..22b4dd8a31 100644 --- a/app/src/main/java/com/tangem/tap/features/main/MainViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/main/MainViewModel.kt @@ -41,6 +41,7 @@ import com.tangem.domain.settings.IncrementAppLaunchCounterUseCase import com.tangem.domain.settings.usercountry.FetchUserCountryUseCase import com.tangem.domain.staking.FetchStakingTokensUseCase import com.tangem.domain.wallets.legacy.UserWalletsListManager +import com.tangem.domain.wallets.models.UserWallet import com.tangem.domain.wallets.models.requireColdWallet import com.tangem.domain.wallets.usecase.AssociateWalletsWithApplicationIdUseCase import com.tangem.domain.wallets.usecase.GetSavedWalletChangesUseCase @@ -200,7 +201,12 @@ internal class MainViewModel @Inject constructor( userWalletsListManager.selectedUserWallet .distinctUntilChanged() .onEach { userWallet -> - Analytics.setContext(userWallet.requireColdWallet().scanResponse) // TODO [REDACTED_TASK_KEY] + when (userWallet) { + is UserWallet.Cold -> Analytics.setContext(userWallet.scanResponse) + is UserWallet.Hot -> { + // TODO [REDACTED_TASK_KEY] + } + } } .flowOn(dispatchers.io) .launchIn(viewModelScope) diff --git a/app/src/main/java/com/tangem/tap/network/auth/DefaultAuthProvider.kt b/app/src/main/java/com/tangem/tap/network/auth/DefaultAuthProvider.kt index 2820d0ed44..e56bec1fd1 100644 --- a/app/src/main/java/com/tangem/tap/network/auth/DefaultAuthProvider.kt +++ b/app/src/main/java/com/tangem/tap/network/auth/DefaultAuthProvider.kt @@ -9,13 +9,23 @@ import com.tangem.domain.wallets.models.requireColdWallet internal class DefaultAuthProvider(private val userWalletsListManager: UserWalletsListManager) : AuthProvider { override fun getCardPublicKey(): String { - return userWalletsListManager.selectedUserWalletSync - ?.requireColdWallet()?.scanResponse?.card?.cardPublicKey?.toHexString() ?: "" + val userWallet = userWalletsListManager.selectedUserWalletSync + + return when (userWallet) { + is UserWallet.Cold -> userWallet.scanResponse.card.cardPublicKey.toHexString() + is UserWallet.Hot -> userWallet.wallets?.firstOrNull()?.publicKey?.toHexString() ?: "" + null -> "" + } } override fun getCardId(): String { - return userWalletsListManager.selectedUserWalletSync - ?.requireColdWallet()?.scanResponse?.card?.cardId ?: "" + val userWallet = userWalletsListManager.selectedUserWalletSync + + if (userWallet !is UserWallet.Cold) { + return "" + } + + return userWallet.requireColdWallet().scanResponse.card.cardId } override fun getCardsPublicKeys(): Map { diff --git a/domain/legacy/src/main/java/com/tangem/domain/common/extensions/WalletManagerFactory.kt b/domain/legacy/src/main/java/com/tangem/domain/common/extensions/WalletManagerFactory.kt index 8eaadd231c..cdf757a38a 100644 --- a/domain/legacy/src/main/java/com/tangem/domain/common/extensions/WalletManagerFactory.kt +++ b/domain/legacy/src/main/java/com/tangem/domain/common/extensions/WalletManagerFactory.kt @@ -74,7 +74,7 @@ fun WalletManagerFactory.makeWalletManagerForApp( } } -private fun makePublicKey( +fun makePublicKey( seedKey: ByteArray, blockchain: Blockchain, derivationPath: DerivationPath, diff --git a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/DefaultWalletManagersFacade.kt b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/DefaultWalletManagersFacade.kt index ebbb56ce04..91d56ba37a 100644 --- a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/DefaultWalletManagersFacade.kt +++ b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/DefaultWalletManagersFacade.kt @@ -41,7 +41,6 @@ import com.tangem.domain.walletmanager.utils.* import com.tangem.domain.walletmanager.utils.WalletManagerFactory import com.tangem.domain.wallets.models.UserWallet import com.tangem.domain.wallets.models.UserWalletId -import com.tangem.domain.wallets.models.requireColdWallet import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.sync.Mutex @@ -371,21 +370,31 @@ class DefaultWalletManagersFacade( initMutex.withLock { val userWallet = getUserWallet(userWalletId) - userWallet.requireColdWallet() // TODO [REDACTED_TASK_KEY] - var walletManager = walletManagersStore.getSyncOrNull( userWalletId = userWalletId, blockchain = blockchain, derivationPath = derivationPath, ) - if (walletManager == null) { - walletManager = walletManagerFactory.createWalletManager( - scanResponse = userWallet.scanResponse, - blockchain = blockchain, - derivationPath = derivationPath?.let { DerivationPath(rawPath = it) }, - ) - walletManager ?: return null + val path = derivationPath?.let { DerivationPath(rawPath = it) } + if (walletManager == null) { + when (userWallet) { + is UserWallet.Hot -> { + walletManager = walletManagerFactory.createWalletManagerForHot( + hotWallet = userWallet, + blockchain = blockchain, + derivationPath = path, + ) + } + is UserWallet.Cold -> { + walletManager = walletManagerFactory.createWalletManager( + scanResponse = userWallet.scanResponse, + blockchain = blockchain, + derivationPath = path, + ) + } + } + walletManager ?: return null walletManagersStore.store(userWalletId, walletManager) } return walletManager diff --git a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/utils/WalletManagerFactory.kt b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/utils/WalletManagerFactory.kt index c5b825b82c..fb837c6259 100644 --- a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/utils/WalletManagerFactory.kt +++ b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/utils/WalletManagerFactory.kt @@ -6,9 +6,11 @@ import com.tangem.blockchain.common.WalletManager import com.tangem.blockchainsdk.BlockchainSDKFactory import com.tangem.crypto.hdWallet.DerivationPath import com.tangem.domain.common.DerivationStyleProvider +import com.tangem.domain.common.extensions.makePublicKey import com.tangem.domain.common.extensions.makeWalletManagerForApp import com.tangem.domain.common.util.derivationStyleProvider import com.tangem.domain.models.scan.ScanResponse +import com.tangem.domain.wallets.models.UserWallet import timber.log.Timber internal class WalletManagerFactory( @@ -34,6 +36,42 @@ internal class WalletManagerFactory( } } + suspend fun createWalletManagerForHot( + hotWallet: UserWallet.Hot, + blockchain: Blockchain, + derivationPath: DerivationPath?, + ): WalletManager? { + val curve = blockchain.getSupportedCurves().first() + val selectedWallet = hotWallet.wallets.orEmpty().firstOrNull { it.curve == curve } + ?: return null + return try { + val factory = blockchainSDKFactory.getWalletManagerFactorySync() ?: return null + + if (derivationPath == null) { + factory.createLegacyWalletManager( + blockchain = blockchain, + walletPublicKey = selectedWallet.publicKey, + curve = selectedWallet.curve, + ) + } else { + factory.createWalletManager( + blockchain = blockchain, + publicKey = makePublicKey( + seedKey = selectedWallet.publicKey, + blockchain = blockchain, + derivationPath = derivationPath, + derivedWalletKeys = selectedWallet.derivedKeys, + isWallet2 = true, + ) ?: return null, + curve = selectedWallet.curve, + ) + } + } catch (e: Throwable) { + Timber.w(e, "Failed to create wallet manager for $blockchain") + null + } + } + private fun getDerivationParams( derivationPath: DerivationPath?, derivationStyleProvider: DerivationStyleProvider, diff --git a/domain/models/src/main/kotlin/com/tangem/domain/models/ArtworkModel.kt b/domain/models/src/main/kotlin/com/tangem/domain/models/ArtworkModel.kt index 777d3355d8..6c96413785 100644 --- a/domain/models/src/main/kotlin/com/tangem/domain/models/ArtworkModel.kt +++ b/domain/models/src/main/kotlin/com/tangem/domain/models/ArtworkModel.kt @@ -3,4 +3,22 @@ package com.tangem.domain.models data class ArtworkModel( val verifiedArtwork: ByteArray? = null, val defaultUrl: String, -) \ No newline at end of file +) { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as ArtworkModel + + if (!verifiedArtwork.contentEquals(other.verifiedArtwork)) return false + if (defaultUrl != other.defaultUrl) return false + + return true + } + + override fun hashCode(): Int { + var result = verifiedArtwork?.contentHashCode() ?: 0 + result = 31 * result + defaultUrl.hashCode() + return result + } +} \ No newline at end of file diff --git a/domain/models/src/main/kotlin/com/tangem/domain/models/MobileWallet.kt b/domain/models/src/main/kotlin/com/tangem/domain/models/MobileWallet.kt new file mode 100644 index 0000000000..6c093f4c9a --- /dev/null +++ b/domain/models/src/main/kotlin/com/tangem/domain/models/MobileWallet.kt @@ -0,0 +1,31 @@ +package com.tangem.domain.models + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass +import com.tangem.common.card.EllipticCurve +import com.tangem.crypto.hdWallet.DerivationPath +import com.tangem.crypto.hdWallet.bip32.ExtendedPublicKey +import com.tangem.domain.models.serialization.MobileWalletAsStringSerializer +import kotlinx.serialization.Serializable + +@Serializable(with = MobileWalletAsStringSerializer::class) +@JsonClass(generateAdapter = true) +class MobileWallet( + @Json(name = "publicKey") + val publicKey: ByteArray, + @Json(name = "chainCode") + val chainCode: ByteArray?, + @Json(name = "curve") + val curve: EllipticCurve, + @Json(name = "derivedKeys") + val derivedKeys: Map, +) { + + val extendedPublicKey: ExtendedPublicKey? + get() = chainCode?.let { + ExtendedPublicKey( + publicKey = publicKey, + chainCode = it, + ) + } +} \ No newline at end of file diff --git a/domain/models/src/main/kotlin/com/tangem/domain/models/serialization/MobileWalletAsStringSerializer.kt b/domain/models/src/main/kotlin/com/tangem/domain/models/serialization/MobileWalletAsStringSerializer.kt new file mode 100644 index 0000000000..26d5c38155 --- /dev/null +++ b/domain/models/src/main/kotlin/com/tangem/domain/models/serialization/MobileWalletAsStringSerializer.kt @@ -0,0 +1,37 @@ +package com.tangem.domain.models.serialization + +import com.squareup.moshi.Moshi +import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory +import com.tangem.common.json.TangemSdkAdapter +import com.tangem.domain.models.MobileWallet +import com.tangem.domain.models.scan.serialization.* +import kotlinx.serialization.KSerializer +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +internal object MobileWalletAsStringSerializer : KSerializer { + + private val moshi = Moshi.Builder() + .add(WalletDerivedKeysMapAdapter()) + .add(ScanResponseDerivedKeysMapAdapter()) + .add(ByteArrayKeyAdapter()) + .add(ExtendedPublicKeysMapAdapter()) + .add(DerivationPathAdapterWithMigration()) + .add(TangemSdkAdapter.DateAdapter()) + .add(TangemSdkAdapter.DerivationNodeAdapter()) + .addLast(KotlinJsonAdapterFactory()) + .build() + + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("MobileWallet", PrimitiveKind.STRING) + + override fun deserialize(decoder: Decoder): MobileWallet { + return moshi.adapter(MobileWallet::class.java).fromJson(decoder.decodeString())!! + } + + override fun serialize(encoder: Encoder, value: MobileWallet) { + encoder.encodeString(moshi.adapter(MobileWallet::class.java).toJson(value)!!) + } +} \ No newline at end of file diff --git a/domain/wallets/build.gradle.kts b/domain/wallets/build.gradle.kts index 331335a257..6a6f7db261 100644 --- a/domain/wallets/build.gradle.kts +++ b/domain/wallets/build.gradle.kts @@ -32,6 +32,7 @@ dependencies { // region Tangem libraries implementation(tangemDeps.blockchain) // android-library implementation(tangemDeps.card.core) + implementation(tangemDeps.hot.core) // endregion // region DI diff --git a/domain/wallets/models/build.gradle.kts b/domain/wallets/models/build.gradle.kts index 58d87775b5..1af28af669 100644 --- a/domain/wallets/models/build.gradle.kts +++ b/domain/wallets/models/build.gradle.kts @@ -8,6 +8,7 @@ plugins { dependencies { // region Tangem libraries implementation(tangemDeps.card.core) + implementation(tangemDeps.hot.core) // endregion // region Domain modules diff --git a/domain/wallets/models/src/main/java/com/tangem/domain/wallets/models/UserWallet.kt b/domain/wallets/models/src/main/java/com/tangem/domain/wallets/models/UserWallet.kt index 459195dd77..b47c4d7355 100644 --- a/domain/wallets/models/src/main/java/com/tangem/domain/wallets/models/UserWallet.kt +++ b/domain/wallets/models/src/main/java/com/tangem/domain/wallets/models/UserWallet.kt @@ -1,8 +1,9 @@ package com.tangem.domain.wallets.models +import com.tangem.domain.models.MobileWallet import com.tangem.domain.models.scan.CardDTO import com.tangem.domain.models.scan.ScanResponse -import com.tangem.domain.wallets.models.UserWallet.Cold +import com.tangem.hot.sdk.model.HotWalletId import kotlinx.serialization.Serializable import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract @@ -56,17 +57,21 @@ sealed interface UserWallet { data class Hot( override val name: String, override val walletId: UserWalletId, - val isLocked: Boolean, - ) : UserWallet + val hotWalletId: HotWalletId, + val wallets: List?, + ) : UserWallet { + + val isLocked: Boolean get() = wallets == null + } } @OptIn(ExperimentalContracts::class) -fun UserWallet.requireColdWallet(): Cold { +fun UserWallet.requireColdWallet(): UserWallet.Cold { contract { - returns() implies (this@requireColdWallet is Cold) + returns() implies (this@requireColdWallet is UserWallet.Cold) } - return this as? Cold + return this as? UserWallet.Cold ?: error("This user wallet is not a cold wallet") } diff --git a/domain/wallets/src/main/java/com/tangem/domain/wallets/builder/HotUserWalletBuilder.kt b/domain/wallets/src/main/java/com/tangem/domain/wallets/builder/HotUserWalletBuilder.kt new file mode 100644 index 0000000000..7d19d37e04 --- /dev/null +++ b/domain/wallets/src/main/java/com/tangem/domain/wallets/builder/HotUserWalletBuilder.kt @@ -0,0 +1,69 @@ +package com.tangem.domain.wallets.builder + +import com.tangem.blockchain.common.Blockchain +import com.tangem.blockchain.common.derivation.DerivationStyle +import com.tangem.domain.models.MobileWallet +import com.tangem.domain.wallets.models.UserWallet +import com.tangem.domain.wallets.models.UserWalletId +import com.tangem.domain.wallets.usecase.GenerateWalletNameUseCase +import com.tangem.hot.sdk.TangemHotSdk +import com.tangem.hot.sdk.model.DeriveWalletRequest +import com.tangem.hot.sdk.model.HotAuth +import com.tangem.hot.sdk.model.HotWalletId +import com.tangem.hot.sdk.model.UnlockHotWallet +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject + +class HotUserWalletBuilder @AssistedInject constructor( + @Assisted private val hotWalletId: HotWalletId, + private val hotSdk: TangemHotSdk, + private val generateWalletNameUseCase: GenerateWalletNameUseCase, +) { + + suspend fun build(): UserWallet.Hot { + val allNetworks = Blockchain.entries // TODO use HotDerivationsRepository to get supported networks + val requests = allNetworks.map { + val curves = it.getSupportedCurves() + val derivationPath = it.derivationPath(DerivationStyle.V3) + + curves.map { + DeriveWalletRequest.Request( + curve = it, + paths = listOfNotNull(derivationPath), + ) + } + }.flatten() + + val derivationResult = hotSdk.derivePublicKey( + unlockHotWallet = UnlockHotWallet( + walletId = hotWalletId, + auth = HotAuth.NoAuth, + ), + request = DeriveWalletRequest( + requests = requests, + ), + ) + + val wallets = derivationResult.responses.map { + MobileWallet( + publicKey = it.seedKey.publicKey, + chainCode = it.seedKey.chainCode, + curve = it.curve, + derivedKeys = it.publicKeys, + ) + } + + return UserWallet.Hot( + name = generateWalletNameUseCase.invokeForHot(), + walletId = UserWalletId(wallets.first().publicKey), + hotWalletId = hotWalletId, + wallets = wallets, + ) + } + + @AssistedFactory + interface Factory { + fun create(hotWalletId: HotWalletId): HotUserWalletBuilder + } +} \ No newline at end of file diff --git a/domain/wallets/src/main/java/com/tangem/domain/wallets/repository/HotDerivationsRepository.kt b/domain/wallets/src/main/java/com/tangem/domain/wallets/repository/HotDerivationsRepository.kt new file mode 100644 index 0000000000..5616695e03 --- /dev/null +++ b/domain/wallets/src/main/java/com/tangem/domain/wallets/repository/HotDerivationsRepository.kt @@ -0,0 +1,8 @@ +package com.tangem.domain.wallets.repository + +import com.tangem.domain.models.network.Network + +interface HotDerivationsRepository { + + fun getAllSupportedNetworks(): Set +} \ No newline at end of file diff --git a/domain/wallets/src/main/java/com/tangem/domain/wallets/usecase/GenerateWalletNameUseCase.kt b/domain/wallets/src/main/java/com/tangem/domain/wallets/usecase/GenerateWalletNameUseCase.kt index f1d1852f0c..e3c901c204 100644 --- a/domain/wallets/src/main/java/com/tangem/domain/wallets/usecase/GenerateWalletNameUseCase.kt +++ b/domain/wallets/src/main/java/com/tangem/domain/wallets/usecase/GenerateWalletNameUseCase.kt @@ -21,6 +21,12 @@ class GenerateWalletNameUseCase( return suggestedWalletName(defaultName, existingNames) } + fun invokeForHot(): String { + val defaultName = "Mobile Wallet" + val existingNames = userWalletsListManager.userWalletsSync.map { it.name }.toSet() + return suggestedWalletName(defaultName, existingNames) + } + private fun suggestedWalletName(defaultName: String, existingNames: Set): String { val startIndex = 2 if (!existingNames.contains(defaultName)) { diff --git a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/CreateMobileWalletModel.kt b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/CreateMobileWalletModel.kt index c285fd8e48..34f6ed62ab 100644 --- a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/CreateMobileWalletModel.kt +++ b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/CreateMobileWalletModel.kt @@ -1,8 +1,11 @@ package com.tangem.features.hotwallet.createmobilewallet +import com.tangem.common.routing.AppRoute import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.navigation.Router +import com.tangem.domain.wallets.builder.HotUserWalletBuilder +import com.tangem.domain.wallets.usecase.SaveWalletUseCase import com.tangem.features.hotwallet.createmobilewallet.entity.CreateMobileWalletUM import com.tangem.hot.sdk.TangemHotSdk import com.tangem.hot.sdk.model.HotAuth @@ -10,12 +13,15 @@ import com.tangem.hot.sdk.model.MnemonicType import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import javax.inject.Inject @ModelScoped internal class CreateMobileWalletModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, + private val hotUserWalletBuilderFactory: HotUserWalletBuilder.Factory, + private val saveUserWalletUseCase: SaveWalletUseCase, private val router: Router, private val tangemHotSdk: TangemHotSdk, ) : Model() { @@ -25,19 +31,28 @@ internal class CreateMobileWalletModel @Inject constructor( CreateMobileWalletUM( onBackClick = { router.pop() }, onCreateClick = ::onCreateClick, + createButtonLoading = false, ), ) private fun onCreateClick() { modelScope.launch { - tangemHotSdk.generateWallet(HotAuth.NoAuth, mnemonicType = MnemonicType.Words12) - // TODO - // val hotUserWalletBuilder = hotUserWalletBuilderFactory.create(hotWalletId, tangemHotSdk) - // saveUserWalletUseCase( - // hotUserWalletBuilder.build(), - // ) + uiState.update { + it.copy(createButtonLoading = true) + } - // router.push(AppRoute.Wallet) + runCatching { + val hotWalletId = tangemHotSdk.generateWallet(HotAuth.NoAuth, mnemonicType = MnemonicType.Words12) + val hotUserWalletBuilder = hotUserWalletBuilderFactory.create(hotWalletId) + saveUserWalletUseCase( + hotUserWalletBuilder.build(), + ) + router.push(AppRoute.Wallet) + }.onFailure { + uiState.update { + it.copy(createButtonLoading = false) + } + } } } } \ No newline at end of file diff --git a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/entity/CreateMobileWalletUM.kt b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/entity/CreateMobileWalletUM.kt index 918e811d85..5d4569e604 100644 --- a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/entity/CreateMobileWalletUM.kt +++ b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/entity/CreateMobileWalletUM.kt @@ -1,6 +1,7 @@ package com.tangem.features.hotwallet.createmobilewallet.entity internal data class CreateMobileWalletUM( + val createButtonLoading: Boolean, val onBackClick: () -> Unit, val onCreateClick: () -> Unit, ) \ No newline at end of file diff --git a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/ui/CreateMobileWalletContent.kt b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/ui/CreateMobileWalletContent.kt index d6861cb49e..08b9a65372 100644 --- a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/ui/CreateMobileWalletContent.kt +++ b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/ui/CreateMobileWalletContent.kt @@ -85,7 +85,7 @@ internal fun CreateMobileWalletContent(state: CreateMobileWalletUM, modifier: Mo .fillMaxWidth() .padding(16.dp), text = stringResourceSafe(R.string.common_create), - showProgress = false, + showProgress = state.createButtonLoading, enabled = true, onClick = state.onCreateClick, ) @@ -133,6 +133,7 @@ private fun PreviewCreateWalletContent() { CreateMobileWalletContent( state = CreateMobileWalletUM( onBackClick = {}, + createButtonLoading = false, onCreateClick = {}, ), ) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/utils/WalletLoadingStateFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/utils/WalletLoadingStateFactory.kt index 5efd04f762..b95fcb4bb0 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/utils/WalletLoadingStateFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/utils/WalletLoadingStateFactory.kt @@ -6,7 +6,6 @@ import com.tangem.core.ui.components.marketprice.MarketPriceBlockState import com.tangem.core.ui.components.transactions.state.TxHistoryState import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.wallets.models.UserWallet -import com.tangem.domain.wallets.models.requireColdWallet import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory import com.tangem.feature.wallet.presentation.wallet.domain.WalletImageResolver @@ -26,12 +25,35 @@ internal class WalletLoadingStateFactory( ) { fun create(userWallet: UserWallet): WalletState { - userWallet.requireColdWallet() + return when (userWallet) { + is UserWallet.Cold -> { + userWallet.createStateByWalletType( + multiCurrencyCreator = { createLoadingMultiCurrencyContent(userWallet) }, + singleCurrencyCreator = { createLoadingSingleCurrencyContent(userWallet) }, + visaWalletCreator = { createLoadingVisaWalletContent(userWallet) }, + ) + } + is UserWallet.Hot -> { + createLoadingHotWalletContent(userWallet) + } + } + } - return userWallet.createStateByWalletType( - multiCurrencyCreator = { createLoadingMultiCurrencyContent(userWallet) }, - singleCurrencyCreator = { createLoadingSingleCurrencyContent(userWallet) }, - visaWalletCreator = { createLoadingVisaWalletContent(userWallet) }, + private fun createLoadingHotWalletContent(userWallet: UserWallet.Hot): WalletState.MultiCurrency.Content { + return WalletState.MultiCurrency.Content( + pullToRefreshConfig = createPullToRefreshConfig(), + walletCardState = WalletCardState.Loading( + id = userWallet.walletId, + title = userWallet.name, + additionalInfo = null, // TODO [REDACTED_TASK_KEY] + imageResId = null, // TODO [REDACTED_TASK_KEY] + dropDownItems = persistentListOf(), + ), + buttons = createMultiWalletActions(userWallet), + warnings = persistentListOf(), + bottomSheetConfig = null, + tokensListState = WalletTokensListState.ContentState.Loading, + nftState = WalletNFTItemUM.Hidden, ) } @@ -99,15 +121,21 @@ internal class WalletLoadingStateFactory( ) } - private fun createMultiWalletActions(userWallet: UserWallet.Cold): PersistentList { - val isSingleWalletWithToken = userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken() + private fun createMultiWalletActions(userWallet: UserWallet): PersistentList { + val isSingleWalletWithToken = + userWallet is UserWallet.Cold && userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken() if (isSingleWalletWithToken) return persistentListOf() return persistentListOf( WalletManageButton.Buy( enabled = true, dimContent = false, - onClick = { clickIntents.onMultiWalletBuyClick(userWalletId = userWallet.walletId, WALLET_TYPE) }, + onClick = { + clickIntents.onMultiWalletBuyClick( + userWalletId = userWallet.walletId, + WALLET_TYPE, + ) + }, ), WalletManageButton.Swap( enabled = true, @@ -124,14 +152,24 @@ internal class WalletLoadingStateFactory( private fun createVisaDimmedButtons(): PersistentList { return persistentListOf( - WalletManageButton.Receive(enabled = true, dimContent = true, onClick = {}, onLongClick = null), + WalletManageButton.Receive( + enabled = true, + dimContent = true, + onClick = {}, + onLongClick = null, + ), WalletManageButton.Buy(enabled = true, dimContent = true, onClick = {}), ) } private fun createDimmedButtons(): PersistentList { return persistentListOf( - WalletManageButton.Receive(enabled = true, dimContent = true, onClick = {}, onLongClick = null), + WalletManageButton.Receive( + enabled = true, + dimContent = true, + onClick = {}, + onLongClick = null, + ), WalletManageButton.Send(enabled = true, dimContent = true, onClick = {}), WalletManageButton.Buy(enabled = true, dimContent = true, onClick = {}), WalletManageButton.Sell(enabled = true, dimContent = true, onClick = {}),