Updated on 2026-08-14
This commit is contained in:
parent
2722983c42
commit
b8fc2d4f76
47 changed files with 1677 additions and 0 deletions
|
|
@ -24,6 +24,7 @@ sealed class ApiConfig {
|
|||
Express,
|
||||
TangemTech,
|
||||
StakeKit,
|
||||
P2PEthPool,
|
||||
TangemPay,
|
||||
BlockAid,
|
||||
YieldSupply,
|
||||
|
|
@ -35,6 +36,7 @@ sealed class ApiConfig {
|
|||
is Express -> ID.Express
|
||||
is TangemTech -> ID.TangemTech
|
||||
is StakeKit -> ID.StakeKit
|
||||
is P2PEthPool -> ID.P2PEthPool
|
||||
is TangemPay -> ID.TangemPay
|
||||
is BlockAid -> ID.BlockAid
|
||||
is YieldSupply -> ID.YieldSupply
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
package com.tangem.datasource.api.common.config
|
||||
|
||||
import com.tangem.datasource.BuildConfig
|
||||
import com.tangem.lib.auth.P2PEthPoolAuthProvider
|
||||
import com.tangem.utils.ProviderSuspend
|
||||
|
||||
/**
|
||||
* P2P.org Ethereum Pooled Staking API configuration
|
||||
*/
|
||||
internal class P2PEthPool(
|
||||
private val p2pAuthProvider: P2PEthPoolAuthProvider,
|
||||
) : ApiConfig() {
|
||||
|
||||
override val defaultEnvironment: ApiEnvironment = getInitialEnvironment()
|
||||
|
||||
override val environmentConfigs: List<ApiEnvironmentConfig> = listOf(
|
||||
createProdEnvironment(),
|
||||
createTestEnvironment(),
|
||||
createMockEnvironment(),
|
||||
)
|
||||
|
||||
private fun getInitialEnvironment(): ApiEnvironment {
|
||||
return when (BuildConfig.BUILD_TYPE) {
|
||||
MOCKED_BUILD_TYPE -> ApiEnvironment.MOCK
|
||||
DEBUG_BUILD_TYPE,
|
||||
INTERNAL_BUILD_TYPE,
|
||||
EXTERNAL_BUILD_TYPE,
|
||||
RELEASE_BUILD_TYPE,
|
||||
-> ApiEnvironment.PROD
|
||||
else -> error("Unknown build type [${BuildConfig.BUILD_TYPE}]")
|
||||
}
|
||||
}
|
||||
|
||||
private fun createProdEnvironment(): ApiEnvironmentConfig {
|
||||
return ApiEnvironmentConfig(
|
||||
environment = ApiEnvironment.PROD,
|
||||
baseUrl = "https://api.p2p.org/",
|
||||
headers = createHeaders(),
|
||||
)
|
||||
}
|
||||
|
||||
private fun createTestEnvironment(): ApiEnvironmentConfig {
|
||||
return ApiEnvironmentConfig(
|
||||
environment = ApiEnvironment.DEV,
|
||||
baseUrl = "https://api-test.p2p.org/",
|
||||
headers = createHeaders(),
|
||||
)
|
||||
}
|
||||
|
||||
private fun createMockEnvironment(): ApiEnvironmentConfig {
|
||||
return ApiEnvironmentConfig(
|
||||
environment = ApiEnvironment.MOCK,
|
||||
baseUrl = "[REDACTED_ENV_URL]",
|
||||
headers = createHeaders(),
|
||||
)
|
||||
}
|
||||
|
||||
private fun createHeaders() = buildMap {
|
||||
put(key = "Authorization", value = ProviderSuspend { "Bearer ${p2pAuthProvider.getApiKey()}" })
|
||||
put(key = "accept", value = ProviderSuspend { "application/json" })
|
||||
put(key = "Content-Type", value = ProviderSuspend { "application/json" })
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
package com.tangem.datasource.api.ethpool
|
||||
|
||||
import com.tangem.datasource.api.common.response.ApiResponse
|
||||
import com.tangem.datasource.api.ethpool.models.request.P2PEthPoolBroadcastRequest
|
||||
import com.tangem.datasource.api.ethpool.models.request.P2PEthPoolDepositRequest
|
||||
import com.tangem.datasource.api.ethpool.models.request.P2PEthPoolUnstakeRequest
|
||||
import com.tangem.datasource.api.ethpool.models.request.P2PEthPoolWithdrawRequest
|
||||
import com.tangem.datasource.api.ethpool.models.response.*
|
||||
import retrofit2.http.*
|
||||
|
||||
/**
|
||||
* P2P.org Ethereum Pooled Staking API client
|
||||
*
|
||||
* Documentation: https://docs.p2p.org/
|
||||
*
|
||||
* Base URL: https://api.p2p.org (prod) / https://api-test.p2p.org (testnet)
|
||||
*/
|
||||
interface P2PEthPoolApi {
|
||||
|
||||
/**
|
||||
* Get list of available vaults
|
||||
*
|
||||
* @param network Ethereum pool network: "mainnet" or "hoodi" (testnet)
|
||||
*/
|
||||
@GET("api/v1/staking/pool/{network}/vaults")
|
||||
suspend fun getVaults(
|
||||
@Path("network") network: String = "mainnet",
|
||||
): ApiResponse<P2PEthPoolResponse<P2PEthPoolVaultsResponse>>
|
||||
|
||||
/**
|
||||
* Prepare deposit transaction
|
||||
*
|
||||
* Create unsigned transaction for depositing ETH into a vault.
|
||||
*
|
||||
* @param network Ethereum pool network: "mainnet" or "hoodi"
|
||||
* @param body Deposit parameters (delegator address, vault address, amount)
|
||||
*/
|
||||
@POST("api/v1/staking/pool/{network}/staking/deposit")
|
||||
suspend fun createDepositTransaction(
|
||||
@Path("network") network: String,
|
||||
@Body body: P2PEthPoolDepositRequest,
|
||||
): ApiResponse<P2PEthPoolResponse<P2PEthPoolDepositResponse>>
|
||||
|
||||
/**
|
||||
* Prepare unstake transaction
|
||||
*
|
||||
* Create unsigned transaction to initiate unstaking process.
|
||||
*
|
||||
* @param network Ethereum pool network: "mainnet" or "hoodi"
|
||||
* @param body Unstake parameters (staker public key, stake transaction hash)
|
||||
*/
|
||||
@POST("api/v1/staking/pool/{network}/staking/unstake")
|
||||
suspend fun createUnstakeTransaction(
|
||||
@Path("network") network: String,
|
||||
@Body body: P2PEthPoolUnstakeRequest,
|
||||
): ApiResponse<P2PEthPoolResponse<P2PEthPoolUnstakeResponse>>
|
||||
|
||||
/**
|
||||
* Prepare withdrawal transaction
|
||||
*
|
||||
* Create unsigned transaction to withdraw available funds from exit queue.
|
||||
*
|
||||
* @param network Ethereum pool network: "mainnet" or "hoodi"
|
||||
* @param body Withdrawal parameters (staker address)
|
||||
*/
|
||||
@POST("api/v1/staking/pool/{network}/staking/withdraw")
|
||||
suspend fun createWithdrawTransaction(
|
||||
@Path("network") network: String,
|
||||
@Body body: P2PEthPoolWithdrawRequest,
|
||||
): ApiResponse<P2PEthPoolResponse<P2PEthPoolWithdrawResponse>>
|
||||
|
||||
/**
|
||||
* Broadcast signed transaction
|
||||
*
|
||||
* Submit a signed transaction to the blockchain network.
|
||||
*
|
||||
* @param network Ethereum pool network: "mainnet" or "hoodi"
|
||||
* @param body Signed transaction in hexadecimal format
|
||||
*/
|
||||
@POST("api/v1/staking/pool/{network}/transaction/send")
|
||||
suspend fun broadcastTransaction(
|
||||
@Path("network") network: String,
|
||||
@Body body: P2PEthPoolBroadcastRequest,
|
||||
): ApiResponse<P2PEthPoolResponse<P2PEthPoolBroadcastResponse>>
|
||||
|
||||
/**
|
||||
* Get account summary
|
||||
*
|
||||
* Retrieve staking balance, rewards, and exit queue information for a specific account and vault.
|
||||
*
|
||||
* @param network Ethereum pool network: "mainnet" or "hoodi"
|
||||
* @param delegatorAddress Account address that initiated staking
|
||||
* @param vaultAddress Ethereum address of the vault
|
||||
*/
|
||||
@GET("api/v1/staking/pool/{network}/account/{delegatorAddress}/vault/{vaultAddress}")
|
||||
suspend fun getAccountInfo(
|
||||
@Path("network") network: String,
|
||||
@Path("delegatorAddress") delegatorAddress: String,
|
||||
@Path("vaultAddress") vaultAddress: String,
|
||||
): ApiResponse<P2PEthPoolResponse<P2PEthPoolAccountResponse>>
|
||||
|
||||
/**
|
||||
* Get rewards history
|
||||
*
|
||||
* Retrieve historical rewards data for a specific account and vault.
|
||||
*
|
||||
* @param network Ethereum pool network: "mainnet" or "hoodi"
|
||||
* @param delegatorAddress Account address that initiated staking
|
||||
* @param vaultAddress Ethereum address of the vault
|
||||
* @param period Optional period filter (30, 60, or 90 days)
|
||||
*/
|
||||
@GET("api/v1/staking/pool/{network}/account/{delegatorAddress}/vault/{vaultAddress}/rewards")
|
||||
suspend fun getRewards(
|
||||
@Path("network") network: String,
|
||||
@Path("delegatorAddress") delegatorAddress: String,
|
||||
@Path("vaultAddress") vaultAddress: String,
|
||||
@Query("period") period: Int? = null,
|
||||
): ApiResponse<P2PEthPoolResponse<P2PEthPoolRewardsResponse>>
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package com.tangem.datasource.api.ethpool.models.request
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
/**
|
||||
* Request body for broadcasting signed transaction
|
||||
*
|
||||
* Used in: POST /api/v1/staking/pool/{network}/transaction/send
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class P2PEthPoolBroadcastRequest(
|
||||
@Json(name = "signedTransaction")
|
||||
val signedTransaction: String,
|
||||
)
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package com.tangem.datasource.api.ethpool.models.request
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
/**
|
||||
* Request body for creating deposit transaction
|
||||
*
|
||||
* Used in: POST /api/v1/staking/pool/{network}/staking/deposit
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class P2PEthPoolDepositRequest(
|
||||
@Json(name = "delegatorAddress")
|
||||
val delegatorAddress: String,
|
||||
@Json(name = "vaultAddress")
|
||||
val vaultAddress: String,
|
||||
@Json(name = "amount")
|
||||
val amount: Double,
|
||||
)
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package com.tangem.datasource.api.ethpool.models.request
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
/**
|
||||
* Request body for creating unstake transaction
|
||||
*
|
||||
* Used in: POST /api/v1/staking/pool/{network}/staking/unstake
|
||||
*
|
||||
* Note: Documentation seems to contain Bitcoin-related fields (possibly copy-paste error).
|
||||
* Using as-is per specification.
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class P2PEthPoolUnstakeRequest(
|
||||
@Json(name = "stakerPublicKey")
|
||||
val stakerPublicKey: String,
|
||||
@Json(name = "stakeTransactionHash")
|
||||
val stakeTransactionHash: String,
|
||||
)
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package com.tangem.datasource.api.ethpool.models.request
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
/**
|
||||
* Request body for creating withdrawal transaction
|
||||
*
|
||||
* Used in: POST /api/v1/staking/pool/{network}/staking/withdraw
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class P2PEthPoolWithdrawRequest(
|
||||
@Json(name = "stakerAddress")
|
||||
val stakerAddress: String,
|
||||
)
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
package com.tangem.datasource.api.ethpool.models.response
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
* Response for GET /api/v1/staking/pool/{network}/account/{delegatorAddress}/vault/{vaultAddress}
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class P2PEthPoolAccountResponse(
|
||||
@Json(name = "delegatorAddress")
|
||||
val delegatorAddress: String,
|
||||
@Json(name = "vaultAddress")
|
||||
val vaultAddress: String,
|
||||
@Json(name = "stake")
|
||||
val stake: P2PEthPoolStakeDTO,
|
||||
@Json(name = "availableToUnstake")
|
||||
val availableToUnstake: BigDecimal,
|
||||
@Json(name = "availableToWithdraw")
|
||||
val availableToWithdraw: BigDecimal,
|
||||
@Json(name = "exitQueue")
|
||||
val exitQueue: P2PEthPoolExitQueueDTO,
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class P2PEthPoolStakeDTO(
|
||||
@Json(name = "assets")
|
||||
val assets: BigDecimal,
|
||||
@Json(name = "totalEarnedAssets")
|
||||
val totalEarnedAssets: BigDecimal,
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class P2PEthPoolExitQueueDTO(
|
||||
@Json(name = "total")
|
||||
val total: Double,
|
||||
@Json(name = "requests")
|
||||
val requests: List<P2PEthPoolExitRequestDTO>,
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class P2PEthPoolExitRequestDTO(
|
||||
@Json(name = "ticket")
|
||||
val ticket: String,
|
||||
@Json(name = "totalAssets")
|
||||
val totalAssets: Double,
|
||||
@Json(name = "timestamp")
|
||||
val timestamp: Long,
|
||||
@Json(name = "withdrawalTimestamp")
|
||||
val withdrawalTimestamp: Long,
|
||||
@Json(name = "isClaimable")
|
||||
val isClaimable: Boolean,
|
||||
)
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
package com.tangem.datasource.api.ethpool.models.response
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
/**
|
||||
* Response for POST /api/v1/staking/pool/{network}/transaction/send
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class P2PEthPoolBroadcastResponse(
|
||||
@Json(name = "hash")
|
||||
val hash: String,
|
||||
@Json(name = "status")
|
||||
val status: P2PEthPoolTxStatusDTO,
|
||||
@Json(name = "blockNumber")
|
||||
val blockNumber: Int,
|
||||
@Json(name = "transactionIndex")
|
||||
val transactionIndex: Int,
|
||||
@Json(name = "gasUsed")
|
||||
val gasUsed: String,
|
||||
@Json(name = "cumulativeGasUsed")
|
||||
val cumulativeGasUsed: String,
|
||||
@Json(name = "effectiveGasPrice")
|
||||
val effectiveGasPrice: String?,
|
||||
@Json(name = "from")
|
||||
val from: String,
|
||||
@Json(name = "to")
|
||||
val to: String,
|
||||
)
|
||||
|
||||
/**
|
||||
* Transaction status from P2P API
|
||||
*/
|
||||
@JsonClass(generateAdapter = false)
|
||||
enum class P2PEthPoolTxStatusDTO {
|
||||
@Json(name = "success")
|
||||
SUCCESS,
|
||||
|
||||
@Json(name = "failed")
|
||||
FAILED,
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package com.tangem.datasource.api.ethpool.models.response
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import org.joda.time.DateTime
|
||||
|
||||
/**
|
||||
* Response for POST /api/v1/staking/pool/{network}/staking/deposit
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class P2PEthPoolDepositResponse(
|
||||
@Json(name = "amount")
|
||||
val amount: Double,
|
||||
@Json(name = "vaultAddress")
|
||||
val vaultAddress: String,
|
||||
@Json(name = "delegatorAddress")
|
||||
val delegatorAddress: String,
|
||||
@Json(name = "unsignedTransaction")
|
||||
val unsignedTransaction: P2PEthPoolUnsignedTxDTO,
|
||||
@Json(name = "createdAt")
|
||||
val createdAt: DateTime,
|
||||
)
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package com.tangem.datasource.api.ethpool.models.response
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
/**
|
||||
* Error response structure for P2P.org API
|
||||
*
|
||||
* All P2P API endpoints return errors in this format
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class P2PEthPoolErrorResponse(
|
||||
@Json(name = "error")
|
||||
val error: P2PEthPoolErrorDetailsDTO,
|
||||
@Json(name = "result")
|
||||
val result: Any? = null, // null on error
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class P2PEthPoolErrorDetailsDTO(
|
||||
@Json(name = "code")
|
||||
val code: Int, // Error code (e.g., 127106, 101111)
|
||||
@Json(name = "message")
|
||||
val message: String, // Human-readable error message
|
||||
@Json(name = "name")
|
||||
val name: String, // Error name/type
|
||||
@Json(name = "errors")
|
||||
val errors: List<String>? = null, // Optional validation errors array
|
||||
)
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package com.tangem.datasource.api.ethpool.models.response
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
/**
|
||||
* Unified response wrapper for all P2P.org API responses
|
||||
*
|
||||
* All P2P API endpoints return responses in this format:
|
||||
* ```json
|
||||
* {
|
||||
* "error": null | { code, message, name, errors },
|
||||
* "result": { ... } | null
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param T The type of the result data
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class P2PEthPoolResponse<T>(
|
||||
@Json(name = "error")
|
||||
val error: P2PEthPoolErrorDetailsDTO?,
|
||||
@Json(name = "result")
|
||||
val result: T?,
|
||||
)
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package com.tangem.datasource.api.ethpool.models.response
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import org.joda.time.DateTime
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
* Response for GET /api/v1/staking/pool/{network}/account/{delegatorAddress}/vault/{vaultAddress}/rewards
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class P2PEthPoolRewardsResponse(
|
||||
@Json(name = "delegatorAddress")
|
||||
val delegatorAddress: String,
|
||||
@Json(name = "vaultAddress")
|
||||
val vaultAddress: String,
|
||||
@Json(name = "rewards")
|
||||
val rewards: List<P2PEthPoolRewardDTO>,
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class P2PEthPoolRewardDTO(
|
||||
@Json(name = "date")
|
||||
val date: DateTime,
|
||||
@Json(name = "apy")
|
||||
val apy: Double,
|
||||
@Json(name = "balance")
|
||||
val balance: BigDecimal,
|
||||
@Json(name = "rewards")
|
||||
val rewards: BigDecimal,
|
||||
)
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package com.tangem.datasource.api.ethpool.models.response
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
* Unsigned transaction structure
|
||||
*
|
||||
* Used in deposit, withdraw responses
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class P2PEthPoolUnsignedTxDTO(
|
||||
@Json(name = "serializeTx")
|
||||
val serializeTx: String,
|
||||
@Json(name = "to")
|
||||
val to: String,
|
||||
@Json(name = "data")
|
||||
val data: String,
|
||||
@Json(name = "value")
|
||||
val value: String,
|
||||
@Json(name = "nonce")
|
||||
val nonce: Int,
|
||||
@Json(name = "chainId")
|
||||
val chainId: Int,
|
||||
@Json(name = "gasLimit")
|
||||
val gasLimit: BigDecimal,
|
||||
@Json(name = "maxFeePerGas")
|
||||
val maxFeePerGas: BigDecimal,
|
||||
@Json(name = "maxPriorityFeePerGas")
|
||||
val maxPriorityFeePerGas: BigDecimal,
|
||||
)
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package com.tangem.datasource.api.ethpool.models.response
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
/**
|
||||
* Response for POST /api/v1/staking/pool/{network}/staking/unstake
|
||||
*
|
||||
* Note: Contains Bitcoin-related fields (likely documentation error).
|
||||
* Using as-is per specification.
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class P2PEthPoolUnstakeResponse(
|
||||
@Json(name = "stakerPublicKey")
|
||||
val stakerPublicKey: String,
|
||||
@Json(name = "stakeTransactionHash")
|
||||
val stakeTransactionHash: String,
|
||||
@Json(name = "unstakeTransactionHex")
|
||||
val unstakeTransactionHex: String, // unsigned
|
||||
@Json(name = "unstakeFee")
|
||||
val unstakeFee: Double,
|
||||
)
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
package com.tangem.datasource.api.ethpool.models.response
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import org.joda.time.DateTime
|
||||
|
||||
/**
|
||||
* Response for GET /api/v1/staking/pool/{network}/vaults
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class P2PEthPoolVaultsResponse(
|
||||
@Json(name = "network")
|
||||
val network: P2PEthPoolNetworkDTO,
|
||||
@Json(name = "vaults")
|
||||
val vaults: List<P2PEthPoolVaultDTO>,
|
||||
)
|
||||
|
||||
/**
|
||||
* Network identifier in P2P API
|
||||
*/
|
||||
@JsonClass(generateAdapter = false)
|
||||
enum class P2PEthPoolNetworkDTO {
|
||||
@Json(name = "mainnet")
|
||||
MAINNET,
|
||||
|
||||
@Json(name = "hoodi")
|
||||
HOODI,
|
||||
}
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class P2PEthPoolVaultDTO(
|
||||
@Json(name = "vaultAddress")
|
||||
val vaultAddress: String,
|
||||
@Json(name = "displayName")
|
||||
val displayName: String,
|
||||
@Json(name = "apy")
|
||||
val apy: Double,
|
||||
@Json(name = "baseApy")
|
||||
val baseApy: Double,
|
||||
@Json(name = "capacity")
|
||||
val capacity: Double,
|
||||
@Json(name = "totalAssets")
|
||||
val totalAssets: Double,
|
||||
@Json(name = "feePercent")
|
||||
val feePercent: Double,
|
||||
@Json(name = "isPrivate")
|
||||
val isPrivate: Boolean,
|
||||
@Json(name = "isGenesis")
|
||||
val isGenesis: Boolean,
|
||||
@Json(name = "isSmoothingPool")
|
||||
val isSmoothingPool: Boolean,
|
||||
@Json(name = "isErc20")
|
||||
val isErc20: Boolean,
|
||||
@Json(name = "tokenName")
|
||||
val tokenName: String?,
|
||||
@Json(name = "tokenSymbol")
|
||||
val tokenSymbol: String?,
|
||||
@Json(name = "createdAt")
|
||||
val createdAt: DateTime,
|
||||
)
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package com.tangem.datasource.api.ethpool.models.response
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import org.joda.time.DateTime
|
||||
|
||||
/**
|
||||
* Response for POST /api/v1/staking/pool/{network}/staking/withdraw
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class P2PEthPoolWithdrawResponse(
|
||||
@Json(name = "amount")
|
||||
val amount: Double,
|
||||
@Json(name = "vaultAddress")
|
||||
val vaultAddress: String,
|
||||
@Json(name = "delegatorAddress")
|
||||
val delegatorAddress: String,
|
||||
@Json(name = "unsignedTransaction")
|
||||
val unsignedTransaction: P2PEthPoolUnsignedTxDTO,
|
||||
@Json(name = "createdAt")
|
||||
val createdAt: DateTime,
|
||||
@Json(name = "tickets")
|
||||
val tickets: List<String>,
|
||||
)
|
||||
|
|
@ -4,6 +4,7 @@ import com.tangem.datasource.api.common.AuthProvider
|
|||
import com.tangem.datasource.api.common.config.*
|
||||
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage
|
||||
import com.tangem.lib.auth.ExpressAuthProvider
|
||||
import com.tangem.lib.auth.P2PEthPoolAuthProvider
|
||||
import com.tangem.lib.auth.StakeKitAuthProvider
|
||||
import com.tangem.utils.info.AppInfoProvider
|
||||
import com.tangem.utils.version.AppVersionProvider
|
||||
|
|
@ -39,6 +40,12 @@ internal object ApiConfigsModule {
|
|||
return StakeKit(stakeKitAuthProvider)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@IntoSet
|
||||
fun provideP2PEthPoolConfig(p2pAuthProvider: P2PEthPoolAuthProvider): ApiConfig {
|
||||
return P2PEthPool(p2pAuthProvider)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@IntoSet
|
||||
fun provideTangemTechConfig(
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import com.tangem.datasource.api.express.TangemExpressApi
|
|||
import com.tangem.datasource.api.markets.TangemTechMarketsApi
|
||||
import com.tangem.datasource.api.moonpay.MoonPayApi
|
||||
import com.tangem.datasource.api.onramp.OnrampApi
|
||||
import com.tangem.datasource.api.ethpool.P2PEthPoolApi
|
||||
import com.tangem.datasource.api.pay.TangemPayApi
|
||||
import com.tangem.datasource.api.stakekit.StakeKitApi
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
|
|
@ -73,6 +74,15 @@ internal object NetworkModule {
|
|||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideP2PEthPoolApi(retrofitApiBuilder: RetrofitApiBuilder): P2PEthPoolApi {
|
||||
return retrofitApiBuilder.build(
|
||||
apiConfigId = ApiConfig.ID.P2PEthPool,
|
||||
applyTimeoutAnnotations = false,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideOnrampApi(retrofitApiBuilder: RetrofitApiBuilder): OnrampApi {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ data class EnvironmentConfig(
|
|||
val express: ExpressModel? = null,
|
||||
val devExpress: ExpressModel? = null,
|
||||
val stakeKitApiKey: String? = null,
|
||||
// val p2pApiKey: P2PKeys? = null, TODO p2p after release 5.30
|
||||
val blockAidApiKey: String? = null,
|
||||
val tangemApiKey: String? = null,
|
||||
val tangemApiKeyDev: String? = null,
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ internal object EnvironmentConfigConverter : Converter<EnvironmentConfigModel, E
|
|||
express = value.express,
|
||||
devExpress = value.devExpress,
|
||||
stakeKitApiKey = value.stakeKitApiKey,
|
||||
// p2pApiKey = value.p2pApiKey, TODO p2p after release 5.30
|
||||
blockAidApiKey = value.blockaidApiKey,
|
||||
tangemApiKey = value.tangemApiKey,
|
||||
tangemApiKeyDev = value.tangemApiKeyDev,
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ class EnvironmentConfigModel(
|
|||
@Json(name = "hederaArkhiaKey") val hederaArkhiaKey: String?,
|
||||
@Json(name = "polygonScanApiKey") val polygonScanApiKey: String?,
|
||||
@Json(name = "stakeKitApiKey") val stakeKitApiKey: String?,
|
||||
// @Json(name = "p2pApiKey") val p2pApiKey: P2PKeys?, TODO p2p after release 5.30
|
||||
@Json(name = "bittensorDwellirKey") val bittensorDwellirApiKey: String?,
|
||||
@Json(name = "bittensorOnfinalityKey") val bittensorOnfinalityKey: String?,
|
||||
@Json(name = "koinosProApiKey") val koinosProApiKey: String?,
|
||||
|
|
@ -97,6 +98,12 @@ data class TonCenterKeys(
|
|||
@Json(name = "testnet") val testnet: String,
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class P2PKeys(
|
||||
@Json(name = "mainnet") val mainnet: String,
|
||||
@Json(name = "hoodi") val hoodi: String,
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class GetBlockToken(
|
||||
@Json(name = "jsonRpc") val jsonRPC: String?,
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ class ApiConfigTest {
|
|||
ApiConfig.ID.TangemPay -> TangemPay(appVersionProvider = mockk())
|
||||
ApiConfig.ID.BlockAid -> BlockAid(configStorage = mockk())
|
||||
ApiConfig.ID.MoonPay -> MoonPay()
|
||||
ApiConfig.ID.P2PEthPool -> P2PEthPool(p2pAuthProvider = mockk())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import com.tangem.datasource.api.common.config.ApiConfig.Companion.RELEASE_BUILD
|
|||
import com.tangem.datasource.api.common.config.managers.MockEnvironmentConfigStorage.Companion.BLOCK_AID_API_KEY
|
||||
import com.tangem.datasource.api.common.config.managers.MockEnvironmentConfigStorage.Companion.TANGEM_API_KEY
|
||||
import com.tangem.lib.auth.ExpressAuthProvider
|
||||
import com.tangem.lib.auth.P2PEthPoolAuthProvider
|
||||
import com.tangem.lib.auth.StakeKitAuthProvider
|
||||
import com.tangem.utils.ProviderSuspend
|
||||
import com.tangem.utils.info.AppInfoProvider
|
||||
|
|
@ -39,6 +40,7 @@ internal class ProdApiConfigsManagerTest {
|
|||
private val appVersionProvider = mockk<AppVersionProvider>()
|
||||
private val expressAuthProvider = mockk<ExpressAuthProvider>()
|
||||
private val stakeKitAuthProvider = mockk<StakeKitAuthProvider>()
|
||||
private val p2pEthPoolAuthProvider = mockk<P2PEthPoolAuthProvider>()
|
||||
private val appAuthProvider = mockk<AuthProvider>()
|
||||
private val appInfoProvider = mockk<AppInfoProvider>()
|
||||
private val tangemApiKeyProvider = mockk<ProviderSuspend<String>>()
|
||||
|
|
@ -58,6 +60,7 @@ internal class ProdApiConfigsManagerTest {
|
|||
every { appVersionProvider.versionName } returns VERSION_NAME
|
||||
every { expressAuthProvider.getSessionId() } returns EXPRESS_SESSION_ID
|
||||
every { stakeKitAuthProvider.getApiKey() } returns STAKE_KIT_API_KEY
|
||||
every { p2pEthPoolAuthProvider.getApiKey() } returns P2P_API_KEY
|
||||
every { appAuthProvider.getApiKey(any()) } returns tangemApiKeyProvider
|
||||
coEvery { tangemApiKeyProvider.invoke() } returns TANGEM_API_KEY
|
||||
coEvery { appAuthProvider.getCardId() } returns APP_CARD_ID
|
||||
|
|
@ -110,6 +113,7 @@ internal class ProdApiConfigsManagerTest {
|
|||
ApiConfig.ID.TangemPay -> TangemPay(appVersionProvider = appVersionProvider)
|
||||
ApiConfig.ID.BlockAid -> BlockAid(configStorage = environmentConfigStorage)
|
||||
ApiConfig.ID.MoonPay -> MoonPay()
|
||||
ApiConfig.ID.P2PEthPool -> P2PEthPool(p2pAuthProvider = p2pEthPoolAuthProvider)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -123,6 +127,7 @@ internal class ProdApiConfigsManagerTest {
|
|||
ApiConfig.ID.TangemPay -> createTangemPayModel()
|
||||
ApiConfig.ID.BlockAid -> createBlockAidSdkModel()
|
||||
ApiConfig.ID.MoonPay -> createMoonPayModel()
|
||||
ApiConfig.ID.P2PEthPool -> createP2PModel()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -275,6 +280,21 @@ internal class ProdApiConfigsManagerTest {
|
|||
)
|
||||
}
|
||||
|
||||
private fun createP2PModel(): TestModel {
|
||||
return TestModel(
|
||||
id = ApiConfig.ID.P2PEthPool,
|
||||
expected = ApiEnvironmentConfig(
|
||||
environment = ApiEnvironment.PROD,
|
||||
baseUrl = "https://api.p2p.org/",
|
||||
headers = mapOf(
|
||||
"Authorization" to ProviderSuspend { "Bearer $P2P_API_KEY" },
|
||||
"accept" to ProviderSuspend { "application/json" },
|
||||
"Content-Type" to ProviderSuspend { "application/json" },
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun String.checkHeaderValueOrEmpty(): String {
|
||||
for (i in this.indices) {
|
||||
val c = this[i]
|
||||
|
|
@ -293,6 +313,7 @@ internal class ProdApiConfigsManagerTest {
|
|||
const val VERSION_NAME = "debug"
|
||||
const val EXPRESS_SESSION_ID = "express_session_id"
|
||||
const val STAKE_KIT_API_KEY = "stake_kit_api_key"
|
||||
const val P2P_API_KEY = "p2p_api_key"
|
||||
const val APP_CARD_ID = "app_card_id"
|
||||
const val APP_CARD_PUBLIC_KEY = "Bearer app_public_key"
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue