Updated on 2026-08-14
This commit is contained in:
parent
c849c203b1
commit
7ab5f7b547
23 changed files with 762 additions and 17 deletions
|
|
@ -15,11 +15,11 @@ internal class DefaultExpressAuthProvider(
|
||||||
private var uuid = AtomicReference(UUID.randomUUID())
|
private var uuid = AtomicReference(UUID.randomUUID())
|
||||||
|
|
||||||
override fun getApiKey(): String {
|
override fun getApiKey(): String {
|
||||||
return configManager.config.express?.apiKey ?: ""
|
return configManager.config.express?.apiKey ?: error("No express api key provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getUserId(): String {
|
override fun getUserId(): String {
|
||||||
return userWalletsStore.selectedUserWalletOrNull?.walletId?.stringValue ?: ""
|
return userWalletsStore.selectedUserWalletOrNull?.walletId?.stringValue ?: error("No user id provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getSessionId(): String {
|
override fun getSessionId(): String {
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,9 +5,11 @@ import com.tangem.datasource.config.ConfigManager
|
||||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||||
import com.tangem.lib.auth.AppVersionProvider
|
import com.tangem.lib.auth.AppVersionProvider
|
||||||
import com.tangem.lib.auth.ExpressAuthProvider
|
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.DefaultAppVersionProvider
|
||||||
import com.tangem.tap.network.auth.DefaultAuthProvider
|
import com.tangem.tap.network.auth.DefaultAuthProvider
|
||||||
import com.tangem.tap.network.auth.DefaultExpressAuthProvider
|
import com.tangem.tap.network.auth.DefaultExpressAuthProvider
|
||||||
|
import com.tangem.tap.network.auth.DefaultStakeKitAuthProvider
|
||||||
import com.tangem.tap.proxy.AppStateHolder
|
import com.tangem.tap.proxy.AppStateHolder
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
|
|
@ -37,6 +39,12 @@ class AuthModule {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
fun provideStakeKitAuthProvider(configManager: ConfigManager): StakeKitAuthProvider {
|
||||||
|
return DefaultStakeKitAuthProvider(configManager)
|
||||||
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
fun provideAppVersionProvider(): AppVersionProvider {
|
fun provideAppVersionProvider(): AppVersionProvider {
|
||||||
|
|
|
||||||
|
|
@ -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<EnabledYieldsResponse>
|
||||||
|
|
||||||
|
@GET("yields/balances")
|
||||||
|
fun getMultipleYieldBalances(@Body body: List<MultipleYieldBalancesRequestBody>): ApiResponse<List<YieldBalances>>
|
||||||
|
|
||||||
|
@GET("tokens")
|
||||||
|
fun getTokens(): ApiResponse<List<TokenWithYield>>
|
||||||
|
}
|
||||||
|
|
@ -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 <T : Enum<T>> create(enumType: Class<T>, defaultValue: T): JsonAdapter<T> =
|
||||||
|
EnumJsonAdapter.create(enumType).withUnknownFallback(defaultValue)
|
||||||
|
}
|
||||||
|
|
@ -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<String>? = null,
|
||||||
|
@Json(name = "lidoStakeAccounts") val lidoStakeAccounts: List<String>? = 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<String>,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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<Yield>,
|
||||||
|
@Json(name = "hasNextPage")
|
||||||
|
val hasNextPage: Boolean,
|
||||||
|
@Json(name = "limit")
|
||||||
|
val limit: Int,
|
||||||
|
@Json(name = "page")
|
||||||
|
val page: Int,
|
||||||
|
)
|
||||||
|
|
@ -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,
|
||||||
|
)
|
||||||
|
|
@ -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,
|
||||||
|
}
|
||||||
|
|
@ -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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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<String>,
|
||||||
|
)
|
||||||
|
|
@ -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<Token>,
|
||||||
|
@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<Validator>,
|
||||||
|
@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<String, AddressArgument>,
|
||||||
|
) {
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
data class Addresses(
|
||||||
|
@Json(name = "address")
|
||||||
|
val address: AddressArgument,
|
||||||
|
@Json(name = "additionalAddresses")
|
||||||
|
val additionalAddresses: Map<String, AddressArgument>? = 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<Token>,
|
||||||
|
@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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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<Balance>,
|
||||||
|
@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<PendingAction>,
|
||||||
|
@Json(name = "token")
|
||||||
|
val token: Token,
|
||||||
|
@Json(name = "validatorAddress")
|
||||||
|
val validatorAddress: String?,
|
||||||
|
@Json(name = "validatorAddresses")
|
||||||
|
val validatorAddresses: List<String>?,
|
||||||
|
@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<Nft>?,
|
||||||
|
@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<String>,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
data class Required(
|
||||||
|
@Json(name = "required")
|
||||||
|
val required: Boolean,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -106,6 +106,7 @@ internal class ConfigManagerImpl @Inject constructor() : ConfigManager {
|
||||||
walletConnectProjectId = configValues.walletConnectProjectId,
|
walletConnectProjectId = configValues.walletConnectProjectId,
|
||||||
tangemComAuthorization = configValues.tangemComAuthorization,
|
tangemComAuthorization = configValues.tangemComAuthorization,
|
||||||
express = if (BuildConfig.ENVIRONMENT == "dev") configValues.devExpress else configValues.express,
|
express = if (BuildConfig.ENVIRONMENT == "dev") configValues.devExpress else configValues.express,
|
||||||
|
stakeKitApiKey = configValues.stakeKitApiKey,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,4 +17,5 @@ data class Config(
|
||||||
val walletConnectProjectId: String = "",
|
val walletConnectProjectId: String = "",
|
||||||
val tangemComAuthorization: String? = null,
|
val tangemComAuthorization: String? = null,
|
||||||
val express: ExpressModel? = null,
|
val express: ExpressModel? = null,
|
||||||
|
val stakeKitApiKey: String? = null,
|
||||||
)
|
)
|
||||||
|
|
@ -42,6 +42,7 @@ class ConfigValueModel(
|
||||||
val devExpress: ExpressModel?,
|
val devExpress: ExpressModel?,
|
||||||
val express: ExpressModel?,
|
val express: ExpressModel?,
|
||||||
val polygonScanApiKey: String?,
|
val polygonScanApiKey: String?,
|
||||||
|
val stakeKitApiKey: String?,
|
||||||
)
|
)
|
||||||
|
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@ import com.tangem.common.json.MoshiJsonConverter
|
||||||
import com.tangem.datasource.api.common.BigDecimalAdapter
|
import com.tangem.datasource.api.common.BigDecimalAdapter
|
||||||
import com.tangem.datasource.api.common.DateTimeAdapter
|
import com.tangem.datasource.api.common.DateTimeAdapter
|
||||||
import com.tangem.datasource.api.common.LocalDateAdapter
|
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 com.tangem.datasource.config.models.ProviderModel
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
|
|
@ -33,6 +35,10 @@ class MoshiModule {
|
||||||
.add(LocalDateAdapter())
|
.add(LocalDateAdapter())
|
||||||
.add(DateTimeAdapter())
|
.add(DateTimeAdapter())
|
||||||
.add(KotlinJsonAdapterFactory())
|
.add(KotlinJsonAdapterFactory())
|
||||||
|
.add(
|
||||||
|
Token.NetworkType::class.java,
|
||||||
|
UnknownEnumMoshiAdapter.create(Token.NetworkType::class.java, Token.NetworkType.UNKNOWN),
|
||||||
|
)
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import com.squareup.moshi.Moshi
|
||||||
import com.tangem.datasource.BuildConfig
|
import com.tangem.datasource.BuildConfig
|
||||||
import com.tangem.datasource.api.common.response.ApiResponseCallAdapterFactory
|
import com.tangem.datasource.api.common.response.ApiResponseCallAdapterFactory
|
||||||
import com.tangem.datasource.api.express.TangemExpressApi
|
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.TangemTechApi
|
||||||
import com.tangem.datasource.api.tangemTech.TangemTechApiV2
|
import com.tangem.datasource.api.tangemTech.TangemTechApiV2
|
||||||
import com.tangem.datasource.api.tangemTech.TangemTechServiceApi
|
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.datasource.utils.addLoggers
|
||||||
import com.tangem.lib.auth.AppVersionProvider
|
import com.tangem.lib.auth.AppVersionProvider
|
||||||
import com.tangem.lib.auth.ExpressAuthProvider
|
import com.tangem.lib.auth.ExpressAuthProvider
|
||||||
|
import com.tangem.lib.auth.StakeKitAuthProvider
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
import dagger.hilt.InstallIn
|
import dagger.hilt.InstallIn
|
||||||
|
|
@ -56,6 +58,27 @@ class NetworkModule {
|
||||||
.create(TangemExpressApi::class.java)
|
.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
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
fun provideTangemTechApi(
|
fun provideTangemTechApi(
|
||||||
|
|
@ -137,6 +160,7 @@ class NetworkModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
private companion object {
|
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 PROD_EXPRESS_BASE_URL = "https://express.tangem.com/v1/"
|
||||||
const val DEV_EXPRESS_BASE_URL = "[REDACTED_ENV_URL]"
|
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 PROD_V2_TANGEM_TECH_BASE_URL = "https://api.tangem-tech.com/v2/"
|
||||||
|
|
||||||
const val TANGEM_TECH_SERVICE_TIMEOUT_SECONDS = 5L
|
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3,6 +3,7 @@ package com.tangem.datasource.utils
|
||||||
import com.tangem.datasource.api.common.AuthProvider
|
import com.tangem.datasource.api.common.AuthProvider
|
||||||
import com.tangem.lib.auth.AppVersionProvider
|
import com.tangem.lib.auth.AppVersionProvider
|
||||||
import com.tangem.lib.auth.ExpressAuthProvider
|
import com.tangem.lib.auth.ExpressAuthProvider
|
||||||
|
import com.tangem.lib.auth.StakeKitAuthProvider
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Presentation of request header
|
* Presentation of request header
|
||||||
|
|
@ -31,4 +32,8 @@ sealed class RequestHeader(vararg pairs: Pair<String, () -> String>) {
|
||||||
"version" to { appVersionProvider.getAppVersion() },
|
"version" to { appVersionProvider.getAppVersion() },
|
||||||
"platform" to { "android" },
|
"platform" to { "android" },
|
||||||
)
|
)
|
||||||
|
|
||||||
|
class StakeKit(stakeKitAuthProvider: StakeKitAuthProvider) : RequestHeader(
|
||||||
|
"X-API-KEY" to { stakeKitAuthProvider.getApiKey() },
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
package com.tangem.lib.auth
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides auth for tangemTech API
|
|
||||||
*/
|
|
||||||
interface AuthBearerProvider {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns api-key
|
|
||||||
*/
|
|
||||||
fun getApiKey(): String
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package com.tangem.lib.auth
|
||||||
|
|
||||||
|
interface StakeKitAuthProvider {
|
||||||
|
|
||||||
|
fun getApiKey(): String
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue