diff --git a/app/src/main/java/com/tangem/tap/network/auth/DefaultP2PEthPoolAuthProvider.kt b/app/src/main/java/com/tangem/tap/network/auth/DefaultP2PEthPoolAuthProvider.kt index 5839903010..5f54236082 100644 --- a/app/src/main/java/com/tangem/tap/network/auth/DefaultP2PEthPoolAuthProvider.kt +++ b/app/src/main/java/com/tangem/tap/network/auth/DefaultP2PEthPoolAuthProvider.kt @@ -1,6 +1,7 @@ package com.tangem.tap.network.auth import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage +import com.tangem.domain.staking.model.ethpool.P2PStakingConfig import com.tangem.lib.auth.P2PEthPoolAuthProvider internal class DefaultP2PEthPoolAuthProvider( @@ -11,6 +12,6 @@ internal class DefaultP2PEthPoolAuthProvider( val keys = environmentConfigStorage.getConfigSync().p2pApiKey ?: error("No P2P api keys provided") - return keys.mainnet + return if (P2PStakingConfig.USE_TESTNET) keys.hoodi else keys.mainnet } } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/common/config/P2PEthPool.kt b/core/datasource/src/main/java/com/tangem/datasource/api/common/config/P2PEthPool.kt index b699172b24..aa1b28c629 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/common/config/P2PEthPool.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/common/config/P2PEthPool.kt @@ -1,6 +1,7 @@ package com.tangem.datasource.api.common.config import com.tangem.datasource.BuildConfig +import com.tangem.domain.staking.model.ethpool.P2PStakingConfig import com.tangem.lib.auth.P2PEthPoolAuthProvider import com.tangem.utils.ProviderSuspend @@ -22,12 +23,7 @@ internal class P2PEthPool( private fun getInitialEnvironment(): ApiEnvironment { return when (BuildConfig.BUILD_TYPE) { MOCKED_BUILD_TYPE -> ApiEnvironment.MOCK - DEBUG_BUILD_TYPE, - INTERNAL_BUILD_TYPE, - EXTERNAL_BUILD_TYPE, - RELEASE_BUILD_TYPE, - -> ApiEnvironment.PROD - else -> error("Unknown build type [${BuildConfig.BUILD_TYPE}]") + else -> if (P2PStakingConfig.USE_TESTNET) ApiEnvironment.DEV else ApiEnvironment.PROD } } diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/ethpool/P2PEthPoolApi.kt b/core/datasource/src/main/java/com/tangem/datasource/api/ethpool/P2PEthPoolApi.kt index 60503742bb..cf3ab2f3e5 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/ethpool/P2PEthPoolApi.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/ethpool/P2PEthPoolApi.kt @@ -23,9 +23,7 @@ interface P2PEthPoolApi { * @param network Ethereum pool network: "mainnet" or "hoodi" (testnet) */ @GET("api/v1/staking/pool/{network}/vaults") - suspend fun getVaults( - @Path("network") network: String = "mainnet", - ): ApiResponse> + suspend fun getVaults(@Path("network") network: String): ApiResponse> /** * Prepare deposit transaction diff --git a/core/datasource/src/test/kotlin/com/tangem/datasource/api/common/config/managers/ProdApiConfigsManagerTest.kt b/core/datasource/src/test/kotlin/com/tangem/datasource/api/common/config/managers/ProdApiConfigsManagerTest.kt index 37f48a1f83..bf6b755bc5 100644 --- a/core/datasource/src/test/kotlin/com/tangem/datasource/api/common/config/managers/ProdApiConfigsManagerTest.kt +++ b/core/datasource/src/test/kotlin/com/tangem/datasource/api/common/config/managers/ProdApiConfigsManagerTest.kt @@ -12,6 +12,7 @@ import com.tangem.datasource.api.common.config.ApiConfig.Companion.MOCKED_BUILD_ import com.tangem.datasource.api.common.config.ApiConfig.Companion.RELEASE_BUILD_TYPE import com.tangem.datasource.api.common.config.managers.MockEnvironmentConfigStorage.Companion.BLOCK_AID_API_KEY import com.tangem.datasource.api.common.config.managers.MockEnvironmentConfigStorage.Companion.TANGEM_API_KEY +import com.tangem.domain.staking.model.ethpool.P2PStakingConfig import com.tangem.lib.auth.ExpressAuthProvider import com.tangem.lib.auth.P2PEthPoolAuthProvider import com.tangem.lib.auth.StakeKitAuthProvider @@ -299,11 +300,17 @@ internal class ProdApiConfigsManagerTest { } private fun createP2PModel(): TestModel { + val (environment, baseUrl) = if (P2PStakingConfig.USE_TESTNET) { + ApiEnvironment.DEV to "https://api-test.p2p.org/" + } else { + ApiEnvironment.PROD to "https://api.p2p.org/" + } + return TestModel( id = ApiConfig.ID.P2PEthPool, expected = ApiEnvironmentConfig( - environment = ApiEnvironment.PROD, - baseUrl = "https://api.p2p.org/", + environment = environment, + baseUrl = baseUrl, headers = mapOf( "Authorization" to ProviderSuspend { "Bearer $P2P_API_KEY" }, "accept" to ProviderSuspend { "application/json" }, diff --git a/data/staking/src/main/java/com/tangem/data/staking/DefaultP2PEthPoolRepository.kt b/data/staking/src/main/java/com/tangem/data/staking/DefaultP2PEthPoolRepository.kt index b97325f373..85f3038652 100644 --- a/data/staking/src/main/java/com/tangem/data/staking/DefaultP2PEthPoolRepository.kt +++ b/data/staking/src/main/java/com/tangem/data/staking/DefaultP2PEthPoolRepository.kt @@ -223,30 +223,18 @@ internal class DefaultP2PEthPoolRepository( .map { vaults -> if (vaults.isEmpty()) { return@map StakingAvailability.TemporaryUnavailable - } - - val vault = findPublicVault(vaults = vaults) - - if (vault != null) { - StakingAvailability.Available(StakingOption.P2P(vault)) } else { - StakingAvailability.TemporaryUnavailable + StakingAvailability.Available(StakingOption.P2P(vaults)) } } } override suspend fun getStakingAvailabilitySync(): StakingAvailability { val vaults = getVaultsSync() - if (vaults.isEmpty()) { - return StakingAvailability.TemporaryUnavailable - } - - val vault = findPublicVault(vaults = vaults) - - return if (vault != null) { - StakingAvailability.Available(StakingOption.P2P(vault)) - } else { + return if (vaults.isEmpty()) { StakingAvailability.TemporaryUnavailable + } else { + StakingAvailability.Available(StakingOption.P2P(vaults)) } } @@ -257,8 +245,4 @@ internal class DefaultP2PEthPoolRepository( private fun getVaultsFlow(): Flow> { return p2pEthPoolVaultsStore.get() } - - private fun findPublicVault(vaults: List): P2PEthPoolVault? { - return vaults.firstOrNull { vault -> !vault.isPrivate } - } } \ No newline at end of file diff --git a/data/staking/src/main/java/com/tangem/data/staking/multi/DefaultMultiStakingBalanceFetcher.kt b/data/staking/src/main/java/com/tangem/data/staking/multi/DefaultMultiStakingBalanceFetcher.kt index 99395f26b0..8a2411fc11 100644 --- a/data/staking/src/main/java/com/tangem/data/staking/multi/DefaultMultiStakingBalanceFetcher.kt +++ b/data/staking/src/main/java/com/tangem/data/staking/multi/DefaultMultiStakingBalanceFetcher.kt @@ -24,7 +24,7 @@ import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.models.wallet.isMultiCurrency import com.tangem.domain.staking.model.StakingIntegrationID -import com.tangem.domain.staking.model.ethpool.P2PEthPoolNetwork +import com.tangem.domain.staking.model.ethpool.P2PStakingConfig import com.tangem.domain.staking.multi.MultiStakingBalanceFetcher import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.coroutines.runSuspendCatching @@ -155,7 +155,7 @@ internal class DefaultMultiStakingBalanceFetcher @Inject constructor( for (address in addresses) { runSuspendCatching { val response = p2pApi.getAccountInfo( - network = P2PEthPoolNetwork.MAINNET.value, + network = P2PStakingConfig.activeNetwork.value, delegatorAddress = address, vaultAddress = vault.vaultAddress, ) diff --git a/domain/models/src/main/kotlin/com/tangem/domain/models/staking/StakingID.kt b/domain/models/src/main/kotlin/com/tangem/domain/models/staking/StakingID.kt index e684f70531..64c8249582 100644 --- a/domain/models/src/main/kotlin/com/tangem/domain/models/staking/StakingID.kt +++ b/domain/models/src/main/kotlin/com/tangem/domain/models/staking/StakingID.kt @@ -2,11 +2,6 @@ package com.tangem.domain.models.staking import kotlinx.serialization.Serializable -enum class StakingProvider { - STAKEKIT, - P2P, -} - @Serializable data class StakingID( val integrationId: String, diff --git a/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/StakingOption.kt b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/StakingOption.kt index 77078dd75e..60f9674e3f 100644 --- a/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/StakingOption.kt +++ b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/StakingOption.kt @@ -39,11 +39,11 @@ sealed interface StakingOption { * P2P pooled staking option * Wraps P2P ETH Pool vault information */ - data class P2P(val vault: P2PEthPoolVault) : StakingOption { + data class P2P(val vaults: List) : StakingOption { override val integrationId: String = "p2p-ethereum-pooled" - override val apy: SerializedBigDecimal = vault.apy + override val apy: SerializedBigDecimal = vaults.maxOf { it.apy } override val token: YieldToken = createEthToken() - override val isAvailable: Boolean = !vault.isPrivate + override val isAvailable: Boolean = vaults.isNotEmpty() private fun createEthToken(): YieldToken { // TODO return YieldToken( diff --git a/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/ethpool/P2PEthPoolNetwork.kt b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/ethpool/P2PEthPoolNetwork.kt index 2321e39114..dfbed790f9 100644 --- a/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/ethpool/P2PEthPoolNetwork.kt +++ b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/ethpool/P2PEthPoolNetwork.kt @@ -11,6 +11,8 @@ enum class P2PEthPoolNetwork( val value: String, val displayName: String, val chainId: Int, + val stakingNetworkId: String, + val isTestnet: Boolean, ) { /** * Ethereum mainnet @@ -20,16 +22,20 @@ enum class P2PEthPoolNetwork( value = "mainnet", displayName = "Ethereum", chainId = 1, + stakingNetworkId = "ethereum", + isTestnet = false, ), /** - * Ethereum testnet (Holesky) + * Ethereum testnet (Hoodi) * Chain ID: 17000 */ TESTNET( value = "hoodi", - displayName = "Holesky Testnet", + displayName = "Hoodi Testnet", chainId = 17000, + stakingNetworkId = "ethereum/test", + isTestnet = true, ), ; diff --git a/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/ethpool/P2PStakingConfig.kt b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/ethpool/P2PStakingConfig.kt new file mode 100644 index 0000000000..52c0f311e8 --- /dev/null +++ b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/ethpool/P2PStakingConfig.kt @@ -0,0 +1,14 @@ +package com.tangem.domain.staking.model.ethpool + +/** + * Configuration for P2P Ethereum staking network. + * + * Change [USE_TESTNET] to switch between testnet and mainnet. + */ +object P2PStakingConfig { + + const val USE_TESTNET: Boolean = true + + val activeNetwork: P2PEthPoolNetwork + get() = if (USE_TESTNET) P2PEthPoolNetwork.TESTNET else P2PEthPoolNetwork.MAINNET +} \ No newline at end of file diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/model/StakingIntegrationID.kt b/domain/staking/src/main/java/com/tangem/domain/staking/model/StakingIntegrationID.kt index 3ce629bf6f..1bf895cbcc 100644 --- a/domain/staking/src/main/java/com/tangem/domain/staking/model/StakingIntegrationID.kt +++ b/domain/staking/src/main/java/com/tangem/domain/staking/model/StakingIntegrationID.kt @@ -5,6 +5,7 @@ import com.tangem.blockchainsdk.utils.toBlockchain import com.tangem.blockchainsdk.utils.toMigratedCoinId import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.network.Network +import com.tangem.domain.staking.model.ethpool.P2PStakingConfig /** * Represents a staking integration identifier. @@ -101,8 +102,10 @@ sealed interface StakingIntegrationID { enum class P2P : StakingIntegrationID { EthereumPooled { override val value: String = "p2p-ethereum-pooled" - override val blockchain: Blockchain = Blockchain.Ethereum - override val networkId: String = "ethereum" + override val blockchain: Blockchain + get() = if (P2PStakingConfig.USE_TESTNET) Blockchain.EthereumTestnet else Blockchain.Ethereum + override val networkId: String + get() = P2PStakingConfig.activeNetwork.stakingNetworkId }, } diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/repositories/P2PEthPoolRepository.kt b/domain/staking/src/main/java/com/tangem/domain/staking/repositories/P2PEthPoolRepository.kt index fabb8176d1..8a116ff9b6 100644 --- a/domain/staking/src/main/java/com/tangem/domain/staking/repositories/P2PEthPoolRepository.kt +++ b/domain/staking/src/main/java/com/tangem/domain/staking/repositories/P2PEthPoolRepository.kt @@ -2,7 +2,13 @@ package com.tangem.domain.staking.repositories import arrow.core.Either import com.tangem.domain.staking.model.StakingAvailability -import com.tangem.domain.staking.model.ethpool.* +import com.tangem.domain.staking.model.ethpool.P2PEthPoolAccount +import com.tangem.domain.staking.model.ethpool.P2PEthPoolBroadcastResult +import com.tangem.domain.staking.model.ethpool.P2PEthPoolNetwork +import com.tangem.domain.staking.model.ethpool.P2PEthPoolReward +import com.tangem.domain.staking.model.ethpool.P2PEthPoolUnsignedTx +import com.tangem.domain.staking.model.ethpool.P2PEthPoolVault +import com.tangem.domain.staking.model.ethpool.P2PStakingConfig import com.tangem.domain.staking.model.stakekit.StakingError import kotlinx.coroutines.flow.Flow @@ -13,7 +19,7 @@ interface P2PEthPoolRepository { * * @param network P2P network (MAINNET or TESTNET) */ - suspend fun fetchVaults(network: P2PEthPoolNetwork = P2PEthPoolNetwork.MAINNET) + suspend fun fetchVaults(network: P2PEthPoolNetwork = P2PStakingConfig.activeNetwork) /** * Get list of available staking vaults @@ -22,7 +28,7 @@ interface P2PEthPoolRepository { * @return Either error or list of vaults with APY, capacity, fees */ suspend fun getVaults( - network: P2PEthPoolNetwork = P2PEthPoolNetwork.MAINNET, + network: P2PEthPoolNetwork = P2PStakingConfig.activeNetwork, ): Either> /** diff --git a/domain/staking/src/test/kotlin/com/tangem/domain/staking/StakingIdFactoryTest.kt b/domain/staking/src/test/kotlin/com/tangem/domain/staking/StakingIdFactoryTest.kt index dc18df883b..996ea8cca0 100644 --- a/domain/staking/src/test/kotlin/com/tangem/domain/staking/StakingIdFactoryTest.kt +++ b/domain/staking/src/test/kotlin/com/tangem/domain/staking/StakingIdFactoryTest.kt @@ -149,7 +149,7 @@ internal class StakingIdFactoryTest { expected = createStakingId(integrationId = StakingIntegrationID.StakeKit.Coin.Cardano), ), CreateModel( - currencyId = createCurrencyId(blockchain = Blockchain.Ethereum), + currencyId = createCurrencyId(blockchain = StakingIntegrationID.P2P.EthereumPooled.blockchain), expected = createStakingId(integrationId = StakingIntegrationID.P2P.EthereumPooled), ), CreateModel( diff --git a/domain/staking/src/test/kotlin/com/tangem/domain/staking/StakingIntegrationIDTest.kt b/domain/staking/src/test/kotlin/com/tangem/domain/staking/StakingIntegrationIDTest.kt index ed60c5fd0c..745af46793 100644 --- a/domain/staking/src/test/kotlin/com/tangem/domain/staking/StakingIntegrationIDTest.kt +++ b/domain/staking/src/test/kotlin/com/tangem/domain/staking/StakingIntegrationIDTest.kt @@ -151,7 +151,7 @@ class StakingIntegrationIDTest { expected = StakingIntegrationID.StakeKit.Coin.Cardano, ), CreateModel( - currencyId = createCurrencyId(blockchain = Blockchain.Ethereum), + currencyId = createCurrencyId(blockchain = StakingIntegrationID.P2P.EthereumPooled.blockchain), expected = StakingIntegrationID.P2P.EthereumPooled, ), CreateModel( diff --git a/gradle/tangem_dependencies.toml b/gradle/tangem_dependencies.toml index 487e084342..8c10bcaf9d 100644 --- a/gradle/tangem_dependencies.toml +++ b/gradle/tangem_dependencies.toml @@ -5,7 +5,7 @@ # https://github.com/tangem/tangem-sdk-android/ # https://github.com/tangem/vico -tangemBlockchainSdk = "develop-1309" +tangemBlockchainSdk = "develop-1317" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "develop-568" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^