Updated on 2026-08-14

This commit is contained in:
Tangem 2026-05-22 11:17:28 +02:00
parent 6031a97ffe
commit 8d0f11d10b
67 changed files with 1527 additions and 41 deletions

View file

@ -0,0 +1,69 @@
package com.tangem.feature.swap
import arrow.core.Either
import com.tangem.datasource.api.surveysparrow.SurveySparrowApi
import com.tangem.datasource.api.surveysparrow.models.CreateSurveySparrowResponseBody
import com.tangem.datasource.api.surveysparrow.models.SurveySparrowAnswerDto
import com.tangem.feature.swap.domain.api.SwapFeedbackRepository
import com.tangem.feature.swap.domain.models.domain.ExistingRating
import com.tangem.feature.swap.domain.models.domain.SwapFeedbackParams
import org.json.JSONObject
internal class DefaultSwapFeedbackRepository(
private val api: SurveySparrowApi,
private val surveyId: Long,
private val ratingQuestionId: Long,
private val feedbackQuestionId: Long,
) : SwapFeedbackRepository {
override suspend fun getRating(txExternalId: String): Either<Throwable, ExistingRating?> {
return Either.catch {
val responses = api.getResponses(
surveyId = surveyId,
variables = JSONObject().put("tx_external_id", txExternalId).toString(),
limit = 1,
)
val ratingAnswer = responses.data
.firstOrNull()
?.answers
?.firstOrNull { answer ->
when (val id = answer.questionId) {
is Number -> id.toLong() == ratingQuestionId
else -> false
}
}
?.answer
?.let { v ->
when (v) {
is Number -> v.toInt()
is String -> v.toIntOrNull()
else -> null
}
}
if (ratingAnswer != null) ExistingRating(ratingAnswer) else null
}
}
override suspend fun submitFeedback(params: SwapFeedbackParams): Either<Throwable, Unit> {
return Either.catch {
api.createResponse(
CreateSurveySparrowResponseBody(
surveyId = surveyId,
answers = buildList {
add(SurveySparrowAnswerDto(ratingQuestionId, params.rating.toString()))
if (params.feedback.isNotEmpty()) {
add(SurveySparrowAnswerDto(feedbackQuestionId, params.feedback))
}
},
variables = mapOf(
"tx_external_id" to params.txExternalId,
"provider_name" to params.providerName,
"tx_url" to params.txUrl,
"user_wallet_id" to params.userWalletIdHash,
),
),
)
}
}
}

View file

@ -0,0 +1,14 @@
package com.tangem.feature.swap
import arrow.core.Either
import arrow.core.right
import com.tangem.feature.swap.domain.api.SwapFeedbackRepository
import com.tangem.feature.swap.domain.models.domain.ExistingRating
import com.tangem.feature.swap.domain.models.domain.SwapFeedbackParams
internal class NoOpSwapFeedbackRepository : SwapFeedbackRepository {
override suspend fun getRating(txExternalId: String): Either<Throwable, ExistingRating?> = null.right()
override suspend fun submitFeedback(params: SwapFeedbackParams): Either<Throwable, Unit> = Unit.right()
}

View file

@ -5,16 +5,21 @@ import com.tangem.data.common.currency.ResponseCryptoCurrenciesFactory
import com.tangem.data.common.network.NetworkFactory
import com.tangem.datasource.api.express.TangemExpressApi
import com.tangem.datasource.api.express.models.response.ExpressErrorResponse
import com.tangem.datasource.api.surveysparrow.SurveySparrowApi
import com.tangem.datasource.crypto.DataSignatureVerifier
import com.tangem.datasource.di.NetworkMoshi
import com.tangem.datasource.local.config.environment.EnvironmentConfig
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.domain.account.supplier.SingleAccountListSupplier
import com.tangem.domain.exchange.RampStateManager
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.feature.swap.DefaultSwapFeedbackRepository
import com.tangem.feature.swap.DefaultSwapRepository
import com.tangem.feature.swap.NoOpSwapFeedbackRepository
import com.tangem.feature.swap.DefaultSwapTransactionRepository
import com.tangem.feature.swap.converters.ErrorsDataConverter
import com.tangem.feature.swap.domain.SwapTransactionRepository
import com.tangem.feature.swap.domain.api.SwapFeedbackRepository
import com.tangem.feature.swap.domain.api.SwapRepository
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.Module
@ -75,4 +80,20 @@ internal class SwapDataModule {
val jsonAdapter = moshi.adapter(ExpressErrorResponse::class.java)
return ErrorsDataConverter(jsonAdapter)
}
@Provides
@Singleton
internal fun provideSwapFeedbackRepository(
api: SurveySparrowApi,
environmentConfig: EnvironmentConfig,
): SwapFeedbackRepository {
val rating = environmentConfig.surveySparrowSwapRating
?: return NoOpSwapFeedbackRepository()
return DefaultSwapFeedbackRepository(
api = api,
surveyId = rating.surveyId,
ratingQuestionId = rating.ratingQuestionId,
feedbackQuestionId = rating.feedbackQuestionId,
)
}
}