Updated on 2026-08-14

This commit is contained in:
Tangem 2024-06-24 10:50:03 +01:00
commit bc84d8f5f8
579 changed files with 13604 additions and 3422 deletions

View file

@ -25,6 +25,7 @@ dependencies {
implementation(projects.domain.wallets.models)
implementation(projects.domain.balanceHiding.models)
implementation(projects.domain.txhistory.models)
implementation(projects.domain.staking) // TODO staking create staking models module
/** Tangem libraries */
implementation(deps.tangem.blockchain)

View file

@ -2,12 +2,40 @@ package com.tangem.datasource.api.common.adapter
import com.squareup.moshi.*
import com.squareup.moshi.adapters.EnumJsonAdapter
import com.tangem.datasource.api.stakekit.models.response.model.*
import com.tangem.datasource.api.stakekit.models.response.model.action.StakingActionStatusDTO
import com.tangem.datasource.api.stakekit.models.response.model.action.StakingActionTypeDTO
import com.tangem.datasource.api.stakekit.models.response.model.transaction.StakingTransactionStatusDTO
import com.tangem.datasource.api.stakekit.models.response.model.transaction.StakingTransactionTypeDTO
/**
* 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)
@Suppress("UNCHECKED_CAST")
fun <T : Enum<T>> create(enumType: Class<out Enum<*>>, defaultValue: Enum<*>): JsonAdapter<out Enum<*>> {
return EnumJsonAdapter.create(enumType as Class<T>).withUnknownFallback(defaultValue as T)
}
}
fun Moshi.Builder.addStakeKitEnumFallbackAdapters(): Moshi.Builder {
val map = mapOf(
NetworkTypeDTO::class.java to NetworkTypeDTO.UNKNOWN,
StakingActionTypeDTO::class.java to StakingActionTypeDTO.UNKNOWN,
YieldDTO.RewardTypeDTO::class.java to YieldDTO.RewardTypeDTO.UNKNOWN,
YieldBalanceWrapperDTO.BalanceDTO.BalanceType::class.java to
YieldBalanceWrapperDTO.BalanceDTO.BalanceType.UNKNOWN,
StakingTransactionTypeDTO::class.java to StakingTransactionTypeDTO.UNKNOWN,
StakingTransactionStatusDTO::class.java to StakingTransactionStatusDTO.UNKNOWN,
StakingActionStatusDTO::class.java to StakingActionStatusDTO.UNKNOWN,
)
return apply {
map.forEach { entry ->
val enumClass = entry.key
val unknownValue = entry.value
add(enumClass, UnknownEnumMoshiAdapter.create(enumClass, unknownValue))
}
}
}

View file

@ -1,48 +1,60 @@
package com.tangem.datasource.api.stakekit
import com.tangem.datasource.api.common.response.ApiResponse
import com.tangem.datasource.api.stakekit.models.request.YieldBalanceRequestBody
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.request.*
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.Yield
import com.tangem.datasource.api.stakekit.models.response.model.YieldBalanceWrapper
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.Path
import retrofit2.http.Query
import com.tangem.datasource.api.stakekit.models.response.EnterActionResponse
import com.tangem.datasource.api.stakekit.models.response.model.transaction.StakingTransactionDTO
import com.tangem.datasource.api.stakekit.models.response.model.TokenWithYieldDTO
import com.tangem.datasource.api.stakekit.models.response.model.YieldDTO
import com.tangem.datasource.api.stakekit.models.response.model.YieldBalanceWrapperDTO
import retrofit2.http.*
@Suppress("LongParameterList")
interface StakeKitApi {
@GET("yields/enabled")
suspend fun getMultipleYields(
@Query("ledgerWalletAPICompatible") ledgerWalletAPICompatible: Boolean,
@Query("type") type: YieldType,
@Query("revenueOption") revenueOption: RevenueOption,
@Query("page") page: Int,
@Query("network") network: String,
@Query("limit") limit: Int,
@Query("ledgerWalletAPICompatible") ledgerWalletAPICompatible: Boolean? = null,
@Query("type") type: YieldType? = null,
@Query("revenueOption") revenueOption: RevenueOption? = null,
@Query("page") page: Int? = null,
@Query("network") network: String? = null,
@Query("limit") limit: Int? = null,
): ApiResponse<EnabledYieldsResponse>
@GET("yields/{integrationId}")
suspend fun getSingleYield(
@Path("integrationId") integrationId: String,
@Query("ledgerWalletAPICompatible") ledgerWalletAPICompatible: Boolean = false,
): ApiResponse<Yield>
): ApiResponse<YieldDTO>
@GET("yields/balances")
suspend fun getMultipleYieldBalances(
@Body body: List<YieldBalanceRequestBody>,
): ApiResponse<List<YieldBalanceWrapper>>
): ApiResponse<List<YieldBalanceWrapperDTO>>
@GET("yields/{integrationId}/balances")
suspend fun getSingleYieldBalance(
@Path("integrationId") integrationId: String,
@Body body: YieldBalanceRequestBody,
): ApiResponse<YieldBalanceWrapper>
): ApiResponse<YieldBalanceWrapperDTO>
@GET("tokens")
suspend fun getTokens(): ApiResponse<List<TokenWithYield>>
suspend fun getTokens(): ApiResponse<List<TokenWithYieldDTO>>
@POST("actions/enter")
suspend fun createEnterAction(@Body body: EnterActionRequestBody): ApiResponse<EnterActionResponse>
@PATCH("transactions/{transactionId}")
suspend fun constructTransaction(
@Path("transactionId") transactionId: String,
@Body body: ConstructTransactionRequestBody,
): ApiResponse<StakingTransactionDTO>
@POST("transactions/{transactionId}/submit_hash")
suspend fun submitTransactionHash(
@Path("transactionId") transactionId: String,
@Body body: SubmitTransactionHashRequestBody,
): ApiResponse<Unit>
}

View file

@ -0,0 +1,39 @@
package com.tangem.datasource.api.stakekit.models.request
import com.squareup.moshi.Json
data class Address(
@Json(name = "address")
val address: String,
@Json(name = "additionalAddresses")
val additionalAddresses: AdditionalAddresses? = null,
@Json(name = "explorerUrl")
val explorerUrl: String? = null,
) {
data class AdditionalAddresses(
// cosmos-specific
@Json(name = "cosmosPubKey")
val cosmosPubKey: String? = null,
// binance-specific
@Json(name = "binanceBeaconAddress")
val binanceBeaconAddress: String? = null,
// solana-specific
@Json(name = "stakeAccounts")
val stakeAccounts: List<String>? = null,
@Json(name = "lidoStakeAccounts")
val lidoStakeAccounts: List<String>? = null,
// tezos-specific
@Json(name = "tezosPubKey")
val tezosPubKey: String? = null,
// avalanche-specific
@Json(name = "cAddressBech")
val cAddressBech: String? = null,
@Json(name = "pAddressBech")
val pAddressBech: String? = null,
)
}

View file

@ -0,0 +1,24 @@
package com.tangem.datasource.api.stakekit.models.request
import com.squareup.moshi.Json
import java.math.BigDecimal
data class ConstructTransactionRequestBody(
@Json(name = "gasArgs")
val gasArgs: GasArgs? = null,
@Json(name = "ledgerWalletAPICompatible")
val ledgerWalletAPICompatible: Boolean? = null,
) {
data class GasArgs(
// cosmos-specific
@Json(name = "gasPrice")
val gasPrice: BigDecimal? = null,
// EVM eip 1559 specific
@Json(name = "type")
val type: Int? = null,
@Json(name = "maxFeePerGas")
val maxFeePerGas: BigDecimal? = null,
@Json(name = "maxPriorityFeePerGas")
val maxPriorityFeePerGas: BigDecimal? = null,
)
}

View file

@ -0,0 +1,47 @@
package com.tangem.datasource.api.stakekit.models.request
import com.squareup.moshi.Json
import com.tangem.datasource.api.stakekit.models.response.model.TokenDTO
import com.tangem.datasource.api.stakekit.models.response.model.YieldBalanceWrapperDTO
data class EnterActionRequestBody(
@Json(name = "integrationId")
val integrationId: String,
@Json(name = "addresses")
val addresses: Address,
@Json(name = "args")
val args: EnterActionRequestBodyArgs,
@Json(name = "referralCode")
val referralCode: String? = null,
) {
data class EnterActionRequestBodyArgs(
@Json(name = "amount")
val amount: String,
@Json(name = "validatorAddress")
val validatorAddress: String? = null,
@Json(name = "validatorAddresses")
val validatorAddresses: List<String>? = null,
@Json(name = "providerId")
val providerId: String? = null,
@Json(name = "duration")
val duration: String? = null,
@Json(name = "nfts")
val nfts: List<YieldBalanceWrapperDTO.BalanceDTO.PendingAction.PendingActionArgs.Nft>? = null,
@Json(name = "ledgerWalletAPICompatible")
val ledgerWalletAPICompatible: Boolean? = null,
@Json(name = "tronResource")
val tronResource: String? = null,
@Json(name = "signatureVerification")
val signatureVerification: SignatureVerification? = null,
@Json(name = "inputToken")
val inputToken: TokenDTO? = null,
)
data class SignatureVerification(
@Json(name = "message")
val message: String,
@Json(name = "signed")
val signed: String,
)
}

View file

@ -0,0 +1,8 @@
package com.tangem.datasource.api.stakekit.models.request
import com.squareup.moshi.Json
data class SubmitTransactionHashRequestBody(
@Json(name = "hash")
val hash: String,
)

View file

@ -8,23 +8,6 @@ data class YieldBalanceRequestBody(
@Json(name = "integrationId") val integrationId: String? = null,
) {
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 YieldBalanceRequestArgs(
@Json(name = "validatorAddresses") val validatorAddresses: List<String>,
)

View file

@ -2,12 +2,12 @@ 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
import com.tangem.datasource.api.stakekit.models.response.model.YieldDTO
@JsonClass(generateAdapter = true)
data class EnabledYieldsResponse(
@Json(name = "data")
val data: List<Yield>,
val data: List<YieldDTO>,
@Json(name = "hasNextPage")
val hasNextPage: Boolean,
@Json(name = "limit")

View file

@ -0,0 +1,33 @@
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.action.StakingActionStatusDTO
import com.tangem.datasource.api.stakekit.models.response.model.action.StakingActionTypeDTO
import com.tangem.datasource.api.stakekit.models.response.model.transaction.StakingTransactionDTO
import org.joda.time.DateTime
import java.math.BigDecimal
@JsonClass(generateAdapter = true)
data class EnterActionResponse(
@Json(name = "id")
val id: String,
@Json(name = "integrationId")
val integrationId: String,
@Json(name = "status")
val status: StakingActionStatusDTO,
@Json(name = "type")
val type: StakingActionTypeDTO,
@Json(name = "currentStepIndex")
val currentStepIndex: Int,
@Json(name = "amount")
val amount: BigDecimal,
@Json(name = "validatorAddress")
val validatorAddress: String?,
@Json(name = "validatorAddresses")
val validatorAddresses: List<String>?,
@Json(name = "transactions")
val transactions: List<StakingTransactionDTO>?,
@Json(name = "createdAt")
val createdAt: DateTime,
)

View file

@ -4,13 +4,13 @@ import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class AddressArgument(
data class AddressArgumentDTO(
@Json(name = "required")
val required: Boolean,
@Json(name = "network")
val network: String? = null,
@Json(name = "minimum")
val minimum: Int? = null,
val minimum: Double? = null,
@Json(name = "maximum")
val maximum: Int? = null,
val maximum: Double? = null,
)

View file

@ -0,0 +1,205 @@
package com.tangem.datasource.api.stakekit.models.response.model
import com.squareup.moshi.Json
enum class NetworkTypeDTO {
@Json(name = "avalanche-c")
AVALANCHE_C,
@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,
}

View file

@ -1,218 +0,0 @@
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-c")
AVALANCHE_C,
@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,
}
}

View file

@ -0,0 +1,24 @@
package com.tangem.datasource.api.stakekit.models.response.model
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class TokenDTO(
@Json(name = "name")
val name: String,
@Json(name = "network")
val network: NetworkTypeDTO,
@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?,
)

View file

@ -4,7 +4,7 @@ import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class TokenWithYield(
@Json(name = "token") val token: Token,
data class TokenWithYieldDTO(
@Json(name = "token") val token: TokenDTO,
@Json(name = "availableYields") val availableYieldIds: List<String>,
)

View file

@ -2,19 +2,20 @@ package com.tangem.datasource.api.stakekit.models.response.model
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import com.tangem.datasource.api.stakekit.models.response.model.action.StakingActionTypeDTO
import org.joda.time.DateTime
import java.math.BigDecimal
@JsonClass(generateAdapter = true)
data class YieldBalanceWrapper(
data class YieldBalanceWrapperDTO(
@Json(name = "balances")
val balances: List<Balance>,
val balances: List<BalanceDTO>,
@Json(name = "integrationId")
val integrationId: String?,
) {
@JsonClass(generateAdapter = true)
data class Balance(
data class BalanceDTO(
@Json(name = "groupId")
val groupId: String,
@Json(name = "type")
@ -28,7 +29,7 @@ data class YieldBalanceWrapper(
@Json(name = "pendingActions")
val pendingActions: List<PendingAction>,
@Json(name = "token")
val token: Token,
val tokenDTO: TokenDTO,
@Json(name = "validatorAddress")
val validatorAddress: String?,
@Json(name = "validatorAddresses")
@ -61,12 +62,14 @@ data class YieldBalanceWrapper(
@Json(name = "unlocking")
UNLOCKING,
UNKNOWN,
}
@JsonClass(generateAdapter = true)
data class PendingAction(
@Json(name = "type")
val type: StakingActionType,
val type: StakingActionTypeDTO,
@Json(name = "passthrough")
val passthrough: String,
@Json(name = "args")

View file

@ -1,138 +0,0 @@
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,
)
}
}

View file

@ -5,33 +5,33 @@ import com.squareup.moshi.JsonClass
import java.math.BigDecimal
@JsonClass(generateAdapter = true)
data class Yield(
data class YieldDTO(
@Json(name = "id")
val id: String,
@Json(name = "token")
val token: Token,
val token: TokenDTO,
@Json(name = "tokens")
val tokens: List<Token>,
val tokens: List<TokenDTO>,
@Json(name = "args")
val args: Args,
val args: ArgsDTO,
@Json(name = "status")
val status: Status,
val status: StatusDTO,
@Json(name = "apy")
val apy: BigDecimal,
@Json(name = "rewardRate")
val rewardRate: Double,
@Json(name = "rewardType")
val rewardType: RewardType,
val rewardType: RewardTypeDTO,
@Json(name = "metadata")
val metadata: Metadata,
val metadata: MetadataDTO,
@Json(name = "validators")
val validators: List<Validator>,
val validators: List<ValidatorDTO>,
@Json(name = "isAvailable")
val isAvailable: Boolean,
) {
@JsonClass(generateAdapter = true)
data class Status(
data class StatusDTO(
@Json(name = "enter")
val enter: Boolean,
@Json(name = "exit")
@ -39,7 +39,7 @@ data class Yield(
)
@JsonClass(generateAdapter = true)
data class Args(
data class ArgsDTO(
@Json(name = "enter")
val enter: Enter,
@Json(name = "exit")
@ -50,20 +50,20 @@ data class Yield(
@Json(name = "addresses")
val addresses: Addresses,
@Json(name = "args")
val args: Map<String, AddressArgument>,
val args: Map<String, AddressArgumentDTO>,
) {
@JsonClass(generateAdapter = true)
data class Addresses(
@Json(name = "address")
val address: AddressArgument,
val address: AddressArgumentDTO,
@Json(name = "additionalAddresses")
val additionalAddresses: Map<String, AddressArgument>? = null,
val additionalAddresses: Map<String, AddressArgumentDTO>? = null,
)
}
}
@JsonClass(generateAdapter = true)
data class Validator(
data class ValidatorDTO(
@Json(name = "address")
val address: String,
@Json(name = "status")
@ -75,7 +75,7 @@ data class Yield(
@Json(name = "website")
val website: String?,
@Json(name = "apr")
val apr: Double?,
val apr: BigDecimal?,
@Json(name = "commission")
val commission: Double?,
@Json(name = "stakedBalance")
@ -87,7 +87,7 @@ data class Yield(
)
@JsonClass(generateAdapter = true)
data class Metadata(
data class MetadataDTO(
@Json(name = "name")
val name: String,
@Json(name = "logoURI")
@ -97,19 +97,19 @@ data class Yield(
@Json(name = "documentation")
val documentation: String?,
@Json(name = "gasFeeToken")
val gasFeeToken: Token,
val gasFeeTokenDTO: TokenDTO,
@Json(name = "token")
val token: Token,
val tokenDTO: TokenDTO,
@Json(name = "tokens")
val tokens: List<Token>,
val tokensDTO: List<TokenDTO>,
@Json(name = "type")
val type: String,
@Json(name = "rewardSchedule")
val rewardSchedule: String,
@Json(name = "cooldownPeriod")
val cooldownPeriod: Period,
val cooldownPeriod: PeriodDTO,
@Json(name = "warmupPeriod")
val warmupPeriod: Period,
val warmupPeriod: PeriodDTO,
@Json(name = "rewardClaiming")
val rewardClaiming: String,
@Json(name = "defaultValidator")
@ -119,28 +119,30 @@ data class Yield(
@Json(name = "supportsMultipleValidators")
val supportsMultipleValidators: Boolean,
@Json(name = "revshare")
val revshare: Enabled,
val revshare: EnabledDTO,
@Json(name = "fee")
val fee: Enabled,
val fee: EnabledDTO,
) {
@JsonClass(generateAdapter = true)
data class Period(
data class PeriodDTO(
@Json(name = "days")
val days: Int,
)
@JsonClass(generateAdapter = true)
data class Enabled(
data class EnabledDTO(
@Json(name = "enabled")
val enabled: Boolean,
)
}
enum class RewardType {
enum class RewardTypeDTO {
@Json(name = "apy")
APY, // auto
APY, // compound rate
@Json(name = "apr")
APR, // manual
APR, // simple rate,
UNKNOWN,
}
}

View file

@ -0,0 +1,25 @@
package com.tangem.datasource.api.stakekit.models.response.model.action
import com.squareup.moshi.Json
enum class StakingActionStatusDTO {
@Json(name = "CANCELED")
CANCELED,
@Json(name = "CREATED")
CREATED,
@Json(name = "WAITING_FOR_NEXT")
WAITING_FOR_NEXT,
@Json(name = "PROCESSING")
PROCESSING,
@Json(name = "FAILED")
FAILED,
@Json(name = "SUCCESS")
SUCCESS,
UNKNOWN,
}

View file

@ -1,8 +1,8 @@
package com.tangem.datasource.api.stakekit.models.response.model
package com.tangem.datasource.api.stakekit.models.response.model.action
import com.squareup.moshi.Json
enum class StakingActionType {
enum class StakingActionTypeDTO {
@Json(name = "STAKE")
STAKE,
@ -47,4 +47,6 @@ enum class StakingActionType {
@Json(name = "MIGRATE")
MIGRATE,
UNKNOWN,
}

View file

@ -0,0 +1,16 @@
package com.tangem.datasource.api.stakekit.models.response.model.transaction
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import com.tangem.datasource.api.stakekit.models.response.model.TokenDTO
import java.math.BigDecimal
@JsonClass(generateAdapter = true)
data class StakingGasEstimateDTO(
@Json(name = "amount")
val amount: BigDecimal,
@Json(name = "token")
val token: TokenDTO,
@Json(name = "gasLimit")
val gasLimit: BigDecimal,
)

View file

@ -0,0 +1,37 @@
package com.tangem.datasource.api.stakekit.models.response.model.transaction
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import com.tangem.datasource.api.stakekit.models.response.model.NetworkTypeDTO
@JsonClass(generateAdapter = true)
data class StakingTransactionDTO(
@Json(name = "id")
val id: String,
@Json(name = "network")
val network: NetworkTypeDTO,
@Json(name = "status")
val status: StakingTransactionStatusDTO,
@Json(name = "type")
val type: StakingTransactionTypeDTO,
@Json(name = "hash")
val hash: String?,
@Json(name = "signedTransaction")
val signedTransaction: String?,
@Json(name = "unsignedTransaction")
val unsignedTransaction: String?,
@Json(name = "stepIndex")
val stepIndex: Int,
@Json(name = "error")
val error: String?,
@Json(name = "gasEstimate")
val gasEstimate: StakingGasEstimateDTO?,
@Json(name = "stakeId")
val stakeId: String?,
@Json(name = "explorerUrl")
val explorerUrl: String?,
@Json(name = "ledgerHwAppId")
val ledgerHwAppId: String?,
@Json(name = "isMessage")
val isMessage: Boolean,
)

View file

@ -0,0 +1,37 @@
package com.tangem.datasource.api.stakekit.models.response.model.transaction
import com.squareup.moshi.Json
enum class StakingTransactionStatusDTO {
@Json(name = "NOT_FOUND")
NOT_FOUND,
@Json(name = "CREATED")
CREATED,
@Json(name = "BLOCKED")
BLOCKED,
@Json(name = "WAITING_FOR_SIGNATURE")
WAITING_FOR_SIGNATURE,
@Json(name = "SIGNED")
SIGNED,
@Json(name = "BROADCASTED")
BROADCASTED,
@Json(name = "PENDING")
PENDING,
@Json(name = "CONFIRMED")
CONFIRMED,
@Json(name = "FAILED")
FAILED,
@Json(name = "SKIPPED")
SKIPPED,
UNKNOWN,
}

View file

@ -0,0 +1,124 @@
package com.tangem.datasource.api.stakekit.models.response.model.transaction
import com.squareup.moshi.Json
enum class StakingTransactionTypeDTO {
@Json(name = "SWAP")
SWAP,
@Json(name = "DEPOSIT")
DEPOSIT,
@Json(name = "APPROVAL")
APPROVAL,
@Json(name = "STAKE")
STAKE,
@Json(name = "CLAIM_UNSTAKED")
CLAIM_UNSTAKED,
@Json(name = "CLAIM_REWARDS")
CLAIM_REWARDS,
@Json(name = "RESTAKE_REWARDS")
RESTAKE_REWARDS,
@Json(name = "UNSTAKE")
UNSTAKE,
@Json(name = "SPLIT")
SPLIT,
@Json(name = "MERGE")
MERGE,
@Json(name = "LOCK")
LOCK,
@Json(name = "UNLOCK")
UNLOCK,
@Json(name = "SUPPLY")
SUPPLY,
@Json(name = "BRIDGE")
BRIDGE,
@Json(name = "VOTE")
VOTE,
@Json(name = "REVOKE")
REVOKE,
@Json(name = "RESTAKE")
RESTAKE,
@Json(name = "REBOND")
REBOND,
@Json(name = "WITHDRAW")
WITHDRAW,
@Json(name = "CREATE_ACCOUNT")
CREATE_ACCOUNT,
@Json(name = "REVEAL")
REVEAL,
@Json(name = "MIGRATE")
MIGRATE,
@Json(name = "UTXO_P_TO_C_IMPORT")
UTXO_P_TO_C_IMPORT,
@Json(name = "UTXO_C_TO_P_IMPORT")
UTXO_C_TO_P_IMPORT,
@Json(name = "UNFREEZE_LEGACY")
UNFREEZE_LEGACY,
@Json(name = "UNFREEZE_LEGACY_BANDWIDTH")
UNFREEZE_LEGACY_BANDWIDTH,
@Json(name = "UNFREEZE_LEGACY_ENERGY")
UNFREEZE_LEGACY_ENERGY,
@Json(name = "UNFREEZE_BANDWIDTH")
UNFREEZE_BANDWIDTH,
@Json(name = "UNFREEZE_ENERGY")
UNFREEZE_ENERGY,
@Json(name = "FREEZE_BANDWIDTH")
FREEZE_BANDWIDTH,
@Json(name = "FREEZE_ENERGY")
FREEZE_ENERGY,
@Json(name = "UNDELEGATE_BANDWIDTH")
UNDELEGATE_BANDWIDTH,
@Json(name = "UNDELEGATE_ENERGY")
UNDELEGATE_ENERGY,
@Json(name = "P2P_NODE_REQUEST")
P2P_NODE_REQUEST,
@Json(name = "LUGANODES_PROVISION")
LUGANODES_PROVISION,
@Json(name = "LUGANODES_EXIT_REQUEST")
LUGANODES_EXIT_REQUEST,
@Json(name = "INFSTONES_PROVISION")
INFSTONES_PROVISION,
@Json(name = "INFSTONES_EXIT_REQUEST")
INFSTONES_EXIT_REQUEST,
@Json(name = "INFSTONES_CLAIM_REQUEST")
INFSTONES_CLAIM_REQUEST,
UNKNOWN,
}

View file

@ -1,8 +1,8 @@
package com.tangem.datasource.di
import com.tangem.datasource.local.datastore.RuntimeDataStore
import com.tangem.datasource.local.token.DefaultAssetsStore
import com.tangem.datasource.local.token.AssetsStore
import com.tangem.datasource.local.token.DefaultExpressAssetsStore
import com.tangem.datasource.local.token.ExpressAssetsStore
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
@ -11,11 +11,11 @@ import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
internal object AssetsStoreModule {
internal object ExpressAssetsStoreModule {
@Provides
@Singleton
fun provideAssetsStore(): AssetsStore {
return DefaultAssetsStore(dataStore = RuntimeDataStore())
fun provideExpressAssetsStore(): ExpressAssetsStore {
return DefaultExpressAssetsStore(dataStore = RuntimeDataStore())
}
}

View file

@ -4,11 +4,10 @@ import com.squareup.moshi.Moshi
import com.squareup.moshi.adapters.PolymorphicJsonAdapterFactory
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import com.tangem.common.json.MoshiJsonConverter
import com.tangem.datasource.api.common.adapter.*
import com.tangem.datasource.api.common.adapter.BigDecimalAdapter
import com.tangem.datasource.api.common.adapter.DateTimeAdapter
import com.tangem.datasource.api.common.adapter.LocalDateAdapter
import com.tangem.datasource.api.common.adapter.UnknownEnumMoshiAdapter
import com.tangem.datasource.api.stakekit.models.response.model.Token
import com.tangem.datasource.config.models.ProviderModel
import dagger.Module
import dagger.Provides
@ -35,10 +34,7 @@ class MoshiModule {
.add(LocalDateAdapter())
.add(DateTimeAdapter())
.add(KotlinJsonAdapterFactory())
.add(
Token.NetworkType::class.java,
UnknownEnumMoshiAdapter.create(Token.NetworkType::class.java, Token.NetworkType.UNKNOWN),
)
.addStakeKitEnumFallbackAdapters()
.build()
}

View file

@ -0,0 +1,21 @@
package com.tangem.datasource.di
import com.tangem.datasource.local.datastore.RuntimeDataStore
import com.tangem.datasource.local.token.DefaultStakingYieldsStore
import com.tangem.datasource.local.token.StakingYieldsStore
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
internal object StakingTokensStoreModule {
@Provides
@Singleton
fun provideStakingTokensStore(): StakingYieldsStore {
return DefaultStakingYieldsStore(dataStore = RuntimeDataStore())
}
}

View file

@ -94,6 +94,20 @@ object PreferencesKeys {
val IS_WALLET_NAMES_MIGRATION_DONE_KEY by lazy { booleanPreferencesKey(name = "isWalletNamesMigrationDone") }
fun getStart2CoinTOSAcceptedKey(region: String?) = booleanPreferencesKey(name = "start2Coin_tos_accepted_$region")
// region Permission
fun getShouldShowPermission(permission: String) = booleanPreferencesKey("shouldShowPushPermission_$permission")
fun getShouldShowInitialPermissionScreen(permission: String) =
booleanPreferencesKey("shouldShowInitialPushPermissionScreen_$permission")
fun getIsFirstTimeAskingPermission(permission: String) =
booleanPreferencesKey("shouldAskInitialPushPermission_$permission")
fun getPermissionLaunchCount(permission: String) = intPreferencesKey("pushPermissionLaunchCount_$permission")
fun getPermissionDaysCount(permission: String) = longPreferencesKey("pushPermissionDaysCount_$permission")
// endregion
}
/** Preferences keys set that should be migrated from "PreferencesDataSource" to a new DataStore<Preferences> */

View file

@ -4,9 +4,9 @@ import com.tangem.datasource.api.express.models.response.Asset
import com.tangem.datasource.local.datastore.core.StringKeyDataStore
import com.tangem.domain.wallets.models.UserWalletId
internal class DefaultAssetsStore(
internal class DefaultExpressAssetsStore(
private val dataStore: StringKeyDataStore<List<Asset>>,
) : AssetsStore {
) : ExpressAssetsStore {
override suspend fun getSyncOrNull(userWalletId: UserWalletId): List<Asset>? {
return dataStore.getSyncOrNull(userWalletId.stringValue)

View file

@ -0,0 +1,21 @@
package com.tangem.datasource.local.token
import com.tangem.datasource.local.datastore.core.StringKeyDataStore
import com.tangem.domain.staking.model.StakingTokenWithYield
internal class DefaultStakingTokensStore(
private val dataStore: StringKeyDataStore<List<StakingTokenWithYield>>,
) : StakingTokensStore {
override suspend fun getSyncOrNull(): List<StakingTokenWithYield>? {
return dataStore.getSyncOrNull(STAKING_TOKENS_KEY)
}
override suspend fun store(items: List<StakingTokenWithYield>) {
dataStore.store(STAKING_TOKENS_KEY, items)
}
companion object {
private const val STAKING_TOKENS_KEY = "STAKING_TOKENS_KEY"
}
}

View file

@ -0,0 +1,21 @@
package com.tangem.datasource.local.token
import com.tangem.datasource.api.stakekit.models.response.model.YieldDTO
import com.tangem.datasource.local.datastore.core.StringKeyDataStore
internal class DefaultStakingYieldsStore(
private val dataStore: StringKeyDataStore<List<YieldDTO>>,
) : StakingYieldsStore {
override suspend fun getSyncOrNull(): List<YieldDTO>? {
return dataStore.getSyncOrNull(STAKING_YIELDS_KEY)
}
override suspend fun store(items: List<YieldDTO>) {
dataStore.store(STAKING_YIELDS_KEY, items)
}
companion object {
private const val STAKING_YIELDS_KEY = "STAKING_YIELDS_KEY"
}
}

View file

@ -3,7 +3,7 @@ package com.tangem.datasource.local.token
import com.tangem.datasource.api.express.models.response.Asset
import com.tangem.domain.wallets.models.UserWalletId
interface AssetsStore {
interface ExpressAssetsStore {
suspend fun getSyncOrNull(userWalletId: UserWalletId): List<Asset>?

View file

@ -0,0 +1,10 @@
package com.tangem.datasource.local.token
import com.tangem.domain.staking.model.StakingTokenWithYield
interface StakingTokensStore {
suspend fun getSyncOrNull(): List<StakingTokenWithYield>?
suspend fun store(items: List<StakingTokenWithYield>)
}

View file

@ -0,0 +1,10 @@
package com.tangem.datasource.local.token
import com.tangem.datasource.api.stakekit.models.response.model.YieldDTO
interface StakingYieldsStore {
suspend fun getSyncOrNull(): List<YieldDTO>?
suspend fun store(items: List<YieldDTO>)
}

View file

@ -35,5 +35,6 @@ sealed class RequestHeader(vararg pairs: Pair<String, () -> String>) {
class StakeKit(stakeKitAuthProvider: StakeKitAuthProvider) : RequestHeader(
"X-API-KEY" to { stakeKitAuthProvider.getApiKey() },
"accept" to { "application/json" },
)
}