Updated on 2026-08-14
This commit is contained in:
parent
7a8f55b589
commit
2af08f578c
46 changed files with 1035 additions and 0 deletions
|
|
@ -0,0 +1,21 @@
|
|||
package com.tangem.datasource.api.common.blockaid
|
||||
|
||||
import com.tangem.datasource.api.common.blockaid.models.request.DomainScanRequest
|
||||
import com.tangem.datasource.api.common.blockaid.models.request.EvmTransactionScanRequest
|
||||
import com.tangem.datasource.api.common.blockaid.models.request.SolanaTransactionScanRequest
|
||||
import com.tangem.datasource.api.common.blockaid.models.response.DomainScanResponse
|
||||
import com.tangem.datasource.api.common.blockaid.models.response.TransactionScanResponse
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.POST
|
||||
|
||||
interface BlockAidApi {
|
||||
|
||||
@POST("site/scan")
|
||||
suspend fun scanDomain(@Body request: DomainScanRequest): DomainScanResponse
|
||||
|
||||
@POST("evm/json-rpc/scan")
|
||||
suspend fun scanJsonRpc(@Body request: EvmTransactionScanRequest): TransactionScanResponse
|
||||
|
||||
@POST("solana/message/scan")
|
||||
suspend fun scanSolanaMessage(@Body request: SolanaTransactionScanRequest): TransactionScanResponse
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package com.tangem.datasource.api.common.blockaid.models.request
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class DomainScanRequest(
|
||||
@Json(name = "url") val url: String,
|
||||
)
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package com.tangem.datasource.api.common.blockaid.models.request
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import com.tangem.datasource.api.common.blockaid.models.response.TransactionMetadata
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class EvmTransactionScanRequest(
|
||||
@Json(name = "chain") val chain: String,
|
||||
@Json(name = "account_address") val accountAddress: String,
|
||||
@Json(name = "method") val method: String,
|
||||
@Json(name = "data") val data: RpcData,
|
||||
@Json(name = "options") val options: List<String> = listOf("simulation", "validation"),
|
||||
@Json(name = "metadata") val metadata: TransactionMetadata,
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class RpcData(
|
||||
@Json(name = "jsonrpc") val jsonrpc: String = "2.0",
|
||||
@Json(name = "method") val method: String,
|
||||
@Json(name = "params") val params: String,
|
||||
)
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package com.tangem.datasource.api.common.blockaid.models.request
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import com.tangem.datasource.api.common.blockaid.models.response.TransactionMetadata
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class SolanaTransactionScanRequest(
|
||||
@Json(name = "encoding") val encoding: String = "base64",
|
||||
@Json(name = "chain") val chain: String,
|
||||
@Json(name = "method") val method: String,
|
||||
@Json(name = "options") val options: List<String> = listOf("simulation, validation"),
|
||||
@Json(name = "metadata") val metadata: TransactionMetadata,
|
||||
@Json(name = "account_address") val accountAddress: String,
|
||||
@Json(name = "transactions") val transactions: List<String>,
|
||||
)
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package com.tangem.datasource.api.common.blockaid.models.response
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class AccountSummaryResponse(
|
||||
@Json(name = "assets_diffs") val assetsDiffs: List<AssetDiff>,
|
||||
@Json(name = "exposures") val exposures: List<Exposure>,
|
||||
)
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package com.tangem.datasource.api.common.blockaid.models.response
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class AssetDiff(
|
||||
@Json(name = "asset_type") val assetType: String,
|
||||
@Json(name = "asset") val asset: Asset,
|
||||
@Json(name = "in") val inTransfer: List<Transfer>? = null,
|
||||
@Json(name = "out") val outTransfer: List<Transfer>? = null,
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class Asset(
|
||||
@Json(name = "chain_id") val chainId: Int? = null,
|
||||
@Json(name = "logo_url") val logoUrl: String? = null,
|
||||
@Json(name = "symbol") val symbol: String,
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class Transfer(
|
||||
@Json(name = "value") val value: String,
|
||||
@Json(name = "raw_value") val rawValue: String,
|
||||
)
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package com.tangem.datasource.api.common.blockaid.models.response
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class DomainScanResponse(
|
||||
@Json(name = "status") val status: String,
|
||||
@Json(name = "is_malicious") val isMalicious: Boolean?,
|
||||
)
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package com.tangem.datasource.api.common.blockaid.models.response
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class Exposure(
|
||||
@Json(name = "asset") val asset: Asset,
|
||||
@Json(name = "spenders") val spenders: Map<String, SpenderDetails>,
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class SpenderDetails(
|
||||
@Json(name = "exposure") val exposure: List<ExposureDetail>,
|
||||
@Json(name = "is_approved_for_all") val isApprovedForAll: Boolean? = null,
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class ExposureDetail(
|
||||
@Json(name = "value") val value: String,
|
||||
@Json(name = "raw_value") val rawValue: String,
|
||||
)
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package com.tangem.datasource.api.common.blockaid.models.response
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class SimulationResponse(
|
||||
@Json(name = "status") val status: String,
|
||||
@Json(name = "account_summary") val accountSummary: AccountSummaryResponse,
|
||||
)
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package com.tangem.datasource.api.common.blockaid.models.response
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class TransactionMetadata(
|
||||
@Json(name = "domain") val domain: String,
|
||||
)
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package com.tangem.datasource.api.common.blockaid.models.response
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class TransactionScanResponse(
|
||||
@Json(name = "validation") val validation: ValidationResponse,
|
||||
@Json(name = "simulation") val simulation: SimulationResponse,
|
||||
)
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package com.tangem.datasource.api.common.blockaid.models.response
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class ValidationResponse(
|
||||
@Json(name = "status") val status: String,
|
||||
@Json(name = "result_type") val resultType: String,
|
||||
)
|
||||
|
|
@ -27,6 +27,7 @@ sealed class ApiConfig {
|
|||
TangemVisaAuth,
|
||||
TangemVisa,
|
||||
TangemCardSdk,
|
||||
BlockAid,
|
||||
}
|
||||
|
||||
private fun initializeId(): ID {
|
||||
|
|
@ -37,6 +38,7 @@ sealed class ApiConfig {
|
|||
is TangemVisaAuth -> ID.TangemVisaAuth
|
||||
is TangemVisa -> ID.TangemVisa
|
||||
is TangemCardSdk -> ID.TangemCardSdk
|
||||
is BlockAid -> ID.BlockAid
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
package com.tangem.datasource.api.common.config
|
||||
|
||||
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage
|
||||
import com.tangem.utils.ProviderSuspend
|
||||
|
||||
internal class BlockAid(
|
||||
private val environmentConfigStorage: EnvironmentConfigStorage,
|
||||
) : ApiConfig() {
|
||||
|
||||
override val defaultEnvironment: ApiEnvironment = ApiEnvironment.PROD
|
||||
|
||||
override val environmentConfigs = listOf(
|
||||
createProdEnvironment(),
|
||||
)
|
||||
|
||||
private fun createProdEnvironment(): ApiEnvironmentConfig = ApiEnvironmentConfig(
|
||||
environment = ApiEnvironment.PROD,
|
||||
baseUrl = "https://api.blockaid.io/v0/",
|
||||
headers = buildMap {
|
||||
environmentConfigStorage.getConfigSync().blockAidApiKey?.let { apiKey ->
|
||||
put("X-API-KEY", ProviderSuspend { apiKey })
|
||||
}
|
||||
put("accept", ProviderSuspend { "application/json" })
|
||||
put("content-type", ProviderSuspend { "application/json" })
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
@ -46,6 +46,12 @@ internal object ApiConfigsModule {
|
|||
@IntoSet
|
||||
fun provideTangemVisaConfig(appVersionProvider: AppVersionProvider): ApiConfig = TangemVisa(appVersionProvider)
|
||||
|
||||
@Provides
|
||||
@IntoSet
|
||||
fun provideBlockAidConfig(environmentConfigStorage: EnvironmentConfigStorage): ApiConfig {
|
||||
return BlockAid(environmentConfigStorage)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@IntoSet
|
||||
fun provideTangemCardSdkConfig(): ApiConfig = TangemCardSdk()
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import android.content.Context
|
|||
import com.squareup.moshi.Moshi
|
||||
import com.tangem.core.analytics.api.AnalyticsErrorHandler
|
||||
import com.tangem.datasource.BuildConfig
|
||||
import com.tangem.datasource.api.common.blockaid.BlockAidApi
|
||||
import com.tangem.datasource.api.common.config.ApiConfig
|
||||
import com.tangem.datasource.api.common.config.ApiConfigs
|
||||
import com.tangem.datasource.api.common.config.managers.ApiConfigsManager
|
||||
|
|
@ -282,6 +283,29 @@ internal object NetworkModule {
|
|||
.create(T::class.java)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideBlockAidApi(
|
||||
@NetworkMoshi moshi: Moshi,
|
||||
@ApplicationContext context: Context,
|
||||
analyticsErrorHandler: AnalyticsErrorHandler,
|
||||
apiConfigsManager: ApiConfigsManager,
|
||||
appLogsStore: AppLogsStore,
|
||||
): BlockAidApi {
|
||||
return createApi<BlockAidApi>(
|
||||
id = ApiConfig.ID.BlockAid,
|
||||
moshi = moshi,
|
||||
context = context,
|
||||
apiConfigsManager = apiConfigsManager,
|
||||
analyticsErrorHandler = analyticsErrorHandler,
|
||||
clientBuilder = {
|
||||
addInterceptor(
|
||||
NetworkLogsSaveInterceptor(appLogsStore),
|
||||
).applyTimeoutAnnotations()
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private inline fun <reified T> createApi(
|
||||
id: ApiConfig.ID,
|
||||
moshi: Moshi,
|
||||
|
|
|
|||
|
|
@ -14,4 +14,5 @@ data class EnvironmentConfig(
|
|||
val express: ExpressModel? = null,
|
||||
val devExpress: ExpressModel? = null,
|
||||
val stakeKitApiKey: String? = null,
|
||||
val blockAidApiKey: String? = null,
|
||||
)
|
||||
|
|
@ -23,6 +23,7 @@ internal object EnvironmentConfigConverter : Converter<EnvironmentConfigModel, E
|
|||
express = value.express,
|
||||
devExpress = value.devExpress,
|
||||
stakeKitApiKey = value.stakeKitApiKey,
|
||||
blockAidApiKey = value.blockaidApiKey,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -38,6 +38,7 @@ class EnvironmentConfigModel(
|
|||
@Json(name = "alephiumTangemApiKey") val alephiumTangemApiKey: String?,
|
||||
@Json(name = "moralisApiKey") val moralisApiKey: String?,
|
||||
@Json(name = "nftScanApiKey") val nftScanApiKey: String?,
|
||||
@Json(name = "blockaidApiKey") val blockaidApiKey: String?,
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ internal class ProdApiConfigsManagerTest(private val model: Model) {
|
|||
is TangemVisaAuth -> createVisaAuthModel()
|
||||
is TangemVisa -> createVisaModel()
|
||||
is TangemCardSdk -> createTangemCardSdkModel()
|
||||
is BlockAid -> createBlockAidSdkModel()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -218,6 +219,16 @@ internal class ProdApiConfigsManagerTest(private val model: Model) {
|
|||
)
|
||||
}
|
||||
|
||||
private fun createBlockAidSdkModel(): Model {
|
||||
return Model(
|
||||
id = ApiConfig.ID.BlockAid,
|
||||
expected = ApiEnvironmentConfig(
|
||||
environment = ApiEnvironment.PROD,
|
||||
baseUrl = "https://api.blockaid.io/v0/",
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun String.checkHeaderValueOrEmpty(): String {
|
||||
for (i in this.indices) {
|
||||
val c = this[i]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue