Updated on 2026-08-14
This commit is contained in:
parent
7f2e5650e2
commit
16c7de9054
27 changed files with 796 additions and 70 deletions
|
|
@ -0,0 +1,54 @@
|
|||
package com.tangem.data.yield.supply
|
||||
|
||||
import com.tangem.blockchain.blockchains.ethereum.EthereumUtils
|
||||
import com.tangem.blockchainsdk.utils.toBlockchain
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.yield.supply.YieldModuleAddressProvider
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
internal class DefaultYieldModuleAddressProvider(
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : YieldModuleAddressProvider {
|
||||
|
||||
private data class Key(val userWalletId: UserWalletId, val networkRawId: String)
|
||||
|
||||
private val cache = ConcurrentHashMap<Key, String>()
|
||||
private val mutex = Mutex()
|
||||
|
||||
override suspend fun getOrFetch(userWalletId: UserWalletId, network: Network): String? {
|
||||
val key = Key(userWalletId, network.rawId)
|
||||
cache[key]?.let { return it }
|
||||
return withContext(dispatchers.io) {
|
||||
mutex.withLock {
|
||||
cache[key]?.let { return@withLock it }
|
||||
val walletManager = walletManagersFacade.getOrCreateWalletManager(
|
||||
userWalletId = userWalletId,
|
||||
blockchain = network.toBlockchain(),
|
||||
derivationPath = network.derivationPath.value,
|
||||
) ?: error("Wallet manager not found for $network")
|
||||
// SDK returns ZERO_ADDRESS on internal failure (e.g. RPC error). Treat that as
|
||||
// "unavailable" so callers are forced by the type system to fall back instead
|
||||
// of using it as a destination.
|
||||
val address = walletManager.getYieldModuleAddress()
|
||||
.takeIf { it != EthereumUtils.ZERO_ADDRESS }
|
||||
if (address != null) cache[key] = address
|
||||
address
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun invalidate(userWalletId: UserWalletId?) {
|
||||
if (userWalletId == null) {
|
||||
cache.clear()
|
||||
} else {
|
||||
cache.keys.removeAll { it.userWalletId == userWalletId }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@ import com.tangem.blockchain.yieldsupply.YieldSupplyContractCallDataProviderFact
|
|||
import com.tangem.blockchainsdk.utils.toBlockchain
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.models.yield.supply.YieldSupplyStatus
|
||||
import com.tangem.domain.utils.convertToSdkAmount
|
||||
|
|
@ -127,6 +128,11 @@ internal class DefaultYieldSupplyTransactionRepository(
|
|||
val amount = getEnterAmount(cryptoCurrency, yieldSupplyStatus)
|
||||
|
||||
val emptyContractAddress = existingYieldAddress == null || existingYieldAddress == EthereumUtils.ZERO_ADDRESS
|
||||
val activeYieldContractAddress = if (emptyContractAddress) {
|
||||
calculatedYieldContractAddress
|
||||
} else {
|
||||
existingYieldAddress
|
||||
}
|
||||
|
||||
when {
|
||||
yieldSupplyStatus == null || emptyContractAddress -> {
|
||||
|
|
@ -143,7 +149,7 @@ internal class DefaultYieldSupplyTransactionRepository(
|
|||
createInitTokenTransaction(
|
||||
walletManager = walletManager,
|
||||
cryptoCurrency = cryptoCurrency,
|
||||
yieldContractAddress = calculatedYieldContractAddress,
|
||||
yieldContractAddress = activeYieldContractAddress,
|
||||
amount = amount,
|
||||
maxNetworkFee = maxNetworkFee,
|
||||
),
|
||||
|
|
@ -152,7 +158,7 @@ internal class DefaultYieldSupplyTransactionRepository(
|
|||
createReactivateTokenTransaction(
|
||||
walletManager = walletManager,
|
||||
cryptoCurrency = cryptoCurrency,
|
||||
yieldContractAddress = calculatedYieldContractAddress,
|
||||
yieldContractAddress = activeYieldContractAddress,
|
||||
amount = amount,
|
||||
maxNetworkFee = maxNetworkFee,
|
||||
),
|
||||
|
|
@ -166,7 +172,7 @@ internal class DefaultYieldSupplyTransactionRepository(
|
|||
walletManager = walletManager,
|
||||
cryptoCurrency = cryptoCurrency,
|
||||
callData = ApprovalERC20TokenCallData(
|
||||
spenderAddress = calculatedYieldContractAddress,
|
||||
spenderAddress = activeYieldContractAddress,
|
||||
amount = null,
|
||||
),
|
||||
destinationAddress = cryptoCurrency.contractAddress,
|
||||
|
|
@ -182,7 +188,7 @@ internal class DefaultYieldSupplyTransactionRepository(
|
|||
walletManager = walletManager,
|
||||
cryptoCurrency = cryptoCurrency,
|
||||
amount = amount,
|
||||
yieldContractAddress = calculatedYieldContractAddress,
|
||||
yieldContractAddress = activeYieldContractAddress,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -218,6 +224,20 @@ internal class DefaultYieldSupplyTransactionRepository(
|
|||
}.onFailure { TangemLogger.e("Error", it) }.getOrThrow()
|
||||
}
|
||||
|
||||
override suspend fun wrapYieldSwapCallDataWithUpgradeIfNeeded(
|
||||
userWalletId: UserWalletId,
|
||||
network: Network,
|
||||
callData: SmartContractCallData,
|
||||
): SmartContractCallData = withContext(dispatchers.io) {
|
||||
val walletManager = walletManagersFacade.getOrCreateWalletManager(
|
||||
userWalletId = userWalletId,
|
||||
blockchain = network.toBlockchain(),
|
||||
derivationPath = network.derivationPath.value,
|
||||
) ?: error("Wallet manager not found for $network")
|
||||
val versionStatus = walletManager.checkModuleVersionStatus()
|
||||
YieldSupplyContractCallDataProviderFactory.wrapWithUpgradeIfNeeded(versionStatus, callData)
|
||||
}
|
||||
|
||||
private suspend fun getYieldTokenStatus(
|
||||
walletManager: WalletManager,
|
||||
cryptoCurrency: CryptoCurrency.Token,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.data.yield.supply.di
|
||||
|
||||
import com.tangem.core.analytics.api.AnalyticsExceptionHandler
|
||||
import com.tangem.data.yield.supply.DefaultYieldModuleAddressProvider
|
||||
import com.tangem.data.yield.supply.DefaultYieldSupplyRepository
|
||||
import com.tangem.data.yield.supply.DefaultYieldSupplyErrorResolver
|
||||
import com.tangem.data.yield.supply.DefaultYieldSupplyTransactionRepository
|
||||
|
|
@ -12,6 +13,7 @@ import com.tangem.datasource.local.yieldsupply.YieldMarketsStore
|
|||
import com.tangem.datasource.local.yieldsupply.promo.YieldBoostPromoStore
|
||||
import com.tangem.datasource.local.yieldsupply.promo.YieldBoostStatusStore
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.yield.supply.YieldModuleAddressProvider
|
||||
import com.tangem.domain.yield.supply.YieldSupplyRepository
|
||||
import com.tangem.domain.yield.supply.YieldSupplyErrorResolver
|
||||
import com.tangem.domain.yield.supply.YieldSupplyTransactionRepository
|
||||
|
|
@ -65,6 +67,18 @@ internal object YieldSupplyDataModule {
|
|||
return DefaultYieldSupplyErrorResolver
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideYieldModuleAddressProvider(
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): YieldModuleAddressProvider {
|
||||
return DefaultYieldModuleAddressProvider(
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideYieldPromoRepository(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue