From 6455a837b7ffd0bea2ad35205f4ea80c8b9bd3b1 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 13 Apr 2023 22:52:21 +0900 Subject: [PATCH] Updated on 2026-08-14 --- .../model/builders/UserWalletBuilder.kt | 46 +-------------- .../userWalletList/GetCardImageUseCase.kt | 59 +++++++++++++++++++ .../userWalletList/UserWalletsListManager.kt | 5 +- .../BiometricUserWalletsListManager.kt | 2 +- .../RuntimeUserWalletsListManager.kt | 2 +- .../tap/features/wallet/redux/WalletAction.kt | 5 ++ .../redux/middlewares/WalletMiddleware.kt | 22 +++++++ .../wallet/redux/reducers/WalletReducer.kt | 5 +- 8 files changed, 99 insertions(+), 47 deletions(-) create mode 100644 app/src/main/java/com/tangem/tap/domain/userWalletList/GetCardImageUseCase.kt diff --git a/app/src/main/java/com/tangem/tap/domain/model/builders/UserWalletBuilder.kt b/app/src/main/java/com/tangem/tap/domain/model/builders/UserWalletBuilder.kt index b74821a988..3a82b45171 100644 --- a/app/src/main/java/com/tangem/tap/domain/model/builders/UserWalletBuilder.kt +++ b/app/src/main/java/com/tangem/tap/domain/model/builders/UserWalletBuilder.kt @@ -1,22 +1,15 @@ package com.tangem.tap.domain.model.builders -import com.tangem.common.extensions.toHexString -import com.tangem.common.services.Result import com.tangem.domain.common.CardDTO import com.tangem.domain.common.ProductType -import com.tangem.domain.common.SaltPayWorkaround import com.tangem.domain.common.ScanResponse import com.tangem.domain.common.TapWorkarounds.isStart2Coin -import com.tangem.domain.common.TwinCardNumber -import com.tangem.domain.common.TwinsHelper -import com.tangem.operations.attestation.OnlineCardVerifier -import com.tangem.operations.attestation.TangemApi import com.tangem.tap.domain.model.UserWallet -import com.tangem.tap.features.wallet.redux.Artwork +import com.tangem.tap.domain.userWalletList.GetCardImageUseCase class UserWalletBuilder( private val scanResponse: ScanResponse, - private val onlineCardVerifier: OnlineCardVerifier = OnlineCardVerifier(), + private val getCardImageUseCase: GetCardImageUseCase = GetCardImageUseCase(), ) { private var backupCardsIds: Set = emptySet() @@ -50,7 +43,7 @@ class UserWalletBuilder( UserWallet( walletId = it, name = userWalletName, - artworkUrl = loadArtworkUrl(card.cardId, card.cardPublicKey), + artworkUrl = getCardImageUseCase.invoke(card.cardId, card.cardPublicKey), cardsInWallet = backupCardsIds.plus(card.cardId), scanResponse = this, isMultiCurrency = cardTypesResolver.isMultiwalletAllowed(), @@ -58,37 +51,4 @@ class UserWalletBuilder( } } } - - private suspend fun loadArtworkUrl(cardId: String, cardPublicKey: ByteArray): String { - return when (val result = onlineCardVerifier.getCardInfo(cardId, cardPublicKey)) { - is Result.Success -> { - val artworkId = result.data.artwork?.id - if (artworkId.isNullOrEmpty()) { - getFallbackArtworkUrl(cardId) - } else { - getUrlForArtwork(cardId, cardPublicKey.toHexString(), artworkId) - } - } - - is Result.Failure -> getFallbackArtworkUrl(cardId) - } - } - - private fun getFallbackArtworkUrl(cardId: String): String { - return when { - cardId.startsWith(Artwork.SERGIO_CARD_ID) -> Artwork.SERGIO_CARD_URL - cardId.startsWith(Artwork.MARTA_CARD_ID) -> Artwork.MARTA_CARD_URL - SaltPayWorkaround.isSaltPayCardId(cardId) -> Artwork.SALT_PAY_URL - else -> when (TwinsHelper.getTwinCardNumber(cardId)) { - TwinCardNumber.First -> Artwork.TWIN_CARD_1 - TwinCardNumber.Second -> Artwork.TWIN_CARD_2 - else -> Artwork.DEFAULT_IMG_URL - } - } - } - - private fun getUrlForArtwork(cardId: String, cardPublicKeyHex: String, artworkId: String): String { - return TangemApi.Companion.BaseUrl.VERIFY.url + TangemApi.ARTWORK + - "?artworkId=$artworkId&CID=$cardId&publicKey=$cardPublicKeyHex" - } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/GetCardImageUseCase.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/GetCardImageUseCase.kt new file mode 100644 index 0000000000..71415134a2 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/GetCardImageUseCase.kt @@ -0,0 +1,59 @@ +package com.tangem.tap.domain.userWalletList + +import com.tangem.common.extensions.toHexString +import com.tangem.common.services.Result +import com.tangem.domain.common.SaltPayWorkaround +import com.tangem.domain.common.TwinCardNumber +import com.tangem.domain.common.TwinsHelper +import com.tangem.operations.attestation.OnlineCardVerifier +import com.tangem.operations.attestation.TangemApi +import com.tangem.tap.features.wallet.redux.Artwork + +/** + * Use case for getting card image url + * + * @property verifier REST API + * +[REDACTED_AUTHOR] + */ +class GetCardImageUseCase(private val verifier: OnlineCardVerifier = OnlineCardVerifier()) { + + /** + * Get card image url + * + * @param cardId card id + * @param cardPublicKey card public key + */ + suspend operator fun invoke(cardId: String, cardPublicKey: ByteArray): String { + return when (val result = verifier.getCardInfo(cardId, cardPublicKey)) { + is Result.Success -> { + val artworkId = result.data.artwork?.id + if (artworkId.isNullOrEmpty()) { + getFallbackArtworkUrl(cardId) + } else { + getUrlForArtwork(cardId, cardPublicKey.toHexString(), artworkId) + } + } + + is Result.Failure -> getFallbackArtworkUrl(cardId) + } + } + + private fun getFallbackArtworkUrl(cardId: String): String { + return when { + cardId.startsWith(Artwork.SERGIO_CARD_ID) -> Artwork.SERGIO_CARD_URL + cardId.startsWith(Artwork.MARTA_CARD_ID) -> Artwork.MARTA_CARD_URL + SaltPayWorkaround.isSaltPayCardId(cardId) -> Artwork.SALT_PAY_URL + else -> when (TwinsHelper.getTwinCardNumber(cardId)) { + TwinCardNumber.First -> Artwork.TWIN_CARD_1 + TwinCardNumber.Second -> Artwork.TWIN_CARD_2 + else -> Artwork.DEFAULT_IMG_URL + } + } + } + + private fun getUrlForArtwork(cardId: String, cardPublicKeyHex: String, artworkId: String): String { + return TangemApi.Companion.BaseUrl.VERIFY.url + TangemApi.ARTWORK + + "?artworkId=$artworkId&CID=$cardId&publicKey=$cardPublicKeyHex" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/UserWalletsListManager.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/UserWalletsListManager.kt index 4286bfd8c0..b1c97b594b 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/UserWalletsListManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/UserWalletsListManager.kt @@ -55,7 +55,10 @@ interface UserWalletsListManager { * @return [CompletionResult.Success] with updated [UserWallet] * or [CompletionResult.Failure] with [NoSuchElementException] if [UserWallet] with [userWalletId] not found * */ - suspend fun update(userWalletId: UserWalletId, update: (UserWallet) -> UserWallet): CompletionResult + suspend fun update( + userWalletId: UserWalletId, + update: suspend (UserWallet) -> UserWallet, + ): CompletionResult /** * Delete saved [UserWallet]s with provided [UserWalletId]s diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManager.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManager.kt index b4bcf48c73..72244a8bf8 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManager.kt @@ -120,7 +120,7 @@ internal class BiometricUserWalletsListManager( override suspend fun update( userWalletId: UserWalletId, - update: (UserWallet) -> UserWallet, + update: suspend (UserWallet) -> UserWallet, ): CompletionResult { return get(userWalletId) .map { storedUserWallet -> diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/RuntimeUserWalletsListManager.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/RuntimeUserWalletsListManager.kt index f726dba792..c94958d46f 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/RuntimeUserWalletsListManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/RuntimeUserWalletsListManager.kt @@ -58,7 +58,7 @@ internal class RuntimeUserWalletsListManager : UserWalletsListManager { override suspend fun update( userWalletId: UserWalletId, - update: (UserWallet) -> UserWallet, + update: suspend (UserWallet) -> UserWallet, ): CompletionResult = catching { val wallet = state.value.userWallet ?.takeIf { it.walletId == userWalletId } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt index c026cc9e0f..e4a508d068 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt @@ -4,6 +4,7 @@ import android.content.Context import com.tangem.blockchain.common.Amount import com.tangem.blockchain.common.address.AddressType import com.tangem.core.analytics.AnalyticsEvent +import com.tangem.domain.common.util.UserWalletId import com.tangem.tap.common.entities.FiatCurrency import com.tangem.tap.common.redux.NotificationAction import com.tangem.tap.domain.TapError @@ -130,4 +131,8 @@ sealed class WalletAction : Action { data class WalletStoresChanged(val walletStores: List) : WalletAction() data class TotalFiatBalanceChanged(val balance: TotalFiatBalance) : WalletAction() + + data class UpdateUserWalletArtwork(val walletId: UserWalletId) : WalletAction() + + data class SetArtworkUrl(val url: String) : WalletAction() } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt index 404aa63a43..7d34cdc332 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt @@ -5,6 +5,7 @@ import com.tangem.blockchain.common.Amount import com.tangem.blockchain.common.AmountType import com.tangem.blockchain.common.address.AddressType import com.tangem.common.CompletionResult +import com.tangem.common.doOnSuccess import com.tangem.common.extensions.guard import com.tangem.core.analytics.Analytics import com.tangem.datasource.connection.NetworkConnectionManager @@ -25,6 +26,7 @@ import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.domain.TapError import com.tangem.tap.domain.model.WalletDataModel import com.tangem.tap.domain.model.WalletStoreModel +import com.tangem.tap.domain.userWalletList.GetCardImageUseCase import com.tangem.tap.domain.userWalletList.lockIfLockable import com.tangem.tap.features.demo.DemoHelper import com.tangem.tap.features.home.redux.HomeAction @@ -133,6 +135,9 @@ class WalletMiddleware { Timber.e("Unable to load/refresh wallets data, no user wallet selected") return } + + store.dispatch(WalletAction.UpdateUserWalletArtwork(selectedWallet.walletId)) + scope.launch { globalState.tapWalletManager.loadData( userWallet = selectedWallet, @@ -205,6 +210,23 @@ class WalletMiddleware { is WalletAction.ChangeSelectedAddress -> { changeSelectedWalletAddress(action.type, walletState) } + is WalletAction.UpdateUserWalletArtwork -> { + scope.launch { + userWalletsListManager + .update( + userWalletId = action.walletId, + update = { userWallet -> + userWallet.copy( + artworkUrl = GetCardImageUseCase().invoke( + cardId = userWallet.cardId, + cardPublicKey = userWallet.scanResponse.card.cardPublicKey, + ), + ) + }, + ) + .doOnSuccess { store.dispatch(WalletAction.SetArtworkUrl(it.artworkUrl)) } + } + } } } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt index b1d7fcfef0..a7ebec614d 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt @@ -113,8 +113,11 @@ private fun internalReduce(action: Action, state: AppState, appStateHolder: AppS ) } is WalletAction.UpdateCanSaveUserWallets -> { + newState = newState.copy(canSaveUserWallets = action.canSaveUserWallets) + } + is WalletAction.SetArtworkUrl -> { newState = newState.copy( - canSaveUserWallets = action.canSaveUserWallets, + cardImage = Artwork(artworkId = action.url, artwork = newState.cardImage?.artwork), ) } else -> Unit