Updated on 2026-08-14

This commit is contained in:
Tangem 2025-12-02 13:23:56 +04:00
parent c9be7fa5c5
commit d47433ee6c
24 changed files with 193 additions and 90 deletions

View file

@ -3,15 +3,7 @@
<ManuallySuppressedIssues/>
<CurrentIssues>
<ID>MultilineLambdaItParameter:DefaultCustomTokensRepository.kt$DefaultCustomTokensRepository${ // TODO: refactor https://tangem.atlassian.net/browse/AND-10006\ if (it.isTestnet() || it in excludedBlockchains || it in hotWalletExcludedBlockchains) { return@mapNotNull null } networkFactory.create( blockchain = it, extraDerivationPath = null, userWallet = userWallet, ) }</ID>
<ID>MultilineLambdaItParameter:DefaultManageTokensRepository.kt$DefaultManageTokensRepository${ it.contractAddress != null &amp;&amp; it.networkId == network.backendId &amp;&amp; it.derivationPath == network.derivationPath.value }</ID>
<ID>MultilineLambdaItParameter:ManageTokensUpdateFetcher.kt$ManageTokensUpdateFetcher${ if (it.key == toUpdate[index].key) { Batch(it.key, updatedItems) } else { null } }</ID>
<ID>NamedArguments:ManagedCryptoCurrencyFactory.kt$ManagedCryptoCurrencyFactory$create(coinsResponse, tokensResponse, userWallet, accountIndex)</ID>
<ID>NamedArguments:ManagedCryptoCurrencyFactory.kt$ManagedCryptoCurrencyFactory$createToken(coin, tokensResponse, coinsResponse.imageHost, userWallet, accountIndex)</ID>
<ID>NamedArguments:ManagedCryptoCurrencyFactory.kt$ManagedCryptoCurrencyFactory$findAddedInNetworks(coinResponse.id, tokensResponse, userWallet, accountIndex)</ID>
<ID>NamedArguments:ManagedCryptoCurrencyFactory.kt$ManagedCryptoCurrencyFactory$findAddedInNetworks(testnetToken.id, tokensResponse, userWallet, accountIndex)</ID>
<ID>SuspendFunSwallowedCancellation:DefaultManageTokensRepository.kt$DefaultManageTokensRepository$runCatching</ID>
<ID>UnsafeCallOnNullableType:DefaultCustomTokensRepository.kt$DefaultCustomTokensRepository$coinNetwork.decimalCount!!</ID>
<ID>UseOrEmpty:ManagedCryptoCurrencyFactory.kt$ManagedCryptoCurrencyFactory$testnetToken.networks?.mapNotNull { network -&gt; createSource( networkId = network.id, contractAddress = network.address, decimals = network.decimalCount, userWallet = userWallet, accountIndex = accountIndex, ) } ?: emptyList()</ID>
<ID>UseOrEmpty:ManagedCryptoCurrencyFactory.kt$ManagedCryptoCurrencyFactory$tokensResponse ?.let { createCustomTokens(it, userWallet, accountIndex) } ?: emptyList()</ID>
</CurrentIssues>
</SmellBaseline>

View file

@ -41,6 +41,7 @@ import com.tangem.pagination.fetcher.LimitOffsetBatchFetcher
import com.tangem.pagination.fetcher.LimitOffsetBatchFetcher.Request
import com.tangem.pagination.toBatchFlow
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.coroutines.runSuspendCatching
@Suppress("LongParameterList", "LargeClass")
internal class DefaultManageTokensRepository(
@ -176,7 +177,7 @@ internal class DefaultManageTokensRepository(
val shouldFetch = loadUserTokensFromRemote && userWallet != null
val fetchedResponse = if (shouldFetch) {
runCatching { walletAccountsFetcher.fetch(userWalletId = userWallet.walletId) }.getOrNull()
runSuspendCatching { walletAccountsFetcher.fetch(userWalletId = userWallet.walletId) }.getOrNull()
} else {
null
}
@ -214,19 +215,22 @@ internal class DefaultManageTokensRepository(
userWallet != null &&
query == null
val accountIndex = accountDTO?.derivationIndex?.let(DerivationIndex::invoke)?.getOrNull()
?: return emptyList()
val items = if (isCreateWithCustom) {
managedCryptoCurrencyFactory.createWithCustomTokens(
coinsResponse = updatedCoinsResponse,
tokensResponse = tokensResponse,
userWallet = userWallet,
accountIndex = accountDTO?.derivationIndex?.let(DerivationIndex::invoke)?.getOrNull(),
accountIndex = accountIndex,
)
} else {
managedCryptoCurrencyFactory.create(
coinsResponse = updatedCoinsResponse,
tokensResponse = tokensResponse,
userWallet = userWallet,
accountIndex = accountDTO?.derivationIndex?.let(DerivationIndex::invoke)?.getOrNull(),
accountIndex = accountIndex,
)
}
@ -262,14 +266,14 @@ internal class DefaultManageTokensRepository(
coinsResponse = updatedCoinsResponse,
tokensResponse = tokensResponse,
userWallet = userWallet,
accountIndex = null,
accountIndex = DerivationIndex.Main,
)
} else {
managedCryptoCurrencyFactory.create(
coinsResponse = updatedCoinsResponse,
tokensResponse = tokensResponse,
userWallet = userWallet,
accountIndex = null,
accountIndex = DerivationIndex.Main,
)
}
}
@ -307,6 +311,13 @@ internal class DefaultManageTokensRepository(
)
}
val accountIndex = accountDTO?.derivationIndex?.let(DerivationIndex::invoke)?.getOrNull()
?: return BatchFetchResult.Success(
data = emptyList(),
empty = true,
last = true,
)
val items = managedCryptoCurrencyFactory.createTestnetWithCustomTokens(
testnetTokensConfig = if (!searchText.isNullOrBlank()) {
testnetTokensConfig.copy(
@ -320,7 +331,7 @@ internal class DefaultManageTokensRepository(
},
tokensResponse = tokensResponse,
userWallet = userWallet,
accountIndex = accountDTO?.derivationIndex?.let(DerivationIndex::invoke)?.getOrNull(),
accountIndex = accountIndex,
)
return BatchFetchResult.Success(
@ -350,7 +361,7 @@ internal class DefaultManageTokensRepository(
},
tokensResponse = getSavedUserTokensResponseSync(userWallet.walletId),
userWallet = userWallet,
accountIndex = null,
accountIndex = DerivationIndex.Main,
)
return BatchFetchResult.Success(
@ -392,10 +403,10 @@ internal class DefaultManageTokensRepository(
)
val newTokensList = storedTokens.tokens + addedTokens - removedTokens.toSet()
return newTokensList.any {
it.contractAddress != null &&
it.networkId == network.backendId &&
it.derivationPath == network.derivationPath.value
return newTokensList.any { token ->
token.contractAddress != null &&
token.networkId == network.backendId &&
token.derivationPath == network.derivationPath.value
}
}

View file

@ -35,10 +35,16 @@ internal class ManagedCryptoCurrencyFactory(
coinsResponse: CoinsResponse,
tokensResponse: UserTokensResponse?,
userWallet: UserWallet?,
accountIndex: DerivationIndex?,
accountIndex: DerivationIndex,
): List<ManagedCryptoCurrency> {
return coinsResponse.coins.mapNotNull { coin ->
createToken(coin, tokensResponse, coinsResponse.imageHost, userWallet, accountIndex)
createToken(
coinResponse = coin,
tokensResponse = tokensResponse,
imageHost = coinsResponse.imageHost,
userWallet = userWallet,
accountIndex = accountIndex,
)
}
}
@ -46,10 +52,15 @@ internal class ManagedCryptoCurrencyFactory(
coinsResponse: CoinsResponse,
tokensResponse: UserTokensResponse,
userWallet: UserWallet,
accountIndex: DerivationIndex?,
accountIndex: DerivationIndex,
): List<ManagedCryptoCurrency> {
val customTokens = createCustomTokens(tokensResponse, userWallet, accountIndex)
val tokens = create(coinsResponse, tokensResponse, userWallet, accountIndex)
val tokens = create(
coinsResponse = coinsResponse,
tokensResponse = tokensResponse,
userWallet = userWallet,
accountIndex = accountIndex,
)
return customTokens + tokens
}
@ -58,11 +69,11 @@ internal class ManagedCryptoCurrencyFactory(
testnetTokensConfig: TestnetTokensConfig,
tokensResponse: UserTokensResponse?,
userWallet: UserWallet,
accountIndex: DerivationIndex?,
accountIndex: DerivationIndex,
): List<ManagedCryptoCurrency> {
val customTokens = tokensResponse
?.let { createCustomTokens(it, userWallet, accountIndex) }
?: emptyList()
.orEmpty()
val testnetTokens = testnetTokensConfig.tokens.map { testnetToken ->
ManagedCryptoCurrency.Token(
id = ManagedCryptoCurrency.ID(testnetToken.id),
@ -77,8 +88,13 @@ internal class ManagedCryptoCurrencyFactory(
userWallet = userWallet,
accountIndex = accountIndex,
)
} ?: emptyList(),
addedIn = findAddedInNetworks(testnetToken.id, tokensResponse, userWallet, accountIndex),
}.orEmpty(),
addedIn = findAddedInNetworks(
currencyId = testnetToken.id,
tokensResponse = tokensResponse,
userWallet = userWallet,
accountIndex = accountIndex,
),
)
}
@ -88,7 +104,7 @@ internal class ManagedCryptoCurrencyFactory(
private fun createCustomTokens(
tokensResponse: UserTokensResponse,
userWallet: UserWallet,
accountIndex: DerivationIndex?,
accountIndex: DerivationIndex,
): List<ManagedCryptoCurrency> = tokensResponse.tokens
.mapNotNull { token ->
maybeCreateCustomToken(token, userWallet, accountIndex)
@ -97,7 +113,7 @@ internal class ManagedCryptoCurrencyFactory(
private fun maybeCreateCustomToken(
token: UserTokensResponse.Token,
userWallet: UserWallet,
accountIndex: DerivationIndex?,
accountIndex: DerivationIndex,
): ManagedCryptoCurrency? {
val blockchain = Blockchain.fromNetworkId(token.networkId)
?.takeUnless { it in excludedBlockchains }
@ -161,7 +177,7 @@ internal class ManagedCryptoCurrencyFactory(
tokensResponse: UserTokensResponse?,
imageHost: String?,
userWallet: UserWallet?,
accountIndex: DerivationIndex?,
accountIndex: DerivationIndex,
): ManagedCryptoCurrency? {
if (coinResponse.networks.isEmpty() || !coinResponse.active) return null
@ -184,7 +200,12 @@ internal class ManagedCryptoCurrencyFactory(
symbol = coinResponse.symbol,
iconUrl = getIconUrl(coinResponse.id, imageHost),
availableNetworks = availableNetworks,
addedIn = findAddedInNetworks(coinResponse.id, tokensResponse, userWallet, accountIndex),
addedIn = findAddedInNetworks(
currencyId = coinResponse.id,
tokensResponse = tokensResponse,
userWallet = userWallet,
accountIndex = accountIndex,
),
)
}
@ -194,7 +215,7 @@ internal class ManagedCryptoCurrencyFactory(
decimals: Int?,
userWallet: UserWallet?,
extraDerivationPath: String? = null,
accountIndex: DerivationIndex?,
accountIndex: DerivationIndex,
): SourceNetwork? {
val blockchain = Blockchain.fromNetworkId(networkId)
?.takeUnless { it in excludedBlockchains }
@ -235,7 +256,7 @@ internal class ManagedCryptoCurrencyFactory(
currencyId: String,
tokensResponse: UserTokensResponse?,
userWallet: UserWallet?,
accountIndex: DerivationIndex?,
accountIndex: DerivationIndex,
): Set<Network> {
if (tokensResponse == null) return emptySet()