From f96324a29947d61972c161d9f02c2ade22af4c1e Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 21 Apr 2025 17:53:14 +0300 Subject: [PATCH 1/6] Updated on 2026-08-14 --- .../src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt index c586e0bf5a..f177785284 100644 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt +++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt @@ -859,7 +859,7 @@ internal class StateBuilder( add( resourceReference( id = R.string.swapping_alert_dex_description_with_slippage, - formatArgs = wrappedList(token, slippage), + formatArgs = wrappedList(slippage), ), ) } else { From a864a979a1e1c1099ab87593130d405a670335e3 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 22 Apr 2025 13:52:11 +0300 Subject: [PATCH 2/6] Updated on 2026-08-14 --- gradle/tangem_dependencies.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/tangem_dependencies.toml b/gradle/tangem_dependencies.toml index 40622899bf..76affe35f0 100644 --- a/gradle/tangem_dependencies.toml +++ b/gradle/tangem_dependencies.toml @@ -5,7 +5,7 @@ # https://github.com/tangem/tangem-sdk-android/ # https://github.com/tangem/vico -tangemBlockchainSdk = "releases-5.23-1039" +tangemBlockchainSdk = "releases-5.23-1043" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "releases-5.23-456" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ From 132fc284c7e1ed043d963086f95c12a24dd920df Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 22 Apr 2025 12:51:25 +0300 Subject: [PATCH 3/6] Updated on 2026-08-14 --- .../store/DefaultNetworksStatusesStoreV2.kt | 64 +++++++++---------- .../NetworkStatusesStoreUpdateMethodsTest.kt | 18 +----- .../wallet/child/wallet/model/WalletModel.kt | 7 ++ 3 files changed, 40 insertions(+), 49 deletions(-) diff --git a/data/networks/src/main/java/com/tangem/data/networks/store/DefaultNetworksStatusesStoreV2.kt b/data/networks/src/main/java/com/tangem/data/networks/store/DefaultNetworksStatusesStoreV2.kt index dedbcb34e5..7dd1828915 100644 --- a/data/networks/src/main/java/com/tangem/data/networks/store/DefaultNetworksStatusesStoreV2.kt +++ b/data/networks/src/main/java/com/tangem/data/networks/store/DefaultNetworksStatusesStoreV2.kt @@ -19,6 +19,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.launch +import timber.log.Timber internal typealias WalletIdWithSimpleStatus = Map> internal typealias WalletIdWithStatusDM = Map> @@ -55,29 +56,17 @@ internal class DefaultNetworksStatusesStoreV2( } override suspend fun refresh(userWalletId: UserWalletId, network: Network) { - updateStatusSourceInRuntime(userWalletId = userWalletId, network = network, source = StatusSource.CACHE) + refresh(userWalletId = userWalletId, networks = setOf(network)) } override suspend fun refresh(userWalletId: UserWalletId, networks: Set) { - val simpleStatusIds = networks.map(SimpleNetworkStatus::Id) + if (networks.isEmpty()) { + Timber.d("Nothing to refresh: networks is empty") + return + } - runtimeStore.update(default = emptyMap()) { stored -> - stored.toMutableMap().apply { - val storedStatuses = this[userWalletId.stringValue].orEmpty() - - val statuses = simpleStatusIds.mapTo(hashSetOf()) { simpleStatusId -> - val status = storedStatuses.firstOrNull { it.id == simpleStatusId } - ?: createDefaultStatus(id = simpleStatusId) - - status.copy( - value = status.value.copySealed(source = StatusSource.CACHE), - ) - } - - val updatedStatuses = storedStatuses.addOrReplace(statuses) { old, new -> old.id == new.id } - - put(key = userWalletId.stringValue, value = updatedStatuses) - } + updateInRuntime(userWalletId = userWalletId, networks = networks) { status -> + status.copy(value = status.value.copySealed(source = StatusSource.CACHE)) } } @@ -93,28 +82,37 @@ internal class DefaultNetworksStatusesStoreV2( } override suspend fun storeError(userWalletId: UserWalletId, network: Network) { - updateStatusSourceInRuntime(userWalletId = userWalletId, network = network, source = StatusSource.ONLY_CACHE) + updateInRuntime( + userWalletId = userWalletId, + networks = setOf(network), + ifNotFound = ::createUnreachableStatus, + update = { status -> + status.copy(value = status.value.copySealed(source = StatusSource.ONLY_CACHE)) + }, + ) } - private suspend fun updateStatusSourceInRuntime( + private suspend fun updateInRuntime( userWalletId: UserWalletId, - network: Network, - source: StatusSource, + networks: Set, + ifNotFound: (SimpleNetworkStatus.Id) -> SimpleNetworkStatus? = { null }, + update: (SimpleNetworkStatus) -> SimpleNetworkStatus, ) { - val simpleStatusId = SimpleNetworkStatus.Id(network) + val simpleStatusIds = networks.map(SimpleNetworkStatus::Id) runtimeStore.update(default = emptyMap()) { stored -> stored.toMutableMap().apply { - val status = this[userWalletId.stringValue].orEmpty() - .firstOrNull { it.id == simpleStatusId } - ?: createDefaultStatus(id = simpleStatusId) + val storedStatuses = this[userWalletId.stringValue].orEmpty() - val updatedStatus = status.copy( - value = status.value.copySealed(source = source), - ) + val statuses = simpleStatusIds.mapNotNullTo(hashSetOf()) { simpleStatusId -> + val status = storedStatuses.firstOrNull { it.id == simpleStatusId } + ?: ifNotFound(simpleStatusId) + ?: return@mapNotNullTo null - val updatedStatuses = this[userWalletId.stringValue].orEmpty() - .addOrReplace(updatedStatus) { it.id == simpleStatusId } + update(status) + } + + val updatedStatuses = storedStatuses.addOrReplace(statuses) { old, new -> old.id == new.id } put(key = userWalletId.stringValue, value = updatedStatuses) } @@ -151,7 +149,7 @@ internal class DefaultNetworksStatusesStoreV2( } } - private fun createDefaultStatus(id: SimpleNetworkStatus.Id): SimpleNetworkStatus { + private fun createUnreachableStatus(id: SimpleNetworkStatus.Id): SimpleNetworkStatus { return SimpleNetworkStatus(id = id, value = NetworkStatus.Unreachable(address = null)) } } \ No newline at end of file diff --git a/data/networks/src/test/java/com/tangem/data/networks/store/NetworkStatusesStoreUpdateMethodsTest.kt b/data/networks/src/test/java/com/tangem/data/networks/store/NetworkStatusesStoreUpdateMethodsTest.kt index 57aea3c1e2..4331b3c8e4 100644 --- a/data/networks/src/test/java/com/tangem/data/networks/store/NetworkStatusesStoreUpdateMethodsTest.kt +++ b/data/networks/src/test/java/com/tangem/data/networks/store/NetworkStatusesStoreUpdateMethodsTest.kt @@ -35,14 +35,7 @@ internal class NetworkStatusesStoreUpdateMethodsTest { fun `refresh the single network if runtime store is empty`() = runTest { store.refresh(userWalletId = userWalletId, network = network) - val runtimeExpected = mapOf( - userWalletId.stringValue to setOf( - SimpleNetworkStatus( - id = SimpleNetworkStatus.Id(network), - value = NetworkStatus.Unreachable(address = null), - ), - ), - ) + val runtimeExpected = mapOf(userWalletId.stringValue to emptySet()) Truth.assertThat(runtimeStore.getSyncOrNull()).isEqualTo(runtimeExpected) Truth.assertThat(persistenceStore.data.firstOrNull()).isEqualTo(emptyMap>()) @@ -72,14 +65,7 @@ internal class NetworkStatusesStoreUpdateMethodsTest { fun `refresh the multi networks if runtime store is empty`() = runTest { store.refresh(userWalletId = userWalletId, networks = networks) - val runtimeExpected = mapOf( - userWalletId.stringValue to networks.mapTo(hashSetOf()) { - SimpleNetworkStatus( - id = SimpleNetworkStatus.Id(it), - value = NetworkStatus.Unreachable(address = null), - ) - }, - ) + val runtimeExpected = mapOf(userWalletId.stringValue to emptySet()) Truth.assertThat(runtimeStore.getSyncOrNull()).isEqualTo(runtimeExpected) Truth.assertThat(persistenceStore.data.firstOrNull()).isEqualTo(emptyMap>()) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt index 5359f89098..418cb39368 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt @@ -402,6 +402,13 @@ internal class WalletModel @Inject constructor( coroutineScope = modelScope, ) + if (action.selectedWallet.scanResponse.cardTypesResolver.isSingleWallet()) { + modelScope.launch { + fetchCurrencyStatusUseCase(userWalletId = action.selectedWallet.walletId) + .onLeft { Timber.e(it.toString()) } + } + } + stateHolder.update( AddWalletTransformer( userWallet = action.selectedWallet, From d80dced3fa88ee28117b2228531d46b108e0c52f Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 22 Apr 2025 15:17:24 +0300 Subject: [PATCH 4/6] Updated on 2026-08-14 --- .../kotlin/com/tangem/features/details/utils/UserWalletSaver.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/UserWalletSaver.kt b/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/UserWalletSaver.kt index 570693940c..1c193139a2 100644 --- a/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/UserWalletSaver.kt +++ b/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/UserWalletSaver.kt @@ -122,7 +122,7 @@ internal class UserWalletSaver @Inject constructor( scanCardProcessor.scan( analyticsSource = AnalyticsParam.ScreensSources.Settings, onWalletNotCreated = { - /* no-op */ + continuation.resume(Either.Right(null)) }, disclaimerWillShow = { continuation.resume(Either.Right(null)) From 2a2e0b3323665aefb996a8e5aeab7e550e2263a2 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 23 Apr 2025 11:42:55 +0300 Subject: [PATCH 5/6] Updated on 2026-08-14 --- .../DefaultSingleNetworkStatusFetcher.kt | 12 ++- .../store/DefaultNetworksStatusesStoreV2.kt | 21 +++- .../networks/store/NetworksStatusesStoreV2.kt | 12 ++- .../DefaultSingleNetworkStatusFetcherTest.kt | 6 +- .../NetworkStatusesStoreUpdateMethodsTest.kt | 102 +++++++++++++----- .../store/StoreActualNetworkStatusTest.kt | 15 +-- 6 files changed, 123 insertions(+), 45 deletions(-) diff --git a/data/networks/src/main/java/com/tangem/data/networks/single/DefaultSingleNetworkStatusFetcher.kt b/data/networks/src/main/java/com/tangem/data/networks/single/DefaultSingleNetworkStatusFetcher.kt index 6ded8b6524..6f72de7745 100644 --- a/data/networks/src/main/java/com/tangem/data/networks/single/DefaultSingleNetworkStatusFetcher.kt +++ b/data/networks/src/main/java/com/tangem/data/networks/single/DefaultSingleNetworkStatusFetcher.kt @@ -19,6 +19,7 @@ import com.tangem.domain.demo.DemoConfig import com.tangem.domain.networks.single.SingleNetworkStatusFetcher import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.Network +import com.tangem.domain.tokens.model.NetworkStatus import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.domain.wallets.models.UserWallet import com.tangem.utils.coroutines.CoroutineDispatcherProvider @@ -76,7 +77,16 @@ internal class DefaultSingleNetworkStatusFetcher @Inject constructor( currencies = networkCurrencies.toSet(), ) - networksStatusesStore.storeActual(userWalletId = params.userWalletId, value = status) + val statusValue = status.value + if (statusValue is NetworkStatus.Unreachable) { + networksStatusesStore.storeError( + userWalletId = params.userWalletId, + network = params.network, + value = statusValue, + ) + } else { + networksStatusesStore.storeSuccess(userWalletId = params.userWalletId, value = status) + } } .onLeft { Timber.e("Failed to fetch network status for $params: $it") diff --git a/data/networks/src/main/java/com/tangem/data/networks/store/DefaultNetworksStatusesStoreV2.kt b/data/networks/src/main/java/com/tangem/data/networks/store/DefaultNetworksStatusesStoreV2.kt index 7dd1828915..e9790f1fd1 100644 --- a/data/networks/src/main/java/com/tangem/data/networks/store/DefaultNetworksStatusesStoreV2.kt +++ b/data/networks/src/main/java/com/tangem/data/networks/store/DefaultNetworksStatusesStoreV2.kt @@ -70,9 +70,19 @@ internal class DefaultNetworksStatusesStoreV2( } } - override suspend fun storeActual(userWalletId: UserWalletId, value: NetworkStatus) { + override suspend fun storeSuccess(userWalletId: UserWalletId, value: NetworkStatus) { + if (value.value is NetworkStatus.Unreachable) { + val message = "Use storeError method to save unreachable status" + Timber.d(message) + + error(message) + } + if (value.value.source != StatusSource.ACTUAL) { - error("Method storeActual can be called only with StatusSource.ACTUAL") + val message = "Method storeActual can be called only with StatusSource.ACTUAL" + Timber.d(message) + + error(message) } coroutineScope { @@ -81,11 +91,14 @@ internal class DefaultNetworksStatusesStoreV2( } } - override suspend fun storeError(userWalletId: UserWalletId, network: Network) { + override suspend fun storeError(userWalletId: UserWalletId, network: Network, value: NetworkStatus.Unreachable?) { updateInRuntime( userWalletId = userWalletId, networks = setOf(network), - ifNotFound = ::createUnreachableStatus, + ifNotFound = { id -> + value?.let { SimpleNetworkStatus(id = id, value = value) } + ?: createUnreachableStatus(id = id) + }, update = { status -> status.copy(value = status.value.copySealed(source = StatusSource.ONLY_CACHE)) }, diff --git a/data/networks/src/main/java/com/tangem/data/networks/store/NetworksStatusesStoreV2.kt b/data/networks/src/main/java/com/tangem/data/networks/store/NetworksStatusesStoreV2.kt index 3810940ad9..d3b9e7b595 100644 --- a/data/networks/src/main/java/com/tangem/data/networks/store/NetworksStatusesStoreV2.kt +++ b/data/networks/src/main/java/com/tangem/data/networks/store/NetworksStatusesStoreV2.kt @@ -18,9 +18,13 @@ internal interface NetworksStatusesStoreV2 { /** Refresh statuses of [networks] by [userWalletId] */ suspend fun refresh(userWalletId: UserWalletId, networks: Set) - /** Store actual [NetworkStatus] by [userWalletId] */ - suspend fun storeActual(userWalletId: UserWalletId, value: NetworkStatus) + /** Store success [value] by [userWalletId]. If status's value is unreachable, throws exception */ + @Throws + suspend fun storeSuccess(userWalletId: UserWalletId, value: NetworkStatus) - /** Store error by [userWalletId] and [network] */ - suspend fun storeError(userWalletId: UserWalletId, network: Network) + /** + * Store error [value] by [userWalletId] and [network]. + * If [value] is null, default unreachable status will be stored. + */ + suspend fun storeError(userWalletId: UserWalletId, network: Network, value: NetworkStatus.Unreachable? = null) } \ No newline at end of file diff --git a/data/networks/src/test/java/com/tangem/data/networks/single/DefaultSingleNetworkStatusFetcherTest.kt b/data/networks/src/test/java/com/tangem/data/networks/single/DefaultSingleNetworkStatusFetcherTest.kt index 051cbca91b..7f2a925235 100644 --- a/data/networks/src/test/java/com/tangem/data/networks/single/DefaultSingleNetworkStatusFetcherTest.kt +++ b/data/networks/src/test/java/com/tangem/data/networks/single/DefaultSingleNetworkStatusFetcherTest.kt @@ -52,7 +52,7 @@ internal class DefaultSingleNetworkStatusFetcherTest { networksStatusesStore.refresh(userWalletId = userWalletId, network = network) userWalletsStore.getSyncStrict(key = userWalletId) walletManagersFacade.update(userWalletId, network, emptySet()) - networksStatusesStore.storeActual( + networksStatusesStore.storeSuccess( userWalletId = userWalletId, value = NetworkStatus(network, NetworkStatus.MissedDerivation), ) @@ -82,7 +82,7 @@ internal class DefaultSingleNetworkStatusFetcherTest { coVerify(inverse = true) { walletManagersFacade.update(userWalletId = any(), network = any(), extraTokens = any()) - networksStatusesStore.storeActual(userWalletId = any(), value = any()) + networksStatusesStore.storeSuccess(userWalletId = any(), value = any()) } Truth.assertThat(actual.isLeft()).isTrue() @@ -105,7 +105,7 @@ internal class DefaultSingleNetworkStatusFetcherTest { coVerifyOrder { userWalletsStore.getSyncStrict(key = userWalletId) walletManagersFacade.update(userWalletId, network, emptySet()) - networksStatusesStore.storeActual( + networksStatusesStore.storeSuccess( userWalletId = userWalletId, value = NetworkStatus(network, NetworkStatus.MissedDerivation), ) diff --git a/data/networks/src/test/java/com/tangem/data/networks/store/NetworkStatusesStoreUpdateMethodsTest.kt b/data/networks/src/test/java/com/tangem/data/networks/store/NetworkStatusesStoreUpdateMethodsTest.kt index 4331b3c8e4..ebf07bff35 100644 --- a/data/networks/src/test/java/com/tangem/data/networks/store/NetworkStatusesStoreUpdateMethodsTest.kt +++ b/data/networks/src/test/java/com/tangem/data/networks/store/NetworkStatusesStoreUpdateMethodsTest.kt @@ -43,7 +43,7 @@ internal class NetworkStatusesStoreUpdateMethodsTest { @Test fun `refresh the single network if runtime store contains status with this network`() = runTest { - val status = MockNetworkStatusFactory.createVerified().toSimple() + val status = MockNetworkStatusFactory.createVerified(network).toSimple() runtimeStore.store( value = mapOf(userWalletId.stringValue to setOf(status)), @@ -98,41 +98,50 @@ internal class NetworkStatusesStoreUpdateMethodsTest { val expectedErrorMessage = "Method storeActual can be called only with StatusSource.ACTUAL" // #1: StatusSource.ACTUAL - val status = MockNetworkStatusFactory.createVerified().copy( - value = MockNetworkStatusFactory.createVerified().value.copySealed(source = StatusSource.ACTUAL), + val status = MockNetworkStatusFactory.createVerified(network).copy( + value = MockNetworkStatusFactory.createVerified(network).value.copySealed(source = StatusSource.ACTUAL), ) - val actual = runCatching { store.storeActual(userWalletId, status) } + val actual = runCatching { store.storeSuccess(userWalletId, status) } + + val runtimeExpected = mapOf(userWalletId.stringValue to setOf(status.toSimple())) + val persistenceExpected = mapOf(userWalletId.stringValue to setOf(status.toDataModel()!!)) Truth.assertThat(actual.isSuccess).isTrue() + Truth.assertThat(runtimeStore.getSyncOrNull()).isEqualTo(runtimeExpected) + Truth.assertThat(persistenceStore.data.firstOrNull()).isEqualTo(persistenceExpected) // #2: StatusSource.CACHE - val cacheStatus = MockNetworkStatusFactory.createVerified().copy( - value = MockNetworkStatusFactory.createVerified().value.copySealed(source = StatusSource.CACHE), + val cacheStatus = MockNetworkStatusFactory.createVerified(network).copy( + value = MockNetworkStatusFactory.createVerified(network).value.copySealed(source = StatusSource.CACHE), ) - val cacheActual = runCatching { store.storeActual(userWalletId, cacheStatus) } + val cacheActual = runCatching { store.storeSuccess(userWalletId, cacheStatus) } Truth.assertThat(cacheActual.isFailure).isTrue() Truth.assertThat(cacheActual.exceptionOrNull()).isInstanceOf(IllegalStateException::class.java) Truth.assertThat(cacheActual.exceptionOrNull()).hasMessageThat().isEqualTo(expectedErrorMessage) + Truth.assertThat(runtimeStore.getSyncOrNull()).isEqualTo(runtimeExpected) + Truth.assertThat(persistenceStore.data.firstOrNull()).isEqualTo(persistenceExpected) // #3: StatusSource.ONLY_CACHE - val onlyCacheStatus = MockNetworkStatusFactory.createVerified().copy( - value = MockNetworkStatusFactory.createVerified().value.copySealed(source = StatusSource.ONLY_CACHE), + val onlyCacheStatus = MockNetworkStatusFactory.createVerified(network).copy( + value = MockNetworkStatusFactory.createVerified(network).value.copySealed(source = StatusSource.ONLY_CACHE), ) - val onlyCacheActual = runCatching { store.storeActual(userWalletId, onlyCacheStatus) } + val onlyCacheActual = runCatching { store.storeSuccess(userWalletId, onlyCacheStatus) } Truth.assertThat(onlyCacheActual.isFailure).isTrue() Truth.assertThat(onlyCacheActual.exceptionOrNull()).isInstanceOf(IllegalStateException::class.java) Truth.assertThat(onlyCacheActual.exceptionOrNull()).hasMessageThat().isEqualTo(expectedErrorMessage) + Truth.assertThat(runtimeStore.getSyncOrNull()).isEqualTo(runtimeExpected) + Truth.assertThat(persistenceStore.data.firstOrNull()).isEqualTo(persistenceExpected) } @Test fun `store actual if runtime and cache stores contain status with this network`() = runTest { - val prevStatus = MockNetworkStatusFactory.createVerified().copy( - value = MockNetworkStatusFactory.createVerified().value.copySealed(source = StatusSource.ONLY_CACHE), + val prevStatus = MockNetworkStatusFactory.createVerified(network).copy( + value = MockNetworkStatusFactory.createVerified(network).value.copySealed(source = StatusSource.ONLY_CACHE), ) runtimeStore.store( @@ -145,11 +154,11 @@ internal class NetworkStatusesStoreUpdateMethodsTest { } } - val newStatus = MockNetworkStatusFactory.createVerified().copy( - value = MockNetworkStatusFactory.createVerified().value.copySealed(source = StatusSource.ACTUAL), + val newStatus = MockNetworkStatusFactory.createVerified(network).copy( + value = MockNetworkStatusFactory.createVerified(network).value.copySealed(source = StatusSource.ACTUAL), ) - store.storeActual(userWalletId, newStatus) + store.storeSuccess(userWalletId, newStatus) val runtimeExpected = mapOf( userWalletId.stringValue to setOf(newStatus.toSimple()), @@ -165,7 +174,7 @@ internal class NetworkStatusesStoreUpdateMethodsTest { @Test fun `store actual unreachable status if cache store contains verified status`() = runTest { - val prevStatus = MockNetworkStatusFactory.createVerified() + val prevStatus = MockNetworkStatusFactory.createVerified(network) runtimeStore.store( value = mapOf(userWalletId.stringValue to setOf(prevStatus.toSimple())), @@ -177,18 +186,17 @@ internal class NetworkStatusesStoreUpdateMethodsTest { } } - val newStatus = MockNetworkStatusFactory.createUnreachable() + val newStatus = MockNetworkStatusFactory.createUnreachable(network) - store.storeActual(userWalletId, newStatus) + val actual = runCatching { store.storeSuccess(userWalletId, newStatus) } - val runtimeExpected = mapOf( - userWalletId.stringValue to setOf(newStatus.toSimple()), - ) - - val persistenceExpected = mapOf( - userWalletId.stringValue to setOf(prevStatus.toDataModel()!!), - ) + val expectedErrorMessage = "Use storeError method to save unreachable status" + val runtimeExpected = mapOf(userWalletId.stringValue to setOf(prevStatus.toSimple())) + val persistenceExpected = mapOf(userWalletId.stringValue to setOf(prevStatus.toDataModel()!!)) + Truth.assertThat(actual.isFailure).isTrue() + Truth.assertThat(actual.exceptionOrNull()).isInstanceOf(IllegalStateException::class.java) + Truth.assertThat(actual.exceptionOrNull()).hasMessageThat().isEqualTo(expectedErrorMessage) Truth.assertThat(runtimeStore.getSyncOrNull()).isEqualTo(runtimeExpected) Truth.assertThat(persistenceStore.data.firstOrNull()).isEqualTo(persistenceExpected) } @@ -212,7 +220,7 @@ internal class NetworkStatusesStoreUpdateMethodsTest { @Test fun `store error if runtime store contains status with this network`() = runTest { - val status = MockNetworkStatusFactory.createVerified().toSimple() + val status = MockNetworkStatusFactory.createVerified(network).toSimple() runtimeStore.store( value = mapOf(userWalletId.stringValue to setOf(status)), @@ -230,6 +238,48 @@ internal class NetworkStatusesStoreUpdateMethodsTest { Truth.assertThat(persistenceStore.data.firstOrNull()).isEqualTo(emptyMap>()) } + @Test + fun `store error if runtime store is empty and unreachable status was passed`() = runTest { + val status = MockNetworkStatusFactory.createUnreachable(network) + + store.storeError( + userWalletId = userWalletId, + network = network, + value = status.value as NetworkStatus.Unreachable, + ) + + val runtimeExpected = mapOf( + userWalletId.stringValue to setOf(status.toSimple()), + ) + + Truth.assertThat(runtimeStore.getSyncOrNull()).isEqualTo(runtimeExpected) + Truth.assertThat(persistenceStore.data.firstOrNull()).isEqualTo(emptyMap>()) + } + + @Test + fun `store error if runtime store contains status with this network and unreachable status was passed`() = runTest { + val status = MockNetworkStatusFactory.createVerified(network) + + runtimeStore.store( + value = mapOf(userWalletId.stringValue to setOf(status.toSimple())), + ) + + store.storeError( + userWalletId = userWalletId, + network = network, + value = MockNetworkStatusFactory.createUnreachable(network).value as NetworkStatus.Unreachable, + ) + + val runtimeExpected = mapOf( + userWalletId.stringValue to setOf( + status.copy(value = status.value.copySealed(source = StatusSource.ONLY_CACHE)).toSimple(), + ), + ) + + Truth.assertThat(runtimeStore.getSyncOrNull()).isEqualTo(runtimeExpected) + Truth.assertThat(persistenceStore.data.firstOrNull()).isEqualTo(emptyMap>()) + } + private companion object { val userWalletId = UserWalletId(stringValue = "011") diff --git a/data/networks/src/test/java/com/tangem/data/networks/store/StoreActualNetworkStatusTest.kt b/data/networks/src/test/java/com/tangem/data/networks/store/StoreActualNetworkStatusTest.kt index 0824241177..52e6f59b59 100644 --- a/data/networks/src/test/java/com/tangem/data/networks/store/StoreActualNetworkStatusTest.kt +++ b/data/networks/src/test/java/com/tangem/data/networks/store/StoreActualNetworkStatusTest.kt @@ -33,15 +33,16 @@ internal class StoreActualNetworkStatusTest(private val model: Model) { @Test fun `store actual`() = runTest { - store.storeActual(userWalletId = userWalletId, value = model.status) + val actual = runCatching { store.storeSuccess(userWalletId = userWalletId, value = model.status) } + Truth.assertThat(actual.isSuccess).isEqualTo(model.isSuccess) Truth.assertThat(runtimeStore.getSyncOrNull()).isEqualTo(model.runtimeExpected) - Truth.assertThat(persistenceStore.data.firstOrNull()).isEqualTo(model.persistenceExpected) } data class Model( val status: NetworkStatus, + val isSuccess: Boolean, val runtimeExpected: Map>, val persistenceExpected: WalletIdWithStatusDM, ) @@ -56,6 +57,7 @@ internal class StoreActualNetworkStatusTest(private val model: Model) { return listOf( Model( status = MockNetworkStatusFactory.createVerified(), + isSuccess = true, runtimeExpected = mapOf( userWalletId.stringValue to setOf( MockNetworkStatusFactory.createVerified().toSimple(), @@ -69,6 +71,7 @@ internal class StoreActualNetworkStatusTest(private val model: Model) { ), Model( status = MockNetworkStatusFactory.createNoAccount(), + isSuccess = true, runtimeExpected = mapOf( userWalletId.stringValue to setOf( MockNetworkStatusFactory.createNoAccount().toSimple(), @@ -82,6 +85,7 @@ internal class StoreActualNetworkStatusTest(private val model: Model) { ), Model( status = MockNetworkStatusFactory.createMissedDerivation(), + isSuccess = true, runtimeExpected = mapOf( userWalletId.stringValue to setOf( MockNetworkStatusFactory.createMissedDerivation().toSimple(), @@ -91,11 +95,8 @@ internal class StoreActualNetworkStatusTest(private val model: Model) { ), Model( status = MockNetworkStatusFactory.createUnreachable(), - runtimeExpected = mapOf( - userWalletId.stringValue to setOf( - MockNetworkStatusFactory.createUnreachable().toSimple(), - ), - ), + isSuccess = false, + runtimeExpected = mapOf(), persistenceExpected = mapOf(), ), ) From 3e2f1b978f0c9217bb0fceda8bb6a2a7ec06c552 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 24 Apr 2025 08:36:22 +0000 Subject: [PATCH 6/6] Updated on 2026-08-14 --- gradle/tangem_dependencies.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle/tangem_dependencies.toml b/gradle/tangem_dependencies.toml index 76affe35f0..a0bc01da42 100644 --- a/gradle/tangem_dependencies.toml +++ b/gradle/tangem_dependencies.toml @@ -5,9 +5,9 @@ # https://github.com/tangem/tangem-sdk-android/ # https://github.com/tangem/vico -tangemBlockchainSdk = "releases-5.23-1043" +tangemBlockchainSdk = "develop-1042" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds -tangemCardSdk = "releases-5.23-456" +tangemCardSdk = "develop-455" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ tangemVico = "2.0.0-alpha.25-tangem12" #tangemVico = "0.0.1" # Keep it! - used for local builds ^ @@ -21,4 +21,4 @@ card-core = { module = "com.tangem.tangem-sdk-kotlin:core", version.ref = "tange vico-compose = { group = "com.tangem.vico", name = "compose", version.ref = "tangemVico" } vico-compose-m3 = { group = "com.tangem.vico", name = "compose-m3", version.ref = "tangemVico" } -vico-core = { group = "com.tangem.vico", name = "core", version.ref = "tangemVico" } +vico-core = { group = "com.tangem.vico", name = "core", version.ref = "tangemVico" } \ No newline at end of file