diff --git a/app/src/main/java/com/tangem/tap/network/auth/DefaultExpressAuthProvider.kt b/app/src/main/java/com/tangem/tap/network/auth/DefaultExpressAuthProvider.kt index 6cd26d788e..f7b18ad5a2 100644 --- a/app/src/main/java/com/tangem/tap/network/auth/DefaultExpressAuthProvider.kt +++ b/app/src/main/java/com/tangem/tap/network/auth/DefaultExpressAuthProvider.kt @@ -15,11 +15,11 @@ internal class DefaultExpressAuthProvider( private var uuid = AtomicReference(UUID.randomUUID()) override fun getApiKey(): String { - return configManager.config.express?.apiKey ?: "" + return configManager.config.express?.apiKey ?: error("No express api key provided") } override fun getUserId(): String { - return userWalletsStore.selectedUserWalletOrNull?.walletId?.stringValue ?: "" + return userWalletsStore.selectedUserWalletOrNull?.walletId?.stringValue ?: error("No user id provided") } override fun getSessionId(): String { diff --git a/app/src/main/java/com/tangem/tap/network/auth/DefaultStakeKitAuthProvider.kt b/app/src/main/java/com/tangem/tap/network/auth/DefaultStakeKitAuthProvider.kt new file mode 100644 index 0000000000..7e953fdfd5 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/network/auth/DefaultStakeKitAuthProvider.kt @@ -0,0 +1,13 @@ +package com.tangem.tap.network.auth + +import com.tangem.datasource.config.ConfigManager +import com.tangem.lib.auth.StakeKitAuthProvider + +internal class DefaultStakeKitAuthProvider( + private val configManager: ConfigManager, +) : StakeKitAuthProvider { + + override fun getApiKey(): String { + return configManager.config.express?.apiKey ?: error("No StakeKit api key provided") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/network/auth/di/AuthModule.kt b/app/src/main/java/com/tangem/tap/network/auth/di/AuthModule.kt index 06b2edda3a..56548f515c 100644 --- a/app/src/main/java/com/tangem/tap/network/auth/di/AuthModule.kt +++ b/app/src/main/java/com/tangem/tap/network/auth/di/AuthModule.kt @@ -5,9 +5,11 @@ import com.tangem.datasource.config.ConfigManager import com.tangem.datasource.local.userwallet.UserWalletsStore import com.tangem.lib.auth.AppVersionProvider import com.tangem.lib.auth.ExpressAuthProvider +import com.tangem.lib.auth.StakeKitAuthProvider import com.tangem.tap.network.auth.DefaultAppVersionProvider import com.tangem.tap.network.auth.DefaultAuthProvider import com.tangem.tap.network.auth.DefaultExpressAuthProvider +import com.tangem.tap.network.auth.DefaultStakeKitAuthProvider import com.tangem.tap.proxy.AppStateHolder import dagger.Module import dagger.Provides @@ -37,6 +39,12 @@ class AuthModule { ) } + @Provides + @Singleton + fun provideStakeKitAuthProvider(configManager: ConfigManager): StakeKitAuthProvider { + return DefaultStakeKitAuthProvider(configManager) + } + @Provides @Singleton fun provideAppVersionProvider(): AppVersionProvider { diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/StakeKitApi.kt b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/StakeKitApi.kt new file mode 100644 index 0000000000..e0adeb7a84 --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/StakeKitApi.kt @@ -0,0 +1,32 @@ +package com.tangem.datasource.api.stakekit + +import com.tangem.datasource.api.common.response.ApiResponse +import com.tangem.datasource.api.stakekit.models.request.MultipleYieldBalancesRequestBody +import com.tangem.datasource.api.stakekit.models.request.RevenueOption +import com.tangem.datasource.api.stakekit.models.request.YieldType +import com.tangem.datasource.api.stakekit.models.response.EnabledYieldsResponse +import com.tangem.datasource.api.stakekit.models.response.model.TokenWithYield +import com.tangem.datasource.api.stakekit.models.response.model.YieldBalances +import retrofit2.http.Body +import retrofit2.http.GET +import retrofit2.http.Query + +@Suppress("LongParameterList") +interface StakeKitApi { + + @GET("yields/enabled") + fun getAllYields( + @Query("ledgerWalletAPICompatible") ledgerWalletAPICompatible: Boolean, + @Query("type") type: YieldType, + @Query("revenueOption") revenueOption: RevenueOption, + @Query("page") page: Int, + @Query("network") network: String, + @Query("limit") limit: Int, + ): ApiResponse + + @GET("yields/balances") + fun getMultipleYieldBalances(@Body body: List): ApiResponse> + + @GET("tokens") + fun getTokens(): ApiResponse> +} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/UnknownEnumMoshiAdapter.kt b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/UnknownEnumMoshiAdapter.kt new file mode 100644 index 0000000000..20fe881be9 --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/UnknownEnumMoshiAdapter.kt @@ -0,0 +1,13 @@ +package com.tangem.datasource.api.stakekit + +import com.squareup.moshi.* +import com.squareup.moshi.adapters.EnumJsonAdapter + +/** + * Object to create a adapter for enum types with support for unknown enum values. + */ +object UnknownEnumMoshiAdapter { + + fun > create(enumType: Class, defaultValue: T): JsonAdapter = + EnumJsonAdapter.create(enumType).withUnknownFallback(defaultValue) +} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/request/MultipleYieldBalancesRequestBody.kt b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/request/MultipleYieldBalancesRequestBody.kt new file mode 100644 index 0000000000..1872f19673 --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/request/MultipleYieldBalancesRequestBody.kt @@ -0,0 +1,31 @@ +package com.tangem.datasource.api.stakekit.models.request + +import com.squareup.moshi.Json + +data class MultipleYieldBalancesRequestBody( + @Json(name = "addresses") val addresses: Address, + @Json(name = "args") val args: MultipleYieldBalancesRequestArgs, + @Json(name = "integrationId") val integrationId: String, +) { + + data class Address( + @Json(name = "address") val address: String, + @Json(name = "additionalAddresses") val additionalAddresses: AdditionalAddresses? = null, + @Json(name = "explorerUrl") val explorerUrl: String, + ) { + + data class AdditionalAddresses( + @Json(name = "cosmosPubKey") val cosmosPubKey: String? = null, + @Json(name = "binanceBeaconAddress") val binanceBeaconAddress: String? = null, + @Json(name = "stakeAccounts") val stakeAccounts: List? = null, + @Json(name = "lidoStakeAccounts") val lidoStakeAccounts: List? = null, + @Json(name = "tezosPubKey") val tezosPubKey: String? = null, + @Json(name = "cAddressBech") val cAddressBech: String? = null, + @Json(name = "pAddressBech") val pAddressBech: String? = null, + ) + } + + data class MultipleYieldBalancesRequestArgs( + @Json(name = "validatorAddresses") val validatorAddresses: List, + ) +} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/request/RevenueOption.kt b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/request/RevenueOption.kt new file mode 100644 index 0000000000..e396cd7ebb --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/request/RevenueOption.kt @@ -0,0 +1,11 @@ +package com.tangem.datasource.api.stakekit.models.request + +enum class RevenueOption(val value: String) { + SUPPORTS_FEE("supportsFee"), + SUPPORTS_REV_SHARE("supportsRevShare"), + ; + + override fun toString(): String { + return value + } +} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/request/YieldType.kt b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/request/YieldType.kt new file mode 100644 index 0000000000..5eb7182cb5 --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/request/YieldType.kt @@ -0,0 +1,14 @@ +package com.tangem.datasource.api.stakekit.models.request + +enum class YieldType(private val value: String) { + STAKING("staking"), + LIQUID_STAKING("liquid-staking"), + LENDING("lending"), + RESTAKING("restaking"), + VAULT("vault"), + ; + + override fun toString(): String { + return value + } +} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/response/EnabledYieldsResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/response/EnabledYieldsResponse.kt new file mode 100644 index 0000000000..c4a958c435 --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/response/EnabledYieldsResponse.kt @@ -0,0 +1,17 @@ +package com.tangem.datasource.api.stakekit.models.response + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass +import com.tangem.datasource.api.stakekit.models.response.model.Yield + +@JsonClass(generateAdapter = true) +data class EnabledYieldsResponse( + @Json(name = "data") + val data: List, + @Json(name = "hasNextPage") + val hasNextPage: Boolean, + @Json(name = "limit") + val limit: Int, + @Json(name = "page") + val page: Int, +) \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/response/model/AddressArgument.kt b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/response/model/AddressArgument.kt new file mode 100644 index 0000000000..301b7b5805 --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/response/model/AddressArgument.kt @@ -0,0 +1,16 @@ +package com.tangem.datasource.api.stakekit.models.response.model + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class AddressArgument( + @Json(name = "required") + val required: Boolean, + @Json(name = "network") + val network: String? = null, + @Json(name = "minimum") + val minimum: Int? = null, + @Json(name = "maximum") + val maximum: Int? = null, +) \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/response/model/StakingActionType.kt b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/response/model/StakingActionType.kt new file mode 100644 index 0000000000..5e60da84d9 --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/response/model/StakingActionType.kt @@ -0,0 +1,50 @@ +package com.tangem.datasource.api.stakekit.models.response.model + +import com.squareup.moshi.Json + +enum class StakingActionType { + @Json(name = "STAKE") + STAKE, + + @Json(name = "UNSTAKE") + UNSTAKE, + + @Json(name = "CLAIM_REWARDS") + CLAIM_REWARDS, + + @Json(name = "RESTAKE_REWARDS") + RESTAKE_REWARDS, + + @Json(name = "WITHDRAW") + WITHDRAW, + + @Json(name = "RESTAKE") + RESTAKE, + + @Json(name = "CLAIM_UNSTAKED") + CLAIM_UNSTAKED, + + @Json(name = "UNLOCK_LOCKED") + UNLOCK_LOCKED, + + @Json(name = "STAKE_LOCKED") + STAKE_LOCKED, + + @Json(name = "VOTE") + VOTE, + + @Json(name = "REVOKE") + REVOKE, + + @Json(name = "VOTE_LOCKED") + VOTE_LOCKED, + + @Json(name = "REVOTE") + REVOTE, + + @Json(name = "REBOND") + REBOND, + + @Json(name = "MIGRATE") + MIGRATE, +} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/response/model/Token.kt b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/response/model/Token.kt new file mode 100644 index 0000000000..35ed171d9e --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/response/model/Token.kt @@ -0,0 +1,218 @@ +package com.tangem.datasource.api.stakekit.models.response.model + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class Token( + @Json(name = "name") val name: String, + @Json(name = "network") val network: NetworkType, + @Json(name = "symbol") val symbol: String, + @Json(name = "decimals") val decimals: Int, + @Json(name = "address") val address: String?, + @Json(name = "coinGeckoId") val coinGeckoId: String?, + @Json(name = "logoURI") val logoURI: String?, + @Json(name = "isPoints") val isPoints: Boolean, +) { + enum class NetworkType { + @Json(name = "avalanche") + AVALANCHE, + + @Json(name = "avalanche-atomic") + AVALANCHE_ATOMIC, + + @Json(name = "avalanche-p") + AVALANCHE_P, + + @Json(name = "arbitrum") + ARBITRUM, + + @Json(name = "binance") + BINANCE, + + @Json(name = "celo") + CELO, + + @Json(name = "ethereum") + ETHEREUM, + + @Json(name = "ethereum-goerli") + ETHEREUM_GOERLI, + + @Json(name = "ethereum-holesky") + ETHEREUM_HOLESKY, + + @Json(name = "fantom") + FANTOM, + + @Json(name = "harmony") + HARMONY, + + @Json(name = "optimism") + OPTIMISM, + + @Json(name = "polygon") + POLYGON, + + @Json(name = "gnosis") + GNOSIS, + + @Json(name = "moonriver") + MOONRIVER, + + @Json(name = "okc") + OKC, + + @Json(name = "zksync") + ZKSYNC, + + @Json(name = "viction") + VICTION, + + @Json(name = "agoric") + AGORIC, + + @Json(name = "akash") + AKASH, + + @Json(name = "axelar") + AXELAR, + + @Json(name = "band-protocol") + BAND_PROTOCOL, + + @Json(name = "bitsong") + BITSONG, + + @Json(name = "canto") + CANTO, + + @Json(name = "chihuahua") + CHIHUAHUA, + + @Json(name = "comdex") + COMDEX, + + @Json(name = "coreum") + COREUM, + + @Json(name = "cosmos") + COSMOS, + + @Json(name = "crescent") + CRESCENT, + + @Json(name = "cronos") + CRONOS, + + @Json(name = "cudos") + CUDOS, + + @Json(name = "desmos") + DESMOS, + + @Json(name = "dydx") + DYDX, + + @Json(name = "evmos") + EVMOS, + + @Json(name = "fetch-ai") + FETCH_AI, + + @Json(name = "gravity-bridge") + GRAVITY_BRIDGE, + + @Json(name = "injective") + INJECTIVE, + + @Json(name = "irisnet") + IRISNET, + + @Json(name = "juno") + JUNO, + + @Json(name = "kava") + KAVA, + + @Json(name = "ki-network") + KI_NETWORK, + + @Json(name = "mars-protocol") + MARS_PROTOCOL, + + @Json(name = "nym") + NYM, + + @Json(name = "okex-chain") + OKEX_CHAIN, + + @Json(name = "onomy") + ONOMY, + + @Json(name = "osmosis") + OSMOSIS, + + @Json(name = "persistence") + PERSISTENCE, + + @Json(name = "quicksilver") + QUICKSILVER, + + @Json(name = "regen") + REGEN, + + @Json(name = "secret") + SECRET, + + @Json(name = "sentinel") + SENTINEL, + + @Json(name = "sommelier") + SOMMELIER, + + @Json(name = "stafi") + STAFI, + + @Json(name = "stargaze") + STARGAZE, + + @Json(name = "stride") + STRIDE, + + @Json(name = "teritori") + TERITORI, + + @Json(name = "tgrade") + TGRADE, + + @Json(name = "umee") + UMEE, + + @Json(name = "polkadot") + POLKADOT, + + @Json(name = "kusama") + KUSAMA, + + @Json(name = "westend") + WESTEND, + + @Json(name = "binancebeacon") + BINANCEBEACON, + + @Json(name = "near") + NEAR, + + @Json(name = "solana") + SOLANA, + + @Json(name = "tezos") + TEZOS, + + @Json(name = "tron") + TRON, + + UNKNOWN, + } +} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/response/model/TokenWithYield.kt b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/response/model/TokenWithYield.kt new file mode 100644 index 0000000000..2bc30185af --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/response/model/TokenWithYield.kt @@ -0,0 +1,10 @@ +package com.tangem.datasource.api.stakekit.models.response.model + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class TokenWithYield( + @Json(name = "token") val token: Token, + @Json(name = "availableYields") val availableYieldIds: List, +) \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/response/model/Yield.kt b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/response/model/Yield.kt new file mode 100644 index 0000000000..5f728eae71 --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/response/model/Yield.kt @@ -0,0 +1,145 @@ +package com.tangem.datasource.api.stakekit.models.response.model + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class Yield( + @Json(name = "id") + val id: String, + @Json(name = "token") + val token: Token, + @Json(name = "tokens") + val tokens: List, + @Json(name = "args") + val args: Args, + @Json(name = "status") + val status: Status, + @Json(name = "apy") + val apy: Double, + @Json(name = "rewardRate") + val rewardRate: Double, + @Json(name = "rewardType") + val rewardType: RewardType, + @Json(name = "metadata") + val metadata: Metadata, + @Json(name = "validators") + val validators: List, + @Json(name = "isAvailable") + val isAvailable: Boolean, +) { + + @JsonClass(generateAdapter = true) + data class Status( + @Json(name = "enter") + val enter: Boolean, + @Json(name = "exit") + val exit: Boolean?, + ) + + @JsonClass(generateAdapter = true) + data class Args( + @Json(name = "enter") + val enter: Enter, + @Json(name = "exit") + val exit: Enter?, + ) { + @JsonClass(generateAdapter = true) + data class Enter( + @Json(name = "addresses") + val addresses: Addresses, + @Json(name = "args") + val args: Map, + ) { + @JsonClass(generateAdapter = true) + data class Addresses( + @Json(name = "address") + val address: AddressArgument, + @Json(name = "additionalAddresses") + val additionalAddresses: Map? = null, + ) + } + } + + @JsonClass(generateAdapter = true) + data class Validator( + @Json(name = "address") + val address: String, + @Json(name = "status") + val status: String, + @Json(name = "name") + val name: String, + @Json(name = "image") + val image: String?, + @Json(name = "website") + val website: String?, + @Json(name = "apr") + val apr: Double?, + @Json(name = "commission") + val commission: Double?, + @Json(name = "stakedBalance") + val stakedBalance: String?, + @Json(name = "votingPower") + val votingPower: Double?, + @Json(name = "preferred") + val preferred: Boolean, + ) + + @JsonClass(generateAdapter = true) + data class Metadata( + @Json(name = "name") + val name: String, + @Json(name = "logoURI") + val logoUri: String, + @Json(name = "description") + val description: String, + @Json(name = "documentation") + val documentation: String?, + @Json(name = "gasFeeToken") + val gasFeeToken: Token, + @Json(name = "token") + val token: Token, + @Json(name = "tokens") + val tokens: List, + @Json(name = "type") + val type: String, + @Json(name = "rewardSchedule") + val rewardSchedule: String, + @Json(name = "cooldownPeriod") + val cooldownPeriod: Period, + @Json(name = "warmupPeriod") + val warmupPeriod: Period, + @Json(name = "rewardClaiming") + val rewardClaiming: String, + @Json(name = "defaultValidator") + val defaultValidator: String?, + @Json(name = "minimumStake") + val minimumStake: Int, + @Json(name = "supportsMultipleValidators") + val supportsMultipleValidators: Boolean, + @Json(name = "revshare") + val revshare: Enabled, + @Json(name = "fee") + val fee: Enabled, + ) { + + @JsonClass(generateAdapter = true) + data class Period( + @Json(name = "days") + val days: Int, + ) + + @JsonClass(generateAdapter = true) + data class Enabled( + @Json(name = "enabled") + val enabled: Boolean, + ) + } + + enum class RewardType { + @Json(name = "apy") + APY, // auto + @Json(name = "apr") + APR, // manual + } +} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/response/model/YieldBalances.kt b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/response/model/YieldBalances.kt new file mode 100644 index 0000000000..98637444a4 --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/models/response/model/YieldBalances.kt @@ -0,0 +1,138 @@ +package com.tangem.datasource.api.stakekit.models.response.model + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass +import org.joda.time.DateTime +import java.math.BigDecimal + +@JsonClass(generateAdapter = true) +data class YieldBalances( + @Json(name = "balances") + val balances: List, + @Json(name = "integrationId") + val integrationId: String, +) { + + @JsonClass(generateAdapter = true) + data class Balance( + @Json(name = "groupId") + val groupId: String, + @Json(name = "type") + val type: BalanceType, + @Json(name = "amount") + val amount: BigDecimal, + @Json(name = "date") + val date: DateTime?, + @Json(name = "pricePerShare") + val pricePerShare: BigDecimal, + @Json(name = "pendingActions") + val pendingActions: List, + @Json(name = "token") + val token: Token, + @Json(name = "validatorAddress") + val validatorAddress: String?, + @Json(name = "validatorAddresses") + val validatorAddresses: List?, + @Json(name = "providerId") + val providerId: String?, + ) { + + enum class BalanceType { + @Json(name = "available") + AVAILABLE, + + @Json(name = "staked") + STAKED, + + @Json(name = "unstaking") + UNSTAKING, + + @Json(name = "unstaked") + UNSTAKED, + + @Json(name = "preparing") + PREPARING, + + @Json(name = "rewards") + REWARDS, + + @Json(name = "locked") + LOCKED, + + @Json(name = "unlocking") + UNLOCKING, + } + + @JsonClass(generateAdapter = true) + data class PendingAction( + @Json(name = "type") + val type: StakingActionType, + @Json(name = "passthrough") + val passthrough: String, + @Json(name = "args") + val args: PendingActionArgs?, + ) { + @JsonClass(generateAdapter = true) + data class PendingActionArgs( + @Json(name = "amount") + val amount: Amount?, + @Json(name = "duration") + val duration: Duration?, + @Json(name = "validatorAddress") + val validatorAddress: Required?, + @Json(name = "validatorAddresses") + val validatorAddresses: Required?, + @Json(name = "nfts") + val nfts: List?, + @Json(name = "tronResource") + val tronResource: TronResource?, + @Json(name = "signatureVerification") + val signatureVerification: Required?, + ) { + @JsonClass(generateAdapter = true) + data class Amount( + @Json(name = "required") + val required: Boolean, + @Json(name = "minimum") + val minimum: BigDecimal?, + @Json(name = "maximum") + val maximum: BigDecimal?, + ) + + @JsonClass(generateAdapter = true) + data class Duration( + @Json(name = "required") + val required: Boolean, + @Json(name = "minimum") + val minimum: Int?, + @Json(name = "maximum") + val maximum: Int?, + ) + + @JsonClass(generateAdapter = true) + data class Nft( + @Json(name = "baycId") + val baycId: Required?, + @Json(name = "maycId") + val maycId: Required?, + @Json(name = "bakcId") + val bakcId: Required?, + ) + + @JsonClass(generateAdapter = true) + data class TronResource( + @Json(name = "required") + val required: Boolean, + @Json(name = "options") + val options: List, + ) + } + } + + @JsonClass(generateAdapter = true) + data class Required( + @Json(name = "required") + val required: Boolean, + ) + } +} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/config/ConfigManagerImpl.kt b/core/datasource/src/main/java/com/tangem/datasource/config/ConfigManagerImpl.kt index 094cc6c04b..cd697735cb 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/config/ConfigManagerImpl.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/config/ConfigManagerImpl.kt @@ -106,6 +106,7 @@ internal class ConfigManagerImpl @Inject constructor() : ConfigManager { walletConnectProjectId = configValues.walletConnectProjectId, tangemComAuthorization = configValues.tangemComAuthorization, express = if (BuildConfig.ENVIRONMENT == "dev") configValues.devExpress else configValues.express, + stakeKitApiKey = configValues.stakeKitApiKey, ) } diff --git a/core/datasource/src/main/java/com/tangem/datasource/config/models/Config.kt b/core/datasource/src/main/java/com/tangem/datasource/config/models/Config.kt index 28e5b2b4d3..3f54641502 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/config/models/Config.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/config/models/Config.kt @@ -17,4 +17,5 @@ data class Config( val walletConnectProjectId: String = "", val tangemComAuthorization: String? = null, val express: ExpressModel? = null, + val stakeKitApiKey: String? = null, ) \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/config/models/JsonModels.kt b/core/datasource/src/main/java/com/tangem/datasource/config/models/JsonModels.kt index 91ae26a0d4..a3f41169e6 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/config/models/JsonModels.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/config/models/JsonModels.kt @@ -42,6 +42,7 @@ class ConfigValueModel( val devExpress: ExpressModel?, val express: ExpressModel?, val polygonScanApiKey: String?, + val stakeKitApiKey: String?, ) @JsonClass(generateAdapter = true) diff --git a/core/datasource/src/main/java/com/tangem/datasource/di/MoshiModule.kt b/core/datasource/src/main/java/com/tangem/datasource/di/MoshiModule.kt index 3884c6c9a5..81956364f7 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/di/MoshiModule.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/di/MoshiModule.kt @@ -7,6 +7,8 @@ import com.tangem.common.json.MoshiJsonConverter import com.tangem.datasource.api.common.BigDecimalAdapter import com.tangem.datasource.api.common.DateTimeAdapter import com.tangem.datasource.api.common.LocalDateAdapter +import com.tangem.datasource.api.stakekit.UnknownEnumMoshiAdapter +import com.tangem.datasource.api.stakekit.models.response.model.Token import com.tangem.datasource.config.models.ProviderModel import dagger.Module import dagger.Provides @@ -33,6 +35,10 @@ class MoshiModule { .add(LocalDateAdapter()) .add(DateTimeAdapter()) .add(KotlinJsonAdapterFactory()) + .add( + Token.NetworkType::class.java, + UnknownEnumMoshiAdapter.create(Token.NetworkType::class.java, Token.NetworkType.UNKNOWN), + ) .build() } diff --git a/core/datasource/src/main/java/com/tangem/datasource/di/NetworkModule.kt b/core/datasource/src/main/java/com/tangem/datasource/di/NetworkModule.kt index e687c394e9..a901fd6b57 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/di/NetworkModule.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/di/NetworkModule.kt @@ -5,6 +5,7 @@ import com.squareup.moshi.Moshi import com.tangem.datasource.BuildConfig import com.tangem.datasource.api.common.response.ApiResponseCallAdapterFactory import com.tangem.datasource.api.express.TangemExpressApi +import com.tangem.datasource.api.stakekit.StakeKitApi import com.tangem.datasource.api.tangemTech.TangemTechApi import com.tangem.datasource.api.tangemTech.TangemTechApiV2 import com.tangem.datasource.api.tangemTech.TangemTechServiceApi @@ -13,6 +14,7 @@ import com.tangem.datasource.utils.addHeaders import com.tangem.datasource.utils.addLoggers import com.tangem.lib.auth.AppVersionProvider import com.tangem.lib.auth.ExpressAuthProvider +import com.tangem.lib.auth.StakeKitAuthProvider import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -56,6 +58,27 @@ class NetworkModule { .create(TangemExpressApi::class.java) } + @Provides + @Singleton + fun provideStakeKitApi( + @NetworkMoshi moshi: Moshi, + @ApplicationContext context: Context, + stakeKitAuthProvider: StakeKitAuthProvider, + ): StakeKitApi { + return Retrofit.Builder() + .addConverterFactory(MoshiConverterFactory.create(moshi)) + .addCallAdapterFactory(ApiResponseCallAdapterFactory.create()) + .baseUrl(STAKEKIT_BASE_URL) + .client( + OkHttpClient.Builder() + .addHeaders(StakeKit(stakeKitAuthProvider)) + .addLoggers(context) + .build(), + ) + .build() + .create(StakeKitApi::class.java) + } + @Provides @Singleton fun provideTangemTechApi( @@ -137,6 +160,7 @@ class NetworkModule { } private companion object { + const val STAKEKIT_BASE_URL = "https://api.stakek.it/v1/" const val PROD_EXPRESS_BASE_URL = "https://express.tangem.com/v1/" const val DEV_EXPRESS_BASE_URL = "[REDACTED_ENV_URL]" @@ -146,8 +170,5 @@ class NetworkModule { const val PROD_V2_TANGEM_TECH_BASE_URL = "https://api.tangem-tech.com/v2/" const val TANGEM_TECH_SERVICE_TIMEOUT_SECONDS = 5L - - const val PAYMENTOLOGY_BASE_URL: String = "https://paymentologygate.oa.r.appspot.com/" - const val API_ONE_INCH_TIMEOUT_MS = 5000L } } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/utils/RequestHeader.kt b/core/datasource/src/main/java/com/tangem/datasource/utils/RequestHeader.kt index 1ee0e4d9f9..5e07267955 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/utils/RequestHeader.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/utils/RequestHeader.kt @@ -3,6 +3,7 @@ package com.tangem.datasource.utils import com.tangem.datasource.api.common.AuthProvider import com.tangem.lib.auth.AppVersionProvider import com.tangem.lib.auth.ExpressAuthProvider +import com.tangem.lib.auth.StakeKitAuthProvider /** * Presentation of request header @@ -31,4 +32,8 @@ sealed class RequestHeader(vararg pairs: Pair String>) { "version" to { appVersionProvider.getAppVersion() }, "platform" to { "android" }, ) + + class StakeKit(stakeKitAuthProvider: StakeKitAuthProvider) : RequestHeader( + "X-API-KEY" to { stakeKitAuthProvider.getApiKey() }, + ) } \ No newline at end of file diff --git a/libs/auth/src/main/java/com/tangem/lib/auth/AuthBearerProvider.kt b/libs/auth/src/main/java/com/tangem/lib/auth/AuthBearerProvider.kt deleted file mode 100644 index dbeac3aebe..0000000000 --- a/libs/auth/src/main/java/com/tangem/lib/auth/AuthBearerProvider.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.tangem.lib.auth - -/** - * Provides auth for tangemTech API - */ -interface AuthBearerProvider { - - /** - * Returns api-key - */ - fun getApiKey(): String -} \ No newline at end of file diff --git a/libs/auth/src/main/java/com/tangem/lib/auth/StakeKitAuthProvider.kt b/libs/auth/src/main/java/com/tangem/lib/auth/StakeKitAuthProvider.kt new file mode 100644 index 0000000000..d6f3fac532 --- /dev/null +++ b/libs/auth/src/main/java/com/tangem/lib/auth/StakeKitAuthProvider.kt @@ -0,0 +1,6 @@ +package com.tangem.lib.auth + +interface StakeKitAuthProvider { + + fun getApiKey(): String +} \ No newline at end of file