Updated on 2026-08-14
This commit is contained in:
parent
ae33c00aae
commit
85cff6b0d3
10 changed files with 169 additions and 22 deletions
|
|
@ -17,6 +17,9 @@ private const val SUCCESS_STATUS = "Success"
|
|||
private const val DOMAIN_CHECKED_STATUS = "hit"
|
||||
private const val VALIDATION_SAFE_STATUS = "Benign"
|
||||
private const val VALIDATION_WARNING_STATUS = "Warning"
|
||||
private const val VALIDATION_MALICIOUS_STATUS = "Malicious"
|
||||
|
||||
private const val SOL_ASSET_SYMBOL = "SOL"
|
||||
|
||||
internal object BlockAidMapper {
|
||||
|
||||
|
|
@ -28,6 +31,26 @@ internal object BlockAidMapper {
|
|||
}
|
||||
}
|
||||
|
||||
fun mapToDomain(from: SolanaTransactionResponse): CheckTransactionResult {
|
||||
val validation = when (from.result.validation.resultType) {
|
||||
VALIDATION_SAFE_STATUS -> ValidationResult.SAFE
|
||||
VALIDATION_WARNING_STATUS -> ValidationResult.WARNING
|
||||
VALIDATION_MALICIOUS_STATUS -> ValidationResult.UNSAFE
|
||||
else -> ValidationResult.FAILED_TO_VALIDATE
|
||||
}
|
||||
val simulationResponse = from.result.simulation
|
||||
val simulation = if (simulationResponse == null) {
|
||||
SimulationResult.FailedToSimulate
|
||||
} else {
|
||||
mapToSolanaAssetsDiffs(simulationResponse.accountSummary.accountAssetsDiff)
|
||||
}
|
||||
return CheckTransactionResult(
|
||||
validation = validation,
|
||||
description = from.result.validation.description,
|
||||
simulation = simulation,
|
||||
)
|
||||
}
|
||||
|
||||
fun mapToDomain(from: TransactionScanResponse): CheckTransactionResult {
|
||||
return CheckTransactionResult(
|
||||
validation = when {
|
||||
|
|
@ -68,7 +91,7 @@ internal object BlockAidMapper {
|
|||
|
||||
fun mapToSolanaRequest(from: TransactionData): SolanaTransactionScanRequest {
|
||||
return SolanaTransactionScanRequest(
|
||||
chain = from.chain.lowercase(),
|
||||
blockchain = from.chain.lowercase(),
|
||||
accountAddress = from.accountAddress,
|
||||
metadata = TransactionMetadata(from.domainUrl),
|
||||
method = from.method,
|
||||
|
|
@ -89,6 +112,49 @@ internal object BlockAidMapper {
|
|||
}
|
||||
}
|
||||
|
||||
private fun mapToSolanaAssetsDiffs(assetsDiffs: List<SolanaTransactionAssetDiff>): SimulationResult {
|
||||
val sendInfo = assetsDiffs.mapNotNull { assetDiff ->
|
||||
val outTransfer = assetDiff.outTransfer ?: return@mapNotNull null
|
||||
val amount = outTransfer.amount?.toBigDecimalOrNull() ?: return@mapNotNull null
|
||||
AmountInfo.FungibleTokens(
|
||||
amount = amount,
|
||||
token = TokenInfo(
|
||||
chainId = null,
|
||||
logoUrl = assetDiff.asset.logoUrl,
|
||||
symbol = assetDiff.asset.assetSymbol(),
|
||||
decimals = assetDiff.asset.decimals ?: 0,
|
||||
),
|
||||
)
|
||||
}
|
||||
val receiveInfo = assetsDiffs.mapNotNull { assetDiff ->
|
||||
val inTransfer = assetDiff.inTransfer ?: return@mapNotNull null
|
||||
val amount = inTransfer.amount?.toBigDecimalOrNull() ?: return@mapNotNull null
|
||||
AmountInfo.FungibleTokens(
|
||||
amount = amount,
|
||||
token = TokenInfo(
|
||||
chainId = null,
|
||||
logoUrl = assetDiff.asset.logoUrl,
|
||||
symbol = assetDiff.asset.assetSymbol(),
|
||||
decimals = assetDiff.asset.decimals ?: 0,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
return if (sendInfo.isNotEmpty() || receiveInfo.isNotEmpty()) {
|
||||
SimulationResult.Success(SimulationData.SendAndReceive(send = sendInfo, receive = receiveInfo))
|
||||
} else {
|
||||
SimulationResult.Success(SimulationData.NoWalletChangesDetected)
|
||||
}
|
||||
}
|
||||
|
||||
private fun SolanaTransactionAsset.assetSymbol(): String {
|
||||
return if (type?.lowercase().equals(SOL_ASSET_SYMBOL, ignoreCase = true)) {
|
||||
symbol ?: SOL_ASSET_SYMBOL
|
||||
} else {
|
||||
symbol.orEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
private fun mapApproveTransaction(exposures: List<Exposure>?): SimulationResult {
|
||||
val amounts = exposures?.flatMap { exposure ->
|
||||
val tokenInfo = TokenInfo(
|
||||
|
|
|
|||
|
|
@ -24,16 +24,21 @@ internal class DefaultBlockAidRepository(
|
|||
}
|
||||
|
||||
override suspend fun verifyTransaction(data: TransactionData): CheckTransactionResult {
|
||||
val response = withContext(dispatchers.io) {
|
||||
when (data.params) {
|
||||
is TransactionParams.Evm -> {
|
||||
api.scanJsonRpc(mapper.mapToEvmRequest(data))
|
||||
}
|
||||
is TransactionParams.Solana -> {
|
||||
api.scanSolanaMessage(mapper.mapToSolanaRequest(data))
|
||||
}
|
||||
}
|
||||
return when (data.params) {
|
||||
is TransactionParams.Evm -> scanEvmTransaction(data = data)
|
||||
is TransactionParams.Solana -> scanSolanaTransaction(data = data)
|
||||
}
|
||||
return mapper.mapToDomain(response)
|
||||
}
|
||||
|
||||
private suspend fun scanEvmTransaction(data: TransactionData): CheckTransactionResult =
|
||||
withContext(dispatchers.io) {
|
||||
val response = api.scanJsonRpc(mapper.mapToEvmRequest(data))
|
||||
mapper.mapToDomain(response)
|
||||
}
|
||||
|
||||
private suspend fun scanSolanaTransaction(data: TransactionData): CheckTransactionResult =
|
||||
withContext(dispatchers.io) {
|
||||
val response = api.scanSolanaMessage(mapper.mapToSolanaRequest(data))
|
||||
mapper.mapToDomain(response)
|
||||
}
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@ import com.tangem.datasource.api.common.blockaid.models.request.DomainScanReques
|
|||
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.SolanaTransactionResponse
|
||||
import com.tangem.datasource.api.common.blockaid.models.response.TransactionScanResponse
|
||||
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
|
||||
import io.mockk.*
|
||||
|
|
@ -91,7 +92,7 @@ class DefaultBlockAidRepositoryTest {
|
|||
)
|
||||
|
||||
val request = mockk<SolanaTransactionScanRequest>()
|
||||
val response = mockk<TransactionScanResponse>()
|
||||
val response = mockk<SolanaTransactionResponse>()
|
||||
val expectedResult = mockk<CheckTransactionResult>()
|
||||
|
||||
every { mapper.mapToSolanaRequest(data) } returns request
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue