Updated on 2026-08-14
This commit is contained in:
parent
4570bc334c
commit
602e20a1d2
53 changed files with 489 additions and 368 deletions
|
|
@ -161,7 +161,7 @@ dependencies {
|
|||
implementation(projects.domain.hotWallet)
|
||||
implementation(projects.domain.news)
|
||||
implementation(projects.domain.earn)
|
||||
implementation(projects.domain.tokensync)
|
||||
implementation(projects.domain.assetsdiscovery)
|
||||
implementation(projects.domain.search)
|
||||
|
||||
implementation(projects.common)
|
||||
|
|
@ -192,7 +192,7 @@ dependencies {
|
|||
implementation(projects.data.common)
|
||||
implementation(projects.data.settings)
|
||||
implementation(projects.data.tokens)
|
||||
implementation(projects.data.tokensync)
|
||||
implementation(projects.data.assetsdiscovery)
|
||||
implementation(projects.data.txhistory)
|
||||
implementation(projects.data.wallets)
|
||||
implementation(projects.data.analytics)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
package com.tangem.tap.di.domain
|
||||
|
||||
import com.tangem.domain.account.status.usecase.ManageCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.assetsdiscovery.repository.AssetsDiscoveryRepository
|
||||
import com.tangem.domain.assetsdiscovery.usecase.AcknowledgeAssetsDiscoveryCompletionUseCase
|
||||
import com.tangem.domain.assetsdiscovery.usecase.ObserveAssetsDiscoveryUseCase
|
||||
import com.tangem.domain.assetsdiscovery.usecase.StartAssetsDiscoveryUseCase
|
||||
import com.tangem.utils.coroutines.AppCoroutineScope
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal object AssetsDiscoveryDomainModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideObserveAssetsDiscoveryUseCase(
|
||||
assetsDiscoveryRepository: AssetsDiscoveryRepository,
|
||||
): ObserveAssetsDiscoveryUseCase {
|
||||
return ObserveAssetsDiscoveryUseCase(
|
||||
assetsDiscoveryRepository = assetsDiscoveryRepository,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideAcknowledgeAssetsDiscoveryCompletionUseCase(
|
||||
assetsDiscoveryRepository: AssetsDiscoveryRepository,
|
||||
): AcknowledgeAssetsDiscoveryCompletionUseCase {
|
||||
return AcknowledgeAssetsDiscoveryCompletionUseCase(
|
||||
assetsDiscoveryRepository = assetsDiscoveryRepository,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideStartAssetsDiscoveryUseCase(
|
||||
assetsDiscoveryRepository: AssetsDiscoveryRepository,
|
||||
manageCryptoCurrenciesUseCase: ManageCryptoCurrenciesUseCase,
|
||||
appCoroutineScope: AppCoroutineScope,
|
||||
): StartAssetsDiscoveryUseCase {
|
||||
return StartAssetsDiscoveryUseCase(
|
||||
assetsDiscoveryRepository = assetsDiscoveryRepository,
|
||||
manageCryptoCurrenciesUseCase = manageCryptoCurrenciesUseCase,
|
||||
appCoroutineScope = appCoroutineScope,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
package com.tangem.tap.di.domain
|
||||
|
||||
import com.tangem.domain.account.status.usecase.ManageCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.tokensync.repository.TokenSyncRepository
|
||||
import com.tangem.domain.tokensync.usecase.AcknowledgeTokenSyncCompletionUseCase
|
||||
import com.tangem.domain.tokensync.usecase.ObserveTokenSyncUseCase
|
||||
import com.tangem.domain.tokensync.usecase.StartTokenSyncUseCase
|
||||
import com.tangem.utils.coroutines.AppCoroutineScope
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal object TokenSyncDomainModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideObserveTokenSyncUseCase(tokenSyncRepository: TokenSyncRepository): ObserveTokenSyncUseCase {
|
||||
return ObserveTokenSyncUseCase(
|
||||
tokenSyncRepository = tokenSyncRepository,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideAcknowledgeTokenSyncCompletionUseCase(
|
||||
tokenSyncRepository: TokenSyncRepository,
|
||||
): AcknowledgeTokenSyncCompletionUseCase {
|
||||
return AcknowledgeTokenSyncCompletionUseCase(
|
||||
tokenSyncRepository = tokenSyncRepository,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideStartTokenSyncUseCase(
|
||||
tokenSyncRepository: TokenSyncRepository,
|
||||
manageCryptoCurrenciesUseCase: ManageCryptoCurrenciesUseCase,
|
||||
appCoroutineScope: AppCoroutineScope,
|
||||
): StartTokenSyncUseCase {
|
||||
return StartTokenSyncUseCase(
|
||||
tokenSyncRepository = tokenSyncRepository,
|
||||
manageCryptoCurrenciesUseCase = manageCryptoCurrenciesUseCase,
|
||||
appCoroutineScope = appCoroutineScope,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -73,7 +73,7 @@
|
|||
"version": "undefined"
|
||||
},
|
||||
{
|
||||
"name": "TOKEN_SYNC_ENABLED",
|
||||
"name": "ASSETS_DISCOVERY_ENABLED",
|
||||
"version": "undefined"
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ object PreferencesKeys {
|
|||
|
||||
val HAS_HAD_FIRST_TOP_UP_KEY by lazy { stringPreferencesKey(name = "hasHadFirstTopUp") }
|
||||
|
||||
val PENDING_DISCOVERY_SYNC_KEY by lazy { stringPreferencesKey(name = "pendingDiscoverySync") }
|
||||
val PENDING_ASSETS_DISCOVERY_KEY by lazy { stringPreferencesKey(name = "pendingAssetsDiscovery") }
|
||||
|
||||
// region Notifications
|
||||
val NOTIFICATIONS_APPLICATION_ID_KEY by lazy { stringPreferencesKey(name = "notificationsApplicationId") }
|
||||
|
|
|
|||
|
|
@ -7,22 +7,25 @@ plugins {
|
|||
}
|
||||
|
||||
android {
|
||||
namespace = "com.tangem.data.tokensync"
|
||||
namespace = "com.tangem.data.assetsdiscovery"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(projects.domain.tokensync)
|
||||
api(projects.domain.assetsdiscovery)
|
||||
implementation(projects.domain.tokens)
|
||||
implementation(projects.domain.tokens.models)
|
||||
implementation(projects.domain.models)
|
||||
implementation(projects.domain.walletManager)
|
||||
implementation(projects.domain.wallets)
|
||||
implementation(projects.data.common)
|
||||
implementation(projects.data.walletManager)
|
||||
implementation(projects.libs.blockchainSdk)
|
||||
implementation(projects.libs.tangemSdkApi)
|
||||
implementation(projects.core.datasource)
|
||||
implementation(projects.core.utils)
|
||||
|
||||
implementation(tangemDeps.blockchain)
|
||||
implementation(tangemDeps.card.core)
|
||||
|
||||
implementation(deps.androidx.datastore)
|
||||
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
package com.tangem.data.assetsdiscovery
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.address.AddressType
|
||||
import com.tangem.blockchainsdk.BlockchainSDKFactory
|
||||
import com.tangem.blockchainsdk.utils.toBlockchain
|
||||
import com.tangem.crypto.hdWallet.DerivationPath
|
||||
import com.tangem.data.walletmanager.extensions.makePublicKey
|
||||
import com.tangem.domain.assetsdiscovery.AssetsDiscoveryFacade
|
||||
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.common.wallets.getSyncStrict
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.wallets.config.curvesConfig
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class DefaultAssetsDiscoveryFacade @Inject constructor(
|
||||
private val blockchainSDKFactory: BlockchainSDKFactory,
|
||||
private val userWalletsListRepository: UserWalletsListRepository,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : AssetsDiscoveryFacade {
|
||||
|
||||
override suspend fun getAssetsDiscoveryService(
|
||||
userWalletId: UserWalletId,
|
||||
network: Network,
|
||||
): AssetsDiscoveryFacade.AssetsDiscoveryServiceInfo? = withContext(dispatchers.io) {
|
||||
val userWallet = userWalletsListRepository.getSyncStrict(userWalletId)
|
||||
if (userWallet !is UserWallet.Hot) return@withContext null
|
||||
|
||||
val assetsDiscoveryServiceFactory = blockchainSDKFactory.getAssetsDiscoveryServiceFactorySync()
|
||||
?: return@withContext null
|
||||
|
||||
val blockchain = network.toBlockchain()
|
||||
val address = makeAddress(userWallet, blockchain, network.derivationPath.value)
|
||||
?: return@withContext null
|
||||
|
||||
AssetsDiscoveryFacade.AssetsDiscoveryServiceInfo(
|
||||
address = address,
|
||||
service = assetsDiscoveryServiceFactory.create(blockchain),
|
||||
)
|
||||
}
|
||||
|
||||
private fun makeAddress(hotWallet: UserWallet.Hot, blockchain: Blockchain, derivationPath: String?): String? {
|
||||
val curve = hotWallet.curvesConfig.primaryCurve(blockchain)
|
||||
val selectedWallet = hotWallet.wallets.orEmpty().firstOrNull { it.curve == curve }
|
||||
?: return null
|
||||
|
||||
val path = derivationPath?.let { DerivationPath(rawPath = it) }
|
||||
|
||||
val publicKey = if (path != null) {
|
||||
makePublicKey(
|
||||
seedKey = selectedWallet.publicKey,
|
||||
blockchain = blockchain,
|
||||
derivationPath = path,
|
||||
derivedWalletKeys = selectedWallet.derivedKeys,
|
||||
isWallet2 = true,
|
||||
) ?: return null
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
return try {
|
||||
val addresses = if (publicKey != null) {
|
||||
blockchain.makeAddresses(
|
||||
walletPublicKey = publicKey.blockchainKey,
|
||||
pairPublicKey = null,
|
||||
curve = selectedWallet.curve,
|
||||
)
|
||||
} else {
|
||||
blockchain.makeAddresses(
|
||||
walletPublicKey = selectedWallet.publicKey,
|
||||
pairPublicKey = null,
|
||||
curve = selectedWallet.curve,
|
||||
)
|
||||
}
|
||||
addresses.find { it.type == AddressType.Default }?.value
|
||||
} catch (e: Throwable) {
|
||||
TangemLogger.w("Failed to derive address for $blockchain", e)
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
package com.tangem.data.assetsdiscovery.di
|
||||
|
||||
import com.tangem.blockchainsdk.BlockchainSDKFactory
|
||||
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
||||
import com.tangem.data.assetsdiscovery.DefaultAssetsDiscoveryFacade
|
||||
import com.tangem.data.assetsdiscovery.repository.DefaultAssetsDiscoveryRepository
|
||||
import com.tangem.data.assetsdiscovery.store.AssetsDiscoveryStoreFactory
|
||||
import com.tangem.data.common.currency.ResponseCryptoCurrenciesFactory
|
||||
import com.tangem.data.common.network.NetworkFactory
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||
import com.tangem.domain.assetsdiscovery.AssetsDiscoveryFacade
|
||||
import com.tangem.domain.assetsdiscovery.repository.AssetsDiscoveryRepository
|
||||
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal object AssetsDiscoveryDataModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideAssetsDiscoveryFacade(
|
||||
blockchainSDKFactory: BlockchainSDKFactory,
|
||||
userWalletsListRepository: UserWalletsListRepository,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): AssetsDiscoveryFacade = DefaultAssetsDiscoveryFacade(
|
||||
blockchainSDKFactory = blockchainSDKFactory,
|
||||
userWalletsListRepository = userWalletsListRepository,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideAssetsDiscoveryRepository(
|
||||
assetsDiscoveryFacade: AssetsDiscoveryFacade,
|
||||
tangemTechApi: TangemTechApi,
|
||||
userWalletsListRepository: UserWalletsListRepository,
|
||||
networkFactory: NetworkFactory,
|
||||
appPreferencesStore: AppPreferencesStore,
|
||||
assetsDiscoveryStoreFactory: AssetsDiscoveryStoreFactory,
|
||||
responseCryptoCurrenciesFactory: ResponseCryptoCurrenciesFactory,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
excludedBlockchains: ExcludedBlockchains,
|
||||
): AssetsDiscoveryRepository = DefaultAssetsDiscoveryRepository(
|
||||
assetsDiscoveryFacade = assetsDiscoveryFacade,
|
||||
tangemTechApi = tangemTechApi,
|
||||
userWalletsListRepository = userWalletsListRepository,
|
||||
networkFactory = networkFactory,
|
||||
appPreferencesStore = appPreferencesStore,
|
||||
assetsDiscoveryStoreFactory = assetsDiscoveryStoreFactory,
|
||||
responseCryptoCurrenciesFactory = responseCryptoCurrenciesFactory,
|
||||
dispatchers = dispatchers,
|
||||
excludedBlockchains = excludedBlockchains,
|
||||
)
|
||||
}
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
package com.tangem.data.tokensync.repository
|
||||
package com.tangem.data.assetsdiscovery.repository
|
||||
|
||||
import com.tangem.blockchain.assetsdiscovery.models.DiscoveredAsset
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.tokenbalance.models.TokenBalance
|
||||
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
||||
import com.tangem.data.assetsdiscovery.store.AssetsDiscoveryStore
|
||||
import com.tangem.data.assetsdiscovery.store.AssetsDiscoveryStoreFactory
|
||||
import com.tangem.data.common.currency.ResponseCryptoCurrenciesFactory
|
||||
import com.tangem.data.common.network.NetworkFactory
|
||||
import com.tangem.data.tokensync.store.TokenSyncStore
|
||||
import com.tangem.data.tokensync.store.TokenSyncStoreFactory
|
||||
import com.tangem.datasource.api.common.response.getOrThrow
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.api.tangemTech.models.CoinsResponse
|
||||
|
|
@ -14,15 +14,15 @@ import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
|||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||
import com.tangem.datasource.local.preferences.PreferencesKeys
|
||||
import com.tangem.datasource.local.preferences.utils.getObjectMapSync
|
||||
import com.tangem.domain.assetsdiscovery.AssetsDiscoveryFacade
|
||||
import com.tangem.domain.assetsdiscovery.model.AssetsDiscoveryProgress
|
||||
import com.tangem.domain.assetsdiscovery.repository.AssetsDiscoveryRepository
|
||||
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.common.wallets.getSyncStrict
|
||||
import com.tangem.domain.models.account.DerivationIndex
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.tokensync.model.TokenSyncProgress
|
||||
import com.tangem.domain.tokensync.repository.TokenSyncRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
import kotlinx.coroutines.async
|
||||
|
|
@ -30,42 +30,39 @@ import kotlinx.coroutines.awaitAll
|
|||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.sync.Semaphore
|
||||
import kotlinx.coroutines.sync.withPermit
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.math.BigDecimal
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class DefaultTokenSyncRepository(
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
internal class DefaultAssetsDiscoveryRepository(
|
||||
private val assetsDiscoveryFacade: AssetsDiscoveryFacade,
|
||||
private val tangemTechApi: TangemTechApi,
|
||||
private val userWalletsListRepository: UserWalletsListRepository,
|
||||
private val networkFactory: NetworkFactory,
|
||||
private val appPreferencesStore: AppPreferencesStore,
|
||||
private val tokenSyncStoreFactory: TokenSyncStoreFactory,
|
||||
private val assetsDiscoveryStoreFactory: AssetsDiscoveryStoreFactory,
|
||||
private val responseCryptoCurrenciesFactory: ResponseCryptoCurrenciesFactory,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
private val excludedBlockchains: ExcludedBlockchains,
|
||||
) : TokenSyncRepository {
|
||||
) : AssetsDiscoveryRepository {
|
||||
|
||||
private val semaphore = Semaphore(MAX_CONCURRENT_REQUESTS)
|
||||
private val progressStates = ConcurrentHashMap<String, MutableStateFlow<TokenSyncProgress>>()
|
||||
private val progressStates = ConcurrentHashMap<String, MutableStateFlow<AssetsDiscoveryProgress>>()
|
||||
|
||||
override fun observeSyncProgress(userWalletId: UserWalletId): Flow<TokenSyncProgress> {
|
||||
override fun observeDiscoveryProgress(userWalletId: UserWalletId): Flow<AssetsDiscoveryProgress> {
|
||||
return getProgressFlow(userWalletId)
|
||||
}
|
||||
|
||||
override fun acknowledgeCompletion(userWalletId: UserWalletId) {
|
||||
val key = userWalletId.stringValue
|
||||
val stateFlow = progressStates[key] ?: return
|
||||
stateFlow.value = TokenSyncProgress.Idle
|
||||
stateFlow.value = AssetsDiscoveryProgress.Idle
|
||||
progressStates.remove(key, stateFlow)
|
||||
}
|
||||
|
||||
override suspend fun getDiscoveredCurrencies(userWalletId: UserWalletId): List<CryptoCurrency> {
|
||||
val tokenSyncStore = tokenSyncStoreFactory.provide(userWalletId)
|
||||
val storedTokens = tokenSyncStore.get()
|
||||
val assetsDiscoveryStore = assetsDiscoveryStoreFactory.provide(userWalletId)
|
||||
val storedTokens = assetsDiscoveryStore.get()
|
||||
if (storedTokens.isEmpty()) return emptyList()
|
||||
|
||||
val userWallet = userWalletsListRepository.getSyncStrict(userWalletId)
|
||||
|
|
@ -77,34 +74,34 @@ internal class DefaultTokenSyncRepository(
|
|||
}
|
||||
|
||||
override suspend fun clearDiscoveredTokens(userWalletId: UserWalletId) {
|
||||
val tokenSyncStore = tokenSyncStoreFactory.provide(userWalletId)
|
||||
tokenSyncStore.clear()
|
||||
val assetsDiscoveryStore = assetsDiscoveryStoreFactory.provide(userWalletId)
|
||||
assetsDiscoveryStore.clear()
|
||||
}
|
||||
|
||||
override suspend fun clearPendingFlag(userWalletId: UserWalletId) {
|
||||
setPendingFlag(userWalletId, value = false)
|
||||
}
|
||||
|
||||
override suspend fun getPendingSyncWalletIds(): List<UserWalletId> {
|
||||
override suspend fun getPendingDiscoveryWalletIds(): List<UserWalletId> {
|
||||
val pendingMap = appPreferencesStore
|
||||
.getObjectMapSync<Boolean>(PreferencesKeys.PENDING_DISCOVERY_SYNC_KEY)
|
||||
.getObjectMapSync<Boolean>(PreferencesKeys.PENDING_ASSETS_DISCOVERY_KEY)
|
||||
return pendingMap
|
||||
.filter { it.value }
|
||||
.map { UserWalletId(it.key) }
|
||||
}
|
||||
|
||||
override suspend fun runSync(userWalletId: UserWalletId) {
|
||||
override suspend fun runDiscovery(userWalletId: UserWalletId) {
|
||||
val networks = getSupportedNetworks(userWalletId)
|
||||
|
||||
if (networks.isEmpty()) return
|
||||
|
||||
setPendingFlag(userWalletId, value = true)
|
||||
val tokenSyncStore = tokenSyncStoreFactory.provide(userWalletId)
|
||||
tokenSyncStore.clear()
|
||||
val assetsDiscoveryStore = assetsDiscoveryStoreFactory.provide(userWalletId)
|
||||
assetsDiscoveryStore.clear()
|
||||
|
||||
val batches = networks.chunked(MAX_CONCURRENT_REQUESTS)
|
||||
var completedNetworks = 0
|
||||
getProgressFlow(userWalletId).value = TokenSyncProgress.InProgress(
|
||||
getProgressFlow(userWalletId).value = AssetsDiscoveryProgress.InProgress(
|
||||
completedNetworks = 0,
|
||||
totalNetworks = networks.size,
|
||||
)
|
||||
|
|
@ -114,25 +111,23 @@ internal class DefaultTokenSyncRepository(
|
|||
completedNetworks = handleBatchResults(
|
||||
userWalletId = userWalletId,
|
||||
results = batchResults,
|
||||
tokenSyncStore = tokenSyncStore,
|
||||
assetsDiscoveryStore = assetsDiscoveryStore,
|
||||
completedNetworks = completedNetworks,
|
||||
totalNetworks = networks.size,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun completeSync(userWalletId: UserWalletId) {
|
||||
override suspend fun completeDiscovery(userWalletId: UserWalletId) {
|
||||
setPendingFlag(userWalletId, value = false)
|
||||
getProgressFlow(userWalletId).value = TokenSyncProgress.Completed
|
||||
getProgressFlow(userWalletId).value = AssetsDiscoveryProgress.Completed
|
||||
}
|
||||
|
||||
private suspend fun processBatch(userWalletId: UserWalletId, batch: List<Network>): List<NetworkResult> {
|
||||
return coroutineScope {
|
||||
batch.map { network ->
|
||||
async(dispatchers.io) {
|
||||
semaphore.withPermit {
|
||||
processNetwork(userWalletId, network)
|
||||
}
|
||||
processNetwork(userWalletId, network)
|
||||
}
|
||||
}.awaitAll()
|
||||
}
|
||||
|
|
@ -141,7 +136,7 @@ internal class DefaultTokenSyncRepository(
|
|||
private suspend fun handleBatchResults(
|
||||
userWalletId: UserWalletId,
|
||||
results: List<NetworkResult>,
|
||||
tokenSyncStore: TokenSyncStore,
|
||||
assetsDiscoveryStore: AssetsDiscoveryStore,
|
||||
completedNetworks: Int,
|
||||
totalNetworks: Int,
|
||||
): Int {
|
||||
|
|
@ -150,8 +145,8 @@ internal class DefaultTokenSyncRepository(
|
|||
|
||||
for (result in results) {
|
||||
completed++
|
||||
handleNetworkResult(result, tokenSyncStore)
|
||||
progressFlow.value = TokenSyncProgress.InProgress(
|
||||
handleNetworkResult(result, assetsDiscoveryStore)
|
||||
progressFlow.value = AssetsDiscoveryProgress.InProgress(
|
||||
completedNetworks = completed,
|
||||
totalNetworks = totalNetworks,
|
||||
)
|
||||
|
|
@ -160,35 +155,35 @@ internal class DefaultTokenSyncRepository(
|
|||
return completed
|
||||
}
|
||||
|
||||
private suspend fun handleNetworkResult(result: NetworkResult, tokenSyncStore: TokenSyncStore) {
|
||||
private suspend fun handleNetworkResult(result: NetworkResult, assetsDiscoveryStore: AssetsDiscoveryStore) {
|
||||
when (result) {
|
||||
is NetworkResult.Success -> {
|
||||
if (result.responseTokens.isNotEmpty()) {
|
||||
try {
|
||||
tokenSyncStore.append(result.responseTokens)
|
||||
assetsDiscoveryStore.append(result.responseTokens)
|
||||
} catch (e: Exception) {
|
||||
TangemLogger.e("Failed to store discovered tokens for network: ${result.networkId}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
is NetworkResult.Error -> {
|
||||
TangemLogger.e("Token sync failed for network: ${result.networkId}", result.cause)
|
||||
TangemLogger.e("Assets discovery failed for network: ${result.networkId}", result.cause)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun processNetwork(userWalletId: UserWalletId, network: Network): NetworkResult {
|
||||
return try {
|
||||
val tokenBalances = fetchAndFilterTokenBalances(userWalletId, network)
|
||||
val discoveredAssets = discoverAndFilterAssets(userWalletId, network)
|
||||
|
||||
if (tokenBalances.isEmpty()) {
|
||||
if (discoveredAssets.isEmpty()) {
|
||||
return NetworkResult.Success(
|
||||
networkId = network.rawId,
|
||||
responseTokens = emptyList(),
|
||||
)
|
||||
}
|
||||
|
||||
val enrichedTokens = enrichTokensWithCatalog(tokenBalances, network)
|
||||
val enrichedTokens = enrichTokensWithCatalog(discoveredAssets, network)
|
||||
|
||||
val responseTokens = enrichedTokens
|
||||
.filter { it.contractAddress != null }
|
||||
|
|
@ -203,36 +198,35 @@ internal class DefaultTokenSyncRepository(
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun fetchAndFilterTokenBalances(userWalletId: UserWalletId, network: Network): List<TokenBalance> {
|
||||
return withContext(dispatchers.io) {
|
||||
walletManagersFacade.getTokenBalances(userWalletId, network)
|
||||
private suspend fun discoverAndFilterAssets(userWalletId: UserWalletId, network: Network): List<DiscoveredAsset> =
|
||||
withContext(dispatchers.io) {
|
||||
val providerInfo = assetsDiscoveryFacade.getAssetsDiscoveryService(userWalletId, network)
|
||||
?: return@withContext emptyList()
|
||||
providerInfo.service.discoverAssets(providerInfo.address)
|
||||
.filter { it.amount > BigDecimal.ZERO }
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun enrichTokensWithCatalog(
|
||||
tokenBalances: List<TokenBalance>,
|
||||
assets: List<DiscoveredAsset>,
|
||||
network: Network,
|
||||
): List<DiscoveredToken> = withContext(dispatchers.io) {
|
||||
val tokensToEnrich = tokenBalances.filter { !it.isNativeToken }
|
||||
): List<EnrichedDiscoveredAsset> = withContext(dispatchers.io) {
|
||||
val tokensToEnrich = assets.filterIsInstance<DiscoveredAsset.Token>()
|
||||
|
||||
val catalogMap = fetchCatalogInfo(
|
||||
networkId = network.rawId,
|
||||
contractAddresses = tokensToEnrich.mapNotNull(TokenBalance::contractAddress),
|
||||
contractAddresses = tokensToEnrich.map { it.contractAddress },
|
||||
)
|
||||
|
||||
tokenBalances.mapNotNull { balance ->
|
||||
if (balance.isNativeToken) return@mapNotNull null
|
||||
|
||||
val contractAddressLower = balance.contractAddress?.lowercase()
|
||||
val coin = contractAddressLower?.let { catalogMap[it] } ?: return@mapNotNull null
|
||||
tokensToEnrich.mapNotNull { balance ->
|
||||
val contractAddressLower = balance.contractAddress.lowercase()
|
||||
val coin = catalogMap[contractAddressLower] ?: return@mapNotNull null
|
||||
val decimals = coin.networks
|
||||
.find { it.contractAddress?.lowercase() == contractAddressLower }
|
||||
?.decimalCount
|
||||
?.toInt()
|
||||
?: 0
|
||||
|
||||
DiscoveredToken(
|
||||
EnrichedDiscoveredAsset(
|
||||
contractAddress = balance.contractAddress,
|
||||
symbol = coin.symbol,
|
||||
name = coin.name,
|
||||
|
|
@ -290,23 +284,23 @@ internal class DefaultTokenSyncRepository(
|
|||
}
|
||||
}
|
||||
|
||||
private fun getProgressFlow(userWalletId: UserWalletId): MutableStateFlow<TokenSyncProgress> {
|
||||
private fun getProgressFlow(userWalletId: UserWalletId): MutableStateFlow<AssetsDiscoveryProgress> {
|
||||
return progressStates.getOrPut(userWalletId.stringValue) {
|
||||
MutableStateFlow(TokenSyncProgress.Idle)
|
||||
MutableStateFlow(AssetsDiscoveryProgress.Idle)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun setPendingFlag(userWalletId: UserWalletId, value: Boolean) {
|
||||
appPreferencesStore.editData { prefs ->
|
||||
prefs.setObjectMap(
|
||||
key = PreferencesKeys.PENDING_DISCOVERY_SYNC_KEY,
|
||||
value = prefs.getObjectMap<Boolean>(PreferencesKeys.PENDING_DISCOVERY_SYNC_KEY)
|
||||
key = PreferencesKeys.PENDING_ASSETS_DISCOVERY_KEY,
|
||||
value = prefs.getObjectMap<Boolean>(PreferencesKeys.PENDING_ASSETS_DISCOVERY_KEY)
|
||||
.plus(userWalletId.stringValue to value),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun DiscoveredToken.toResponseToken(): UserTokensResponse.Token {
|
||||
private fun EnrichedDiscoveredAsset.toResponseToken(): UserTokensResponse.Token {
|
||||
return UserTokensResponse.Token(
|
||||
id = currencyId,
|
||||
networkId = networkId,
|
||||
|
|
@ -317,7 +311,7 @@ internal class DefaultTokenSyncRepository(
|
|||
)
|
||||
}
|
||||
|
||||
private data class DiscoveredToken(
|
||||
private data class EnrichedDiscoveredAsset(
|
||||
val contractAddress: String?,
|
||||
val symbol: String,
|
||||
val name: String,
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
package com.tangem.data.tokensync.store
|
||||
package com.tangem.data.assetsdiscovery.store
|
||||
|
||||
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
||||
|
||||
interface TokenSyncStore {
|
||||
interface AssetsDiscoveryStore {
|
||||
|
||||
suspend fun get(): List<UserTokensResponse.Token>
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.data.tokensync.store
|
||||
package com.tangem.data.assetsdiscovery.store
|
||||
|
||||
import android.content.Context
|
||||
import androidx.datastore.core.DataStore
|
||||
|
|
@ -17,18 +17,18 @@ import javax.inject.Inject
|
|||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class TokenSyncStoreFactory @Inject constructor(
|
||||
class AssetsDiscoveryStoreFactory @Inject constructor(
|
||||
@NetworkMoshi private val moshi: Moshi,
|
||||
@ApplicationContext private val context: Context,
|
||||
private val appScope: AppCoroutineScope,
|
||||
) {
|
||||
|
||||
private val stores = ConcurrentHashMap<String, TokenSyncStore>()
|
||||
private val stores = ConcurrentHashMap<String, AssetsDiscoveryStore>()
|
||||
|
||||
fun provide(userWalletId: UserWalletId): TokenSyncStore {
|
||||
fun provide(userWalletId: UserWalletId): AssetsDiscoveryStore {
|
||||
val userWalletStringId = userWalletId.formatted()
|
||||
return stores.computeIfAbsent(userWalletStringId) {
|
||||
DefaultTokenSyncStore(
|
||||
DefaultAssetsDiscoveryStore(
|
||||
persistenceStore = createPersistenceStore(
|
||||
fileName = "token_sync_$userWalletStringId",
|
||||
types = listTypes<UserTokensResponse.Token>(),
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
package com.tangem.data.tokensync.store
|
||||
package com.tangem.data.assetsdiscovery.store
|
||||
|
||||
import androidx.datastore.core.DataStore
|
||||
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
|
||||
internal class DefaultTokenSyncStore(
|
||||
internal class DefaultAssetsDiscoveryStore(
|
||||
private val persistenceStore: DataStore<List<UserTokensResponse.Token>>,
|
||||
) : TokenSyncStore {
|
||||
) : AssetsDiscoveryStore {
|
||||
|
||||
override suspend fun get(): List<UserTokensResponse.Token> {
|
||||
return persistenceStore.data.firstOrNull().orEmpty()
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
package com.tangem.data.tokensync.di
|
||||
|
||||
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
||||
import com.tangem.data.common.currency.ResponseCryptoCurrenciesFactory
|
||||
import com.tangem.data.common.network.NetworkFactory
|
||||
import com.tangem.data.tokensync.repository.DefaultTokenSyncRepository
|
||||
import com.tangem.data.tokensync.store.TokenSyncStoreFactory
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.tokensync.repository.TokenSyncRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal object TokenSyncDataModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideTokenSyncRepository(
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
tangemTechApi: TangemTechApi,
|
||||
userWalletsListRepository: UserWalletsListRepository,
|
||||
networkFactory: NetworkFactory,
|
||||
appPreferencesStore: AppPreferencesStore,
|
||||
tokenSyncStoreFactory: TokenSyncStoreFactory,
|
||||
responseCryptoCurrenciesFactory: ResponseCryptoCurrenciesFactory,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
excludedBlockchains: ExcludedBlockchains,
|
||||
): TokenSyncRepository {
|
||||
return DefaultTokenSyncRepository(
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
tangemTechApi = tangemTechApi,
|
||||
userWalletsListRepository = userWalletsListRepository,
|
||||
networkFactory = networkFactory,
|
||||
appPreferencesStore = appPreferencesStore,
|
||||
tokenSyncStoreFactory = tokenSyncStoreFactory,
|
||||
responseCryptoCurrenciesFactory = responseCryptoCurrenciesFactory,
|
||||
dispatchers = dispatchers,
|
||||
excludedBlockchains = excludedBlockchains,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -19,7 +19,6 @@ import com.tangem.blockchain.extensions.Result
|
|||
import com.tangem.blockchain.extensions.SimpleResult
|
||||
import com.tangem.blockchain.nft.models.NFTAsset
|
||||
import com.tangem.blockchain.nft.models.NFTCollection
|
||||
import com.tangem.blockchain.tokenbalance.models.TokenBalance
|
||||
import com.tangem.blockchain.transactionhistory.models.TransactionHistoryRequest
|
||||
import com.tangem.blockchain.yieldsupply.YieldSupplyContractCallDataProviderFactory
|
||||
import com.tangem.blockchainsdk.BlockchainSDKFactory
|
||||
|
|
@ -850,17 +849,6 @@ internal class DefaultWalletManagersFacade @Inject constructor(
|
|||
return blockchain.getNFTExploreUrl(assetIdentifier)
|
||||
}
|
||||
|
||||
override suspend fun getTokenBalances(userWalletId: UserWalletId, network: Network): List<TokenBalance> {
|
||||
val blockchain = network.toBlockchain()
|
||||
val walletManager = getOrCreateWalletManager(
|
||||
userWalletId = userWalletId,
|
||||
blockchain = blockchain,
|
||||
derivationPath = network.derivationPath.value,
|
||||
) ?: return emptyList()
|
||||
val address = walletManager.wallet.address
|
||||
return walletManager.getTokenBalances(address)
|
||||
}
|
||||
|
||||
override suspend fun isAccountInitialized(userWalletId: UserWalletId, network: Network): Boolean {
|
||||
val walletManager = getOrCreateWalletManager(userWalletId = userWalletId, network = network)
|
||||
val initializableAccountWalletManger = walletManager as? InitializableAccount ?: return true
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ plugins {
|
|||
}
|
||||
|
||||
android {
|
||||
namespace = "com.tangem.domain.tokensync"
|
||||
namespace = "com.tangem.domain.assetsdiscovery"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
|
@ -14,6 +14,9 @@ dependencies {
|
|||
implementation(projects.domain.account.status)
|
||||
implementation(projects.core.utils)
|
||||
|
||||
implementation(projects.libs.blockchainSdk)
|
||||
implementation(tangemDeps.blockchain)
|
||||
|
||||
implementation(deps.kotlin.coroutines)
|
||||
implementation(deps.arrow.core)
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package com.tangem.domain.assetsdiscovery
|
||||
|
||||
import com.tangem.blockchain.assetsdiscovery.AssetsDiscoveryService
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
|
||||
interface AssetsDiscoveryFacade {
|
||||
|
||||
suspend fun getAssetsDiscoveryService(userWalletId: UserWalletId, network: Network): AssetsDiscoveryServiceInfo?
|
||||
|
||||
data class AssetsDiscoveryServiceInfo(
|
||||
val address: String,
|
||||
val service: AssetsDiscoveryService,
|
||||
)
|
||||
}
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
package com.tangem.domain.tokensync.model
|
||||
package com.tangem.domain.assetsdiscovery.model
|
||||
|
||||
sealed class TokenSyncProgress {
|
||||
sealed class AssetsDiscoveryProgress {
|
||||
|
||||
data object Idle : TokenSyncProgress()
|
||||
data object Idle : AssetsDiscoveryProgress()
|
||||
|
||||
data class InProgress(
|
||||
val completedNetworks: Int,
|
||||
val totalNetworks: Int,
|
||||
) : TokenSyncProgress() {
|
||||
) : AssetsDiscoveryProgress() {
|
||||
val progressPercent: Int
|
||||
get() = if (totalNetworks > 0) {
|
||||
completedNetworks * 100 / totalNetworks
|
||||
|
|
@ -16,5 +16,5 @@ sealed class TokenSyncProgress {
|
|||
}
|
||||
}
|
||||
|
||||
data object Completed : TokenSyncProgress()
|
||||
data object Completed : AssetsDiscoveryProgress()
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package com.tangem.domain.assetsdiscovery.repository
|
||||
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.assetsdiscovery.model.AssetsDiscoveryProgress
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface AssetsDiscoveryRepository {
|
||||
|
||||
suspend fun runDiscovery(userWalletId: UserWalletId)
|
||||
|
||||
suspend fun completeDiscovery(userWalletId: UserWalletId)
|
||||
|
||||
suspend fun getPendingDiscoveryWalletIds(): List<UserWalletId>
|
||||
|
||||
fun observeDiscoveryProgress(userWalletId: UserWalletId): Flow<AssetsDiscoveryProgress>
|
||||
|
||||
fun acknowledgeCompletion(userWalletId: UserWalletId)
|
||||
|
||||
suspend fun clearPendingFlag(userWalletId: UserWalletId)
|
||||
|
||||
suspend fun getDiscoveredCurrencies(userWalletId: UserWalletId): List<CryptoCurrency>
|
||||
|
||||
suspend fun clearDiscoveredTokens(userWalletId: UserWalletId)
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package com.tangem.domain.assetsdiscovery.usecase
|
||||
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.assetsdiscovery.repository.AssetsDiscoveryRepository
|
||||
|
||||
class AcknowledgeAssetsDiscoveryCompletionUseCase(
|
||||
private val assetsDiscoveryRepository: AssetsDiscoveryRepository,
|
||||
) {
|
||||
|
||||
operator fun invoke(userWalletId: UserWalletId) {
|
||||
assetsDiscoveryRepository.acknowledgeCompletion(userWalletId)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package com.tangem.domain.assetsdiscovery.usecase
|
||||
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.assetsdiscovery.model.AssetsDiscoveryProgress
|
||||
import com.tangem.domain.assetsdiscovery.repository.AssetsDiscoveryRepository
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class ObserveAssetsDiscoveryUseCase(
|
||||
private val assetsDiscoveryRepository: AssetsDiscoveryRepository,
|
||||
) {
|
||||
|
||||
operator fun invoke(userWalletId: UserWalletId): Flow<AssetsDiscoveryProgress> {
|
||||
return assetsDiscoveryRepository.observeDiscoveryProgress(userWalletId)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +1,18 @@
|
|||
package com.tangem.domain.tokensync.usecase
|
||||
package com.tangem.domain.assetsdiscovery.usecase
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.domain.account.status.usecase.ManageCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.tokensync.repository.TokenSyncRepository
|
||||
import com.tangem.domain.assetsdiscovery.repository.AssetsDiscoveryRepository
|
||||
import com.tangem.utils.coroutines.AppCoroutineScope
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
class StartTokenSyncUseCase(
|
||||
private val tokenSyncRepository: TokenSyncRepository,
|
||||
class StartAssetsDiscoveryUseCase(
|
||||
private val assetsDiscoveryRepository: AssetsDiscoveryRepository,
|
||||
private val manageCryptoCurrenciesUseCase: ManageCryptoCurrenciesUseCase,
|
||||
private val appCoroutineScope: AppCoroutineScope,
|
||||
) {
|
||||
|
|
@ -23,9 +23,9 @@ class StartTokenSyncUseCase(
|
|||
activeSyncJobs[userWalletId]?.cancel()
|
||||
activeSyncJobs[userWalletId] = appCoroutineScope.launch {
|
||||
try {
|
||||
tokenSyncRepository.runSync(userWalletId)
|
||||
assetsDiscoveryRepository.runDiscovery(userWalletId)
|
||||
applyDiscoveredTokens(userWalletId)
|
||||
tokenSyncRepository.completeSync(userWalletId)
|
||||
assetsDiscoveryRepository.completeDiscovery(userWalletId)
|
||||
} catch (e: Exception) {
|
||||
TangemLogger.e("Token sync failed for wallet: $userWalletId", e)
|
||||
} finally {
|
||||
|
|
@ -36,18 +36,18 @@ class StartTokenSyncUseCase(
|
|||
|
||||
suspend fun cancel(userWalletId: UserWalletId): Either<Throwable, Unit> = Either.catch {
|
||||
activeSyncJobs.remove(userWalletId)?.cancel()
|
||||
tokenSyncRepository.clearPendingFlag(userWalletId)
|
||||
tokenSyncRepository.clearDiscoveredTokens(userWalletId)
|
||||
assetsDiscoveryRepository.clearPendingFlag(userWalletId)
|
||||
assetsDiscoveryRepository.clearDiscoveredTokens(userWalletId)
|
||||
}
|
||||
|
||||
fun applyPendingSyncs() {
|
||||
fun applyPendingAssetsDiscovery() {
|
||||
appCoroutineScope.launch {
|
||||
try {
|
||||
val pendingIds = tokenSyncRepository.getPendingSyncWalletIds()
|
||||
val pendingIds = assetsDiscoveryRepository.getPendingDiscoveryWalletIds()
|
||||
for (walletId in pendingIds) {
|
||||
val isApplied = applyDiscoveredTokens(walletId)
|
||||
if (isApplied) {
|
||||
tokenSyncRepository.clearPendingFlag(walletId)
|
||||
assetsDiscoveryRepository.clearPendingFlag(walletId)
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
|
|
@ -57,7 +57,7 @@ class StartTokenSyncUseCase(
|
|||
}
|
||||
|
||||
private suspend fun applyDiscoveredTokens(userWalletId: UserWalletId): Boolean {
|
||||
val currencies = tokenSyncRepository.getDiscoveredCurrencies(userWalletId)
|
||||
val currencies = assetsDiscoveryRepository.getDiscoveredCurrencies(userWalletId)
|
||||
|
||||
if (currencies.isEmpty()) return true
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ class StartTokenSyncUseCase(
|
|||
add = currencies,
|
||||
).fold(
|
||||
ifRight = {
|
||||
tokenSyncRepository.clearDiscoveredTokens(userWalletId)
|
||||
assetsDiscoveryRepository.clearDiscoveredTokens(userWalletId)
|
||||
true
|
||||
},
|
||||
ifLeft = { error ->
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
package com.tangem.domain.tokensync.repository
|
||||
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.tokensync.model.TokenSyncProgress
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface TokenSyncRepository {
|
||||
|
||||
suspend fun runSync(userWalletId: UserWalletId)
|
||||
|
||||
suspend fun completeSync(userWalletId: UserWalletId)
|
||||
|
||||
suspend fun getPendingSyncWalletIds(): List<UserWalletId>
|
||||
|
||||
fun observeSyncProgress(userWalletId: UserWalletId): Flow<TokenSyncProgress>
|
||||
|
||||
fun acknowledgeCompletion(userWalletId: UserWalletId)
|
||||
|
||||
suspend fun clearPendingFlag(userWalletId: UserWalletId)
|
||||
|
||||
suspend fun getDiscoveredCurrencies(userWalletId: UserWalletId): List<CryptoCurrency>
|
||||
|
||||
suspend fun clearDiscoveredTokens(userWalletId: UserWalletId)
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
package com.tangem.domain.tokensync.usecase
|
||||
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.tokensync.repository.TokenSyncRepository
|
||||
|
||||
class AcknowledgeTokenSyncCompletionUseCase(
|
||||
private val tokenSyncRepository: TokenSyncRepository,
|
||||
) {
|
||||
|
||||
operator fun invoke(userWalletId: UserWalletId) {
|
||||
tokenSyncRepository.acknowledgeCompletion(userWalletId)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
package com.tangem.domain.tokensync.usecase
|
||||
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.tokensync.model.TokenSyncProgress
|
||||
import com.tangem.domain.tokensync.repository.TokenSyncRepository
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class ObserveTokenSyncUseCase(
|
||||
private val tokenSyncRepository: TokenSyncRepository,
|
||||
) {
|
||||
|
||||
operator fun invoke(userWalletId: UserWalletId): Flow<TokenSyncProgress> {
|
||||
return tokenSyncRepository.observeSyncProgress(userWalletId)
|
||||
}
|
||||
}
|
||||
|
|
@ -12,7 +12,6 @@ import com.tangem.blockchain.extensions.Result
|
|||
import com.tangem.blockchain.extensions.SimpleResult
|
||||
import com.tangem.blockchain.nft.models.NFTAsset
|
||||
import com.tangem.blockchain.nft.models.NFTCollection
|
||||
import com.tangem.blockchain.tokenbalance.models.TokenBalance
|
||||
import com.tangem.blockchainsdk.models.UpdateWalletManagerResult
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.Network
|
||||
|
|
@ -282,8 +281,6 @@ interface WalletManagersFacade {
|
|||
|
||||
suspend fun getNFTExploreUrl(network: Network, assetIdentifier: NFTAsset.Identifier): String?
|
||||
|
||||
suspend fun getTokenBalances(userWalletId: UserWalletId, network: Network): List<TokenBalance>
|
||||
|
||||
/**
|
||||
* If wallet manager implements [InitializableAccount] then returns [InitializableAccount.isAccountInitialized]
|
||||
* value. Otherwise always return true
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ internal class PreviewDetailsComponent : DetailsComponent {
|
|||
router = DummyRouter(),
|
||||
hotWalletFeatureToggles = object : HotWalletFeatureToggles {
|
||||
override val isWalletCreationRestrictionEnabled: Boolean = true
|
||||
override val isTokenSyncEnabled: Boolean = true
|
||||
override val isAssetsDiscoveryEnabled: Boolean = true
|
||||
},
|
||||
).buildAll(
|
||||
isWalletConnectAvailable = true,
|
||||
|
|
|
|||
|
|
@ -2,5 +2,5 @@ package com.tangem.features.hotwallet
|
|||
|
||||
interface HotWalletFeatureToggles {
|
||||
val isWalletCreationRestrictionEnabled: Boolean
|
||||
val isTokenSyncEnabled: Boolean
|
||||
val isAssetsDiscoveryEnabled: Boolean
|
||||
}
|
||||
|
|
@ -38,7 +38,7 @@ dependencies {
|
|||
implementation(projects.domain.feedback)
|
||||
implementation(projects.domain.feedback.models)
|
||||
implementation(projects.domain.hotWallet)
|
||||
implementation(projects.domain.tokensync)
|
||||
implementation(projects.domain.assetsdiscovery)
|
||||
|
||||
/** Common */
|
||||
implementation(projects.common.ui)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,6 @@ internal class DefaultHotWalletFeatureToggles(
|
|||
override val isWalletCreationRestrictionEnabled: Boolean
|
||||
get() = featureTogglesManager.isFeatureEnabled(FeatureToggles.HOT_WALLET_CREATION_RESTRICTION_ENABLED)
|
||||
|
||||
override val isTokenSyncEnabled: Boolean
|
||||
get() = featureTogglesManager.isFeatureEnabled(FeatureToggles.TOKEN_SYNC_ENABLED)
|
||||
override val isAssetsDiscoveryEnabled: Boolean
|
||||
get() = featureTogglesManager.isFeatureEnabled(FeatureToggles.ASSETS_DISCOVERY_ENABLED)
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@ import com.tangem.core.ui.extensions.wrappedList
|
|||
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.settings.CanUseBiometryUseCase
|
||||
import com.tangem.domain.tokensync.usecase.StartTokenSyncUseCase
|
||||
import com.tangem.domain.assetsdiscovery.usecase.StartAssetsDiscoveryUseCase
|
||||
import com.tangem.domain.wallets.hot.HotWalletAccessCodeAttemptsRepository
|
||||
import com.tangem.domain.wallets.hot.HotWalletAccessCodeAttemptsRepository.Attempts
|
||||
import com.tangem.domain.wallets.hot.HotWalletAccessCodeAttemptsRepository.Companion.MAX_FAST_FORWARD_ATTEMPTS
|
||||
|
|
@ -39,7 +39,7 @@ internal class HotAccessCodeRequestModel @Inject constructor(
|
|||
private val userWalletsListRepository: UserWalletsListRepository,
|
||||
private val canUseBiometryUseCase: CanUseBiometryUseCase,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
private val startTokenSyncUseCase: StartTokenSyncUseCase,
|
||||
private val startAssetsDiscoveryUseCase: StartAssetsDiscoveryUseCase,
|
||||
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
) : Model() {
|
||||
|
||||
|
|
@ -220,8 +220,8 @@ internal class HotAccessCodeRequestModel @Inject constructor(
|
|||
val userWallet = userWalletsListRepository.userWalletsSync()
|
||||
.firstOrNull { it is UserWallet.Hot && it.hotWalletId == currentRequest.hotWalletId } ?: return
|
||||
|
||||
if (hotWalletFeatureToggles.isTokenSyncEnabled) {
|
||||
startTokenSyncUseCase.cancel(userWallet.walletId)
|
||||
if (hotWalletFeatureToggles.isAssetsDiscoveryEnabled) {
|
||||
startAssetsDiscoveryUseCase.cancel(userWallet.walletId)
|
||||
}
|
||||
|
||||
userWalletsListRepository.delete(listOf(userWallet.walletId))
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import com.tangem.core.ui.message.bottomSheetMessage
|
|||
import com.tangem.crypto.bip39.Mnemonic
|
||||
import com.tangem.datasource.local.appsflyer.AppsFlyerStore
|
||||
import com.tangem.domain.common.wallets.error.SaveWalletError
|
||||
import com.tangem.domain.tokensync.usecase.StartTokenSyncUseCase
|
||||
import com.tangem.domain.assetsdiscovery.usecase.StartAssetsDiscoveryUseCase
|
||||
import com.tangem.domain.wallets.builder.HotUserWalletBuilder
|
||||
import com.tangem.domain.wallets.usecase.SaveWalletUseCase
|
||||
import com.tangem.features.hotwallet.HotWalletFeatureToggles
|
||||
|
|
@ -42,7 +42,7 @@ internal class AddExistingWalletImportModel @Inject constructor(
|
|||
private val tangemHotSdk: TangemHotSdk,
|
||||
private val hotUserWalletBuilderFactory: HotUserWalletBuilder.Factory,
|
||||
private val saveUserWalletUseCase: SaveWalletUseCase,
|
||||
private val startTokenSyncUseCase: StartTokenSyncUseCase,
|
||||
private val startAssetsDiscoveryUseCase: StartAssetsDiscoveryUseCase,
|
||||
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
@GlobalUiMessageSender private val uiMessageSender: UiMessageSender,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
|
|
@ -114,8 +114,8 @@ internal class AddExistingWalletImportModel @Inject constructor(
|
|||
.onRight {
|
||||
setImportProgress(false)
|
||||
|
||||
if (hotWalletFeatureToggles.isTokenSyncEnabled) {
|
||||
startTokenSyncUseCase(userWallet.walletId)
|
||||
if (hotWalletFeatureToggles.isAssetsDiscoveryEnabled) {
|
||||
startAssetsDiscoveryUseCase(userWallet.walletId)
|
||||
}
|
||||
|
||||
analyticsEventHandler.send(
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import com.tangem.core.ui.extensions.resourceReference
|
|||
import com.tangem.core.ui.message.DialogMessage
|
||||
import com.tangem.core.ui.message.EventMessageAction
|
||||
import com.tangem.core.ui.message.SnackbarMessage
|
||||
import com.tangem.domain.tokensync.usecase.StartTokenSyncUseCase
|
||||
import com.tangem.domain.assetsdiscovery.usecase.StartAssetsDiscoveryUseCase
|
||||
import com.tangem.domain.wallets.usecase.DeleteWalletUseCase
|
||||
import com.tangem.features.hotwallet.ForgetWalletComponent
|
||||
import com.tangem.features.hotwallet.HotWalletFeatureToggles
|
||||
|
|
@ -33,7 +33,7 @@ internal class ForgetWalletModel @Inject constructor(
|
|||
private val router: Router,
|
||||
private val deleteWalletUseCase: DeleteWalletUseCase,
|
||||
private val uiMessageSender: UiMessageSender,
|
||||
private val startTokenSyncUseCase: StartTokenSyncUseCase,
|
||||
private val startAssetsDiscoveryUseCase: StartAssetsDiscoveryUseCase,
|
||||
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
) : Model() {
|
||||
|
||||
|
|
@ -84,8 +84,8 @@ internal class ForgetWalletModel @Inject constructor(
|
|||
|
||||
private fun forgetWallet() {
|
||||
modelScope.launch {
|
||||
if (hotWalletFeatureToggles.isTokenSyncEnabled) {
|
||||
startTokenSyncUseCase.cancel(params.userWalletId)
|
||||
if (hotWalletFeatureToggles.isAssetsDiscoveryEnabled) {
|
||||
startAssetsDiscoveryUseCase.cancel(params.userWalletId)
|
||||
}
|
||||
|
||||
val hasUserWallets = deleteWalletUseCase(params.userWalletId)
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ dependencies {
|
|||
implementation(projects.domain.settings)
|
||||
implementation(projects.domain.notifications.models)
|
||||
implementation(projects.domain.notifications)
|
||||
implementation(projects.domain.tokensync)
|
||||
implementation(projects.domain.assetsdiscovery)
|
||||
|
||||
/* AndroidX */
|
||||
implementation(deps.androidx.fragment.ktx)
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ import com.tangem.domain.nft.EnableWalletNFTUseCase
|
|||
import com.tangem.domain.nft.GetWalletNFTEnabledUseCase
|
||||
import com.tangem.domain.notifications.repository.NotificationsRepository
|
||||
import com.tangem.domain.settings.repositories.PermissionRepository
|
||||
import com.tangem.domain.tokensync.usecase.StartTokenSyncUseCase
|
||||
import com.tangem.domain.assetsdiscovery.usecase.StartAssetsDiscoveryUseCase
|
||||
import com.tangem.domain.wallets.analytics.Settings
|
||||
import com.tangem.domain.wallets.analytics.WalletSettingsAnalyticEvents
|
||||
import com.tangem.domain.wallets.analytics.WalletSettingsAnalyticEvents.RecoveryPhraseScreenAction
|
||||
|
|
@ -90,7 +90,7 @@ internal class WalletSettingsModel @Inject constructor(
|
|||
private val isAccountsModeEnabledUseCase: IsAccountsModeEnabledUseCase,
|
||||
private val singleAccountListSupplier: SingleAccountListSupplier,
|
||||
private val accountListSortingSaver: AccountListSortingSaver,
|
||||
private val startTokenSyncUseCase: StartTokenSyncUseCase,
|
||||
private val startAssetsDiscoveryUseCase: StartAssetsDiscoveryUseCase,
|
||||
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
) : Model() {
|
||||
|
||||
|
|
@ -256,8 +256,8 @@ internal class WalletSettingsModel @Inject constructor(
|
|||
val userWallet = getUserWalletUseCase(params.userWalletId)
|
||||
.getOrNull()
|
||||
|
||||
if (userWallet is UserWallet.Hot && hotWalletFeatureToggles.isTokenSyncEnabled) {
|
||||
startTokenSyncUseCase.cancel(params.userWalletId)
|
||||
if (userWallet is UserWallet.Hot && hotWalletFeatureToggles.isAssetsDiscoveryEnabled) {
|
||||
startAssetsDiscoveryUseCase.cancel(params.userWalletId)
|
||||
}
|
||||
|
||||
val hasUserWallets = deleteWalletUseCase(params.userWalletId).getOrElse { error ->
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ dependencies {
|
|||
implementation(projects.domain.yieldSupply.models)
|
||||
implementation(projects.domain.appTheme)
|
||||
implementation(projects.domain.appTheme.models)
|
||||
implementation(projects.domain.tokensync)
|
||||
implementation(projects.domain.assetsdiscovery)
|
||||
|
||||
/** Feature Apis */
|
||||
implementation(projects.features.details.api)
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ import com.tangem.domain.settings.*
|
|||
import com.tangem.domain.tokens.RefreshMultiCurrencyWalletQuotesUseCase
|
||||
import com.tangem.domain.walletconnect.WcPairService
|
||||
import com.tangem.domain.walletconnect.model.WcPairRequest
|
||||
import com.tangem.domain.tokensync.usecase.StartTokenSyncUseCase
|
||||
import com.tangem.domain.assetsdiscovery.usecase.StartAssetsDiscoveryUseCase
|
||||
import com.tangem.features.hotwallet.HotWalletFeatureToggles
|
||||
import com.tangem.domain.wallets.usecase.*
|
||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyApyUpdateUseCase
|
||||
|
|
@ -126,7 +126,7 @@ internal class WalletModel @Inject constructor(
|
|||
private val tangemPayFeatureToggles: TangemPayFeatureToggles,
|
||||
private val uiMessageSender: UiMessageSender,
|
||||
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
private val startTokenSyncUseCase: StartTokenSyncUseCase,
|
||||
private val startAssetsDiscoveryUseCase: StartAssetsDiscoveryUseCase,
|
||||
val screenLifecycleProvider: ScreenLifecycleProvider,
|
||||
val innerWalletRouter: InnerWalletRouter,
|
||||
) : Model() {
|
||||
|
|
@ -159,7 +159,7 @@ internal class WalletModel @Inject constructor(
|
|||
subscribeTangemPayOnWalletState()
|
||||
subscribeToMainScreenQrScanning()
|
||||
enableNotificationsIfNeeded()
|
||||
applyPendingTokenSyncs()
|
||||
applyPendingAssetsDiscovery()
|
||||
|
||||
clickIntents.initialize(innerWalletRouter, modelScope)
|
||||
|
||||
|
|
@ -840,9 +840,9 @@ internal class WalletModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun applyPendingTokenSyncs() {
|
||||
if (hotWalletFeatureToggles.isTokenSyncEnabled) {
|
||||
startTokenSyncUseCase.applyPendingSyncs()
|
||||
private fun applyPendingAssetsDiscovery() {
|
||||
if (hotWalletFeatureToggles.isAssetsDiscoveryEnabled) {
|
||||
startAssetsDiscoveryUseCase.applyPendingAssetsDiscovery()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ import com.tangem.domain.tokens.model.analytics.PromoAnalyticsEvent
|
|||
import com.tangem.domain.tokens.model.analytics.PromoAnalyticsEvent.Program
|
||||
import com.tangem.domain.tokens.model.analytics.PromoAnalyticsEvent.PromotionBannerClicked
|
||||
import com.tangem.domain.tokens.model.details.NavigationAction
|
||||
import com.tangem.domain.tokensync.usecase.AcknowledgeTokenSyncCompletionUseCase
|
||||
import com.tangem.domain.assetsdiscovery.usecase.AcknowledgeAssetsDiscoveryCompletionUseCase
|
||||
import com.tangem.domain.wallets.usecase.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent.Basic
|
||||
|
|
@ -97,9 +97,9 @@ internal interface WalletWarningsClickIntents {
|
|||
|
||||
fun onCloseUpgradeBannerClick(userWalletId: UserWalletId)
|
||||
|
||||
fun onDismissTokenSyncNotification(userWalletId: UserWalletId)
|
||||
fun onDismissAssetsDiscoveryNotification(userWalletId: UserWalletId)
|
||||
|
||||
fun onTokenSyncManageClick(userWalletId: UserWalletId)
|
||||
fun onAssetsDiscoveryManageClick(userWalletId: UserWalletId)
|
||||
}
|
||||
|
||||
@Suppress("LargeClass", "LongParameterList", "TooManyFunctions")
|
||||
|
|
@ -132,7 +132,7 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
|
|||
private val uiMessageSender: UiMessageSender,
|
||||
private val reviewManager: ReviewManager,
|
||||
private val closeHotWalletUpgradeBannerUseCase: CloseHotWalletUpgradeBannerUseCase,
|
||||
private val acknowledgeTokenSyncCompletionUseCase: AcknowledgeTokenSyncCompletionUseCase,
|
||||
private val acknowledgeAssetsDiscoveryCompletionUseCase: AcknowledgeAssetsDiscoveryCompletionUseCase,
|
||||
) : BaseWalletClickIntents(), WalletWarningsClickIntents {
|
||||
|
||||
override fun onAddBackupCardClick() {
|
||||
|
|
@ -508,12 +508,12 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
override fun onDismissTokenSyncNotification(userWalletId: UserWalletId) {
|
||||
acknowledgeTokenSyncCompletionUseCase(userWalletId)
|
||||
override fun onDismissAssetsDiscoveryNotification(userWalletId: UserWalletId) {
|
||||
acknowledgeAssetsDiscoveryCompletionUseCase(userWalletId)
|
||||
}
|
||||
|
||||
override fun onTokenSyncManageClick(userWalletId: UserWalletId) {
|
||||
acknowledgeTokenSyncCompletionUseCase(userWalletId)
|
||||
override fun onAssetsDiscoveryManageClick(userWalletId: UserWalletId) {
|
||||
acknowledgeAssetsDiscoveryCompletionUseCase(userWalletId)
|
||||
router.openManageTokensScreen(
|
||||
AccountId.forMainCryptoPortfolio(userWalletId),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ internal class WalletWarningsAnalyticsSender @Inject constructor(
|
|||
is WalletNotification.Warning.TangemPayRefreshNeeded -> null
|
||||
is WalletNotification.Warning.TangemPayUnreachable -> null
|
||||
is WalletNotification.UpgradeHotWalletPromo -> null
|
||||
is WalletNotification.TokenSyncCompleted -> null
|
||||
is WalletNotification.AssetsDiscoveryCompleted -> null
|
||||
is WalletNotification.CreateTangemPayAccount -> null
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ import com.tangem.domain.notifications.repository.NotificationsRepository
|
|||
import com.tangem.domain.promo.ShouldShowPromoWalletUseCase
|
||||
import com.tangem.domain.promo.models.PromoId
|
||||
import com.tangem.domain.settings.IsReadyToShowRateAppUseCase
|
||||
import com.tangem.domain.tokensync.model.TokenSyncProgress
|
||||
import com.tangem.domain.tokensync.usecase.ObserveTokenSyncUseCase
|
||||
import com.tangem.domain.assetsdiscovery.model.AssetsDiscoveryProgress
|
||||
import com.tangem.domain.assetsdiscovery.usecase.ObserveAssetsDiscoveryUseCase
|
||||
import com.tangem.features.hotwallet.HotWalletFeatureToggles
|
||||
import com.tangem.domain.wallets.usecase.IsNeedToBackupUseCase
|
||||
import com.tangem.feature.wallet.child.wallet.model.WalletActivationBannerType
|
||||
|
|
@ -65,7 +65,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
private val shouldShowUpgradeHotWalletBannerUseCase: ShouldShowUpgradeHotWalletBannerUseCase,
|
||||
private val getUpgradeBannerClosureTimestampUseCase: GetUpgradeBannerClosureTimestampUseCase,
|
||||
private val checkHotWalletUpgradeBannerUseCase: CheckHotWalletUpgradeBannerUseCase,
|
||||
private val observeTokenSyncUseCase: ObserveTokenSyncUseCase,
|
||||
private val observeAssetsDiscoveryUseCase: ObserveAssetsDiscoveryUseCase,
|
||||
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
) {
|
||||
|
||||
|
|
@ -75,11 +75,12 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
val params = SingleAccountStatusListProducer.Params(userWallet.walletId)
|
||||
val accountStatusListFlow = accountDependencies.singleAccountStatusListSupplier(params)
|
||||
|
||||
val tokenSyncProgressFlow = if (hotWalletFeatureToggles.isTokenSyncEnabled && userWallet is UserWallet.Hot) {
|
||||
observeTokenSyncUseCase(userWallet.walletId).distinctUntilChanged()
|
||||
} else {
|
||||
flowOf(TokenSyncProgress.Idle)
|
||||
}
|
||||
val assetsDiscoveryProgressFlow =
|
||||
if (hotWalletFeatureToggles.isAssetsDiscoveryEnabled && userWallet is UserWallet.Hot) {
|
||||
observeAssetsDiscoveryUseCase(userWallet.walletId).distinctUntilChanged()
|
||||
} else {
|
||||
flowOf(AssetsDiscoveryProgress.Idle)
|
||||
}
|
||||
|
||||
return combine(
|
||||
accountStatusListFlow,
|
||||
|
|
@ -96,7 +97,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
.distinctUntilChanged(),
|
||||
getUpgradeBannerClosureTimestampUseCase(userWallet.walletId)
|
||||
.distinctUntilChanged(),
|
||||
tokenSyncProgressFlow,
|
||||
assetsDiscoveryProgressFlow,
|
||||
) { array -> array }
|
||||
.map { array ->
|
||||
val accountStatusList = array[0] as AccountStatusList
|
||||
|
|
@ -108,7 +109,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
val shouldShowYieldPromo = array[6] as Boolean
|
||||
val shouldShowUpgradeBanner = array[7] as Boolean
|
||||
val closureTimestamp = array[8] as? Long
|
||||
val tokenSyncProgress = array[9] as TokenSyncProgress
|
||||
val assetsDiscoveryProgress = array[9] as AssetsDiscoveryProgress
|
||||
|
||||
val flattenCurrencies = accountStatusList.flattenCurrencies()
|
||||
val paymentAccountStatus = accountStatusList.accountStatuses
|
||||
|
|
@ -153,9 +154,9 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
clickIntents = clickIntents,
|
||||
)
|
||||
|
||||
addTokenSyncCompletedNotification(
|
||||
addAssetsDiscoveryCompletedNotification(
|
||||
userWallet = userWallet,
|
||||
tokenSyncProgress = tokenSyncProgress,
|
||||
assetsDiscoveryProgress = assetsDiscoveryProgress,
|
||||
clickIntents = clickIntents,
|
||||
)
|
||||
|
||||
|
|
@ -404,17 +405,17 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
// }
|
||||
// }
|
||||
|
||||
private fun MutableList<WalletNotification>.addTokenSyncCompletedNotification(
|
||||
private fun MutableList<WalletNotification>.addAssetsDiscoveryCompletedNotification(
|
||||
userWallet: UserWallet,
|
||||
tokenSyncProgress: TokenSyncProgress,
|
||||
assetsDiscoveryProgress: AssetsDiscoveryProgress,
|
||||
clickIntents: WalletClickIntents,
|
||||
) {
|
||||
addIf(
|
||||
element = WalletNotification.TokenSyncCompleted(
|
||||
onCloseClick = { clickIntents.onDismissTokenSyncNotification(userWallet.walletId) },
|
||||
onManageTokensClick = { clickIntents.onTokenSyncManageClick(userWallet.walletId) },
|
||||
element = WalletNotification.AssetsDiscoveryCompleted(
|
||||
onCloseClick = { clickIntents.onDismissAssetsDiscoveryNotification(userWallet.walletId) },
|
||||
onManageTokensClick = { clickIntents.onAssetsDiscoveryManageClick(userWallet.walletId) },
|
||||
),
|
||||
condition = tokenSyncProgress is TokenSyncProgress.Completed,
|
||||
condition = assetsDiscoveryProgress is AssetsDiscoveryProgress.Completed,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import com.tangem.domain.card.common.util.cardTypesResolver
|
|||
import com.tangem.domain.card.common.util.getCardsCount
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.TokenSyncProgressUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.AssetsDiscoveryProgressUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletAdditionalInfo
|
||||
import java.math.BigDecimal
|
||||
|
||||
|
|
@ -32,7 +32,7 @@ internal object WalletAdditionalInfoFactory {
|
|||
fun resolve(
|
||||
wallet: UserWallet,
|
||||
currencyAmount: BigDecimal? = null,
|
||||
syncProgress: TokenSyncProgressUM = TokenSyncProgressUM.Idle,
|
||||
syncProgress: AssetsDiscoveryProgressUM = AssetsDiscoveryProgressUM.Idle,
|
||||
): WalletAdditionalInfo {
|
||||
return when (wallet) {
|
||||
is UserWallet.Cold -> {
|
||||
|
|
@ -46,8 +46,8 @@ internal object WalletAdditionalInfoFactory {
|
|||
}
|
||||
}
|
||||
|
||||
private fun UserWallet.Hot.resolveAdditionalInfo(syncProgress: TokenSyncProgressUM): WalletAdditionalInfo {
|
||||
val content = if (syncProgress is TokenSyncProgressUM.InProgress) {
|
||||
private fun UserWallet.Hot.resolveAdditionalInfo(syncProgress: AssetsDiscoveryProgressUM): WalletAdditionalInfo {
|
||||
val content = if (syncProgress is AssetsDiscoveryProgressUM.InProgress) {
|
||||
WalletAdditionalInfo.Content.SyncProgress(syncProgress.progressPercent)
|
||||
} else {
|
||||
WalletAdditionalInfo.Content.Text(
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ internal class MultiWalletContentLoader @AssistedInject constructor(
|
|||
private val walletNotificationsSubscriberFactory: WalletNotificationsSubscriber.Factory,
|
||||
private val multiWalletActionButtonsSubscriberFactory: MultiWalletActionButtonsSubscriber.Factory,
|
||||
private val tangemPayMainSubscriberFactory: TangemPayMainSubscriber.Factory,
|
||||
private val tokenSyncSubscriberFactory: TokenSyncSubscriber.Factory,
|
||||
private val assetsDiscoverySubscriberFactory: AssetsDiscoverySubscriber.Factory,
|
||||
private val tokenListAnalyticsSubscriberFactory: TokenListAnalyticsSubscriber.Factory,
|
||||
private val designFeatureToggles: DesignFeatureToggles,
|
||||
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
|
|
@ -36,8 +36,8 @@ internal class MultiWalletContentLoader @AssistedInject constructor(
|
|||
multiWalletActionButtonsSubscriberFactory.create(userWallet),
|
||||
tangemPayMainSubscriberFactory.create(userWallet),
|
||||
tokenListAnalyticsSubscriberFactory.create(userWallet),
|
||||
if (hotWalletFeatureToggles.isTokenSyncEnabled && userWallet is UserWallet.Hot) {
|
||||
tokenSyncSubscriberFactory.create(userWallet)
|
||||
if (hotWalletFeatureToggles.isAssetsDiscoveryEnabled && userWallet is UserWallet.Hot) {
|
||||
assetsDiscoverySubscriberFactory.create(userWallet)
|
||||
} else {
|
||||
null
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.model
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
|
||||
@Immutable
|
||||
internal sealed class AssetsDiscoveryProgressUM {
|
||||
|
||||
data object Idle : AssetsDiscoveryProgressUM()
|
||||
|
||||
data class InProgress(val progressPercent: Int) : AssetsDiscoveryProgressUM()
|
||||
|
||||
data object Completed : AssetsDiscoveryProgressUM()
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.model
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
|
||||
@Immutable
|
||||
internal sealed class TokenSyncProgressUM {
|
||||
|
||||
data object Idle : TokenSyncProgressUM()
|
||||
|
||||
data class InProgress(val progressPercent: Int) : TokenSyncProgressUM()
|
||||
|
||||
data object Completed : TokenSyncProgressUM()
|
||||
}
|
||||
|
|
@ -435,7 +435,7 @@ sealed class WalletNotification(val config: NotificationConfig) {
|
|||
),
|
||||
)
|
||||
|
||||
data class TokenSyncCompleted(
|
||||
data class AssetsDiscoveryCompleted(
|
||||
val onCloseClick: () -> Unit,
|
||||
val onManageTokensClick: () -> Unit,
|
||||
) : WalletNotification(
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ internal sealed interface WalletState : WalletStateHolder {
|
|||
abstract val tangemPayState: TangemPayState
|
||||
abstract val tangemPayMainUM: TangemPayMainUM
|
||||
abstract val isTangemPayRefactorEnabled: Boolean // TANGEM_PAY_ACCOUNTS_REFACTOR_ENABLED
|
||||
abstract val tokenSyncProgressUM: TokenSyncProgressUM
|
||||
abstract val assetsDiscoveryProgressUM: AssetsDiscoveryProgressUM
|
||||
|
||||
data class Content(
|
||||
override val pullToRefreshConfig: PullToRefreshConfig,
|
||||
|
|
@ -41,7 +41,7 @@ internal sealed interface WalletState : WalletStateHolder {
|
|||
override val tangemPayState: TangemPayState,
|
||||
override val tangemPayMainUM: TangemPayMainUM,
|
||||
override val isTangemPayRefactorEnabled: Boolean,
|
||||
override val tokenSyncProgressUM: TokenSyncProgressUM = TokenSyncProgressUM.Idle,
|
||||
override val assetsDiscoveryProgressUM: AssetsDiscoveryProgressUM = AssetsDiscoveryProgressUM.Idle,
|
||||
) : MultiCurrency()
|
||||
|
||||
data class Locked(
|
||||
|
|
@ -63,7 +63,7 @@ internal sealed interface WalletState : WalletStateHolder {
|
|||
override val tangemPayState: TangemPayState = TangemPayState.Empty
|
||||
override val tangemPayMainUM: TangemPayMainUM = TangemPayMainUM.Empty
|
||||
override val isTangemPayRefactorEnabled: Boolean = false
|
||||
override val tokenSyncProgressUM: TokenSyncProgressUM = TokenSyncProgressUM.Idle
|
||||
override val assetsDiscoveryProgressUM: AssetsDiscoveryProgressUM = AssetsDiscoveryProgressUM.Idle
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,21 +2,21 @@ package com.tangem.feature.wallet.presentation.wallet.state.transformers
|
|||
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.TokenSyncProgressUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.AssetsDiscoveryProgressUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
|
||||
internal class SetTokenSyncProgressTransformer(
|
||||
internal class SetAssetsDiscoveryProgressTransformer(
|
||||
private val userWallet: UserWallet,
|
||||
private val progress: TokenSyncProgressUM,
|
||||
private val progress: AssetsDiscoveryProgressUM,
|
||||
) : WalletStateTransformer(userWallet.walletId) {
|
||||
|
||||
override fun transform(prevState: WalletState): WalletState {
|
||||
return when (prevState) {
|
||||
is WalletState.MultiCurrency.Content -> prevState.copy(
|
||||
walletCardState = updateCardState(prevState.walletCardState),
|
||||
tokenSyncProgressUM = progress,
|
||||
assetsDiscoveryProgressUM = progress,
|
||||
)
|
||||
else -> prevState
|
||||
}
|
||||
|
|
@ -61,7 +61,7 @@ internal class SetTokenListErrorTransformer(
|
|||
walletsBalanceUM = walletUM.walletsBalanceUM.toLoadedState(),
|
||||
tokensListUM = WalletTokensListUM.Empty(
|
||||
onEmptyClick = {
|
||||
clickIntents.onTokenSyncManageClick(walletUM.walletsBalanceUM.id)
|
||||
clickIntents.onAssetsDiscoveryManageClick(walletUM.walletsBalanceUM.id)
|
||||
},
|
||||
),
|
||||
buttons = walletUM.disableButtons(),
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ internal class SetTokenListTransformer(
|
|||
if (params !is TokenConverterParams.Account) {
|
||||
return WalletTokensListUM.Empty(
|
||||
onEmptyClick = {
|
||||
clickIntents.onTokenSyncManageClick(userWallet.walletId)
|
||||
clickIntents.onAssetsDiscoveryManageClick(userWallet.walletId)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import com.tangem.domain.card.common.util.getCardsCount
|
|||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletImageResolver
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.TokenSyncProgressUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.AssetsDiscoveryProgressUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
|
|
@ -19,7 +19,7 @@ internal class UpdateWalletCardsCountTransformer(
|
|||
return when (prevState) {
|
||||
is WalletState.MultiCurrency.Content -> {
|
||||
prevState.copy(
|
||||
walletCardState = prevState.walletCardState.toUpdatedState(prevState.tokenSyncProgressUM),
|
||||
walletCardState = prevState.walletCardState.toUpdatedState(prevState.assetsDiscoveryProgressUM),
|
||||
)
|
||||
}
|
||||
is WalletState.SingleCurrency.Content -> {
|
||||
|
|
@ -39,7 +39,7 @@ internal class UpdateWalletCardsCountTransformer(
|
|||
}
|
||||
|
||||
private fun WalletCardState.toUpdatedState(
|
||||
syncProgress: TokenSyncProgressUM = TokenSyncProgressUM.Idle,
|
||||
syncProgress: AssetsDiscoveryProgressUM = AssetsDiscoveryProgressUM.Idle,
|
||||
): WalletCardState {
|
||||
return when (this) {
|
||||
is WalletCardState.Content -> copy(
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.subscribers
|
||||
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.tokensync.model.TokenSyncProgress
|
||||
import com.tangem.domain.tokensync.usecase.ObserveTokenSyncUseCase
|
||||
import com.tangem.domain.assetsdiscovery.model.AssetsDiscoveryProgress
|
||||
import com.tangem.domain.assetsdiscovery.usecase.ObserveAssetsDiscoveryUseCase
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.TokenSyncProgressUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetTokenSyncProgressTransformer
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.AssetsDiscoveryProgressUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetAssetsDiscoveryProgressTransformer
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
|
@ -13,25 +13,25 @@ import kotlinx.coroutines.CoroutineScope
|
|||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
|
||||
internal class TokenSyncSubscriber @AssistedInject constructor(
|
||||
internal class AssetsDiscoverySubscriber @AssistedInject constructor(
|
||||
@Assisted private val userWallet: UserWallet,
|
||||
private val stateController: WalletStateController,
|
||||
private val observeTokenSyncUseCase: ObserveTokenSyncUseCase,
|
||||
private val observeAssetsDiscoveryUseCase: ObserveAssetsDiscoveryUseCase,
|
||||
) : WalletSubscriber() {
|
||||
|
||||
override fun create(coroutineScope: CoroutineScope): Flow<*> {
|
||||
return observeTokenSyncUseCase(userWallet.walletId)
|
||||
return observeAssetsDiscoveryUseCase(userWallet.walletId)
|
||||
.onEach { current -> handleProgress(userWallet, current) }
|
||||
}
|
||||
|
||||
private fun handleProgress(userWallet: UserWallet, current: TokenSyncProgress) {
|
||||
private fun handleProgress(userWallet: UserWallet, current: AssetsDiscoveryProgress) {
|
||||
val progressUM = when (current) {
|
||||
is TokenSyncProgress.InProgress -> TokenSyncProgressUM.InProgress(current.progressPercent)
|
||||
is TokenSyncProgress.Completed -> TokenSyncProgressUM.Completed
|
||||
is TokenSyncProgress.Idle -> TokenSyncProgressUM.Idle
|
||||
is AssetsDiscoveryProgress.InProgress -> AssetsDiscoveryProgressUM.InProgress(current.progressPercent)
|
||||
is AssetsDiscoveryProgress.Completed -> AssetsDiscoveryProgressUM.Completed
|
||||
is AssetsDiscoveryProgress.Idle -> AssetsDiscoveryProgressUM.Idle
|
||||
}
|
||||
stateController.update(
|
||||
SetTokenSyncProgressTransformer(
|
||||
SetAssetsDiscoveryProgressTransformer(
|
||||
userWallet = userWallet,
|
||||
progress = progressUM,
|
||||
),
|
||||
|
|
@ -40,6 +40,6 @@ internal class TokenSyncSubscriber @AssistedInject constructor(
|
|||
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(userWallet: UserWallet): TokenSyncSubscriber
|
||||
fun create(userWallet: UserWallet): AssetsDiscoverySubscriber
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.blockchainsdk
|
||||
|
||||
import com.tangem.blockchain.assetsdiscovery.AssetsDiscoveryServiceFactory
|
||||
import com.tangem.blockchain.common.WalletManagerFactory
|
||||
import com.tangem.blockchain.common.memo.MemoValidatorFactory
|
||||
|
||||
|
|
@ -18,4 +19,7 @@ interface BlockchainSDKFactory {
|
|||
|
||||
/** Get [MemoValidatorFactory] synchronously */
|
||||
suspend fun getMemoValidatorFactorySync(): MemoValidatorFactory?
|
||||
|
||||
/** Get [AssetsDiscoveryServiceFactory] synchronously */
|
||||
suspend fun getAssetsDiscoveryServiceFactorySync(): AssetsDiscoveryServiceFactory?
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.blockchainsdk
|
||||
|
||||
import com.tangem.blockchain.assetsdiscovery.AssetsDiscoveryServiceFactory
|
||||
import com.tangem.blockchain.common.BlockchainSdkConfig
|
||||
import com.tangem.blockchain.common.WalletManagerFactory
|
||||
import com.tangem.blockchain.common.memo.MemoValidatorFactory
|
||||
|
|
@ -34,6 +35,8 @@ internal class DefaultBlockchainSDKFactory(
|
|||
|
||||
private val walletManagerFactory: Flow<WalletManagerFactory?> = createWalletManagerFactory()
|
||||
private val memoValidatorFactory: Flow<MemoValidatorFactory?> = createMemoValidatorFactory()
|
||||
private val assetsDiscoveryServiceFactory: Flow<AssetsDiscoveryServiceFactory?> =
|
||||
createAssetsDiscoveryServiceFactory()
|
||||
|
||||
override suspend fun init() {
|
||||
coroutineScope {
|
||||
|
|
@ -45,6 +48,9 @@ internal class DefaultBlockchainSDKFactory(
|
|||
|
||||
override suspend fun getMemoValidatorFactorySync(): MemoValidatorFactory? = memoValidatorFactory.firstOrNull()
|
||||
|
||||
override suspend fun getAssetsDiscoveryServiceFactorySync(): AssetsDiscoveryServiceFactory? =
|
||||
assetsDiscoveryServiceFactory.firstOrNull()
|
||||
|
||||
private fun createWalletManagerFactory(): Flow<WalletManagerFactory?> {
|
||||
return combine(
|
||||
flow = flowOf(blockchainSdkConfig),
|
||||
|
|
@ -56,6 +62,16 @@ internal class DefaultBlockchainSDKFactory(
|
|||
.stateIn(scope = mainScope, started = SharingStarted.Eagerly, initialValue = null)
|
||||
}
|
||||
|
||||
private fun createAssetsDiscoveryServiceFactory(): Flow<AssetsDiscoveryServiceFactory?> {
|
||||
return combine(
|
||||
flow = flowOf(blockchainSdkConfig),
|
||||
flow2 = blockchainProvidersTypesManager.get(),
|
||||
) { config, providerTypes ->
|
||||
AssetsDiscoveryServiceFactory(config = config, providerTypes = providerTypes)
|
||||
}
|
||||
.stateIn(scope = mainScope, started = SharingStarted.Eagerly, initialValue = null)
|
||||
}
|
||||
|
||||
private fun createMemoValidatorFactory(): Flow<MemoValidatorFactory?> {
|
||||
return combine(
|
||||
flow = flowOf(blockchainSdkConfig),
|
||||
|
|
|
|||
|
|
@ -340,7 +340,7 @@ include(":domain:dynamic-addresses:models")
|
|||
include(":domain:settings")
|
||||
include(":domain:tokens")
|
||||
include(":domain:tokens:models")
|
||||
include(":domain:tokensync")
|
||||
include(":domain:assetsdiscovery")
|
||||
include(":domain:wallets")
|
||||
include(":domain:wallets:models")
|
||||
include(":domain:txhistory")
|
||||
|
|
@ -409,7 +409,7 @@ include(":data:balance-hiding")
|
|||
include(":data:common")
|
||||
include(":data:card")
|
||||
include(":data:tokens")
|
||||
include(":data:tokensync")
|
||||
include(":data:assetsdiscovery")
|
||||
include(":data:settings")
|
||||
include(":data:txhistory")
|
||||
include(":data:wallets")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue