Updated on 2026-08-14

This commit is contained in:
Tangem 2025-12-04 18:46:38 +04:00
parent b210d3b7fd
commit c9804fa0ed
16 changed files with 166 additions and 51 deletions

View file

@ -1,9 +1,12 @@
package com.tangem.data.pay.datasource
import arrow.core.Either
import arrow.core.left
import arrow.core.raise.either
import com.tangem.common.CompletionResult
import com.tangem.common.core.TangemSdkError
import com.tangem.domain.pay.datasource.TangemPayAuthDataSource
import com.tangem.domain.pay.model.WithdrawalSignatureResult
import com.tangem.domain.visa.datasource.VisaAuthRemoteDataSource
import com.tangem.domain.visa.model.TangemPayAuthTokens
import com.tangem.domain.visa.model.TangemPayInitialCredentials
@ -28,12 +31,21 @@ internal class DefaultTangemPayAuthDataSource @Inject constructor(
.bind()
}
override suspend fun getWithdrawalSignature(cardId: String, hash: String): Either<Throwable, String> {
override suspend fun getWithdrawalSignature(
cardId: String,
hash: String,
): Either<Throwable, WithdrawalSignatureResult> {
return when (val signResult = tangemSdkManager.getWithdrawalSignature(cardId, hash)) {
is CompletionResult.Failure<*> -> Either.Left(
IllegalStateException("TangemPay sign hash failed: ${signResult.error}"),
)
is CompletionResult.Success<String> -> Either.Right(signResult.data)
is CompletionResult.Failure<*> -> {
if (signResult.error is TangemSdkError.UserCancelled) {
Either.Right(WithdrawalSignatureResult.Cancelled)
} else {
signResult.error.left()
}
}
is CompletionResult.Success<String> -> {
Either.Right(WithdrawalSignatureResult.Success(signResult.data))
}
}
}
}

View file

@ -11,7 +11,9 @@ import com.tangem.domain.common.wallets.UserWalletsListRepository
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.pay.WithdrawalResult
import com.tangem.domain.pay.datasource.TangemPayAuthDataSource
import com.tangem.domain.pay.model.WithdrawalSignatureResult
import com.tangem.domain.pay.repository.TangemPaySwapRepository
import com.tangem.domain.visa.error.VisaApiError
import com.tangem.domain.wallets.legacy.UserWalletsListManager
@ -39,7 +41,7 @@ internal class DefaultTangemPaySwapRepository @Inject constructor(
receiverAddress: String,
cryptoAmount: BigDecimal,
cryptoCurrencyId: CryptoCurrency.RawID,
): Either<UniversalError, Unit> {
): Either<UniversalError, WithdrawalResult> {
val amountInCents = getAmountInCents(cryptoAmount, cryptoCurrencyId)
if (amountInCents.isNullOrEmpty()) return Either.Left(VisaApiError.WithdrawalDataError)
return requestHelper.makeSafeRequest(userWalletId) { authHeader ->
@ -48,25 +50,35 @@ internal class DefaultTangemPaySwapRepository @Inject constructor(
}.map { data ->
val result = data.result
if (result == null) return Either.Left(VisaApiError.WithdrawalDataError)
val signature = authDataSource.getWithdrawalSignature(cardId = getCardId(userWalletId), hash = result.hash)
.getOrNull()
if (signature == null) return Either.Left(VisaApiError.SignWithdrawError)
val signatureResult = authDataSource.getWithdrawalSignature(
cardId = getCardId(userWalletId),
hash = result.hash,
).getOrNull()
requestHelper.makeSafeRequest(userWalletId) { authHeader ->
val request = WithdrawRequest(
amountInCents = amountInCents,
recipientAddress = receiverAddress,
adminSalt = result.salt,
senderAddress = result.senderAddress,
adminSignature = signature,
)
tangemPayApi.withdraw(authHeader = authHeader, body = request)
}
.mapLeft { return Either.Left(VisaApiError.WithdrawError) }
.map { response ->
val orderId = response.result?.orderId
if (orderId != null) tangemPayStorage.storeWithdrawOrder(userWalletId, orderId)
return when (signatureResult) {
is WithdrawalSignatureResult.Cancelled -> {
Either.Right(WithdrawalResult.Cancelled)
}
is WithdrawalSignatureResult.Success -> {
requestHelper.makeSafeRequest(userWalletId) { authHeader ->
val request = WithdrawRequest(
amountInCents = amountInCents,
recipientAddress = receiverAddress,
adminSalt = result.salt,
senderAddress = result.senderAddress,
adminSignature = signatureResult.signature,
)
tangemPayApi.withdraw(authHeader = authHeader, body = request)
}
.mapLeft { return Either.Left(VisaApiError.WithdrawError) }
.map { response ->
val orderId = response.result?.orderId
if (orderId != null) tangemPayStorage.storeWithdrawOrder(userWalletId, orderId)
WithdrawalResult.Success
}
}
null -> return Either.Left(VisaApiError.SignWithdrawError)
}
}
}

View file

@ -4,6 +4,7 @@ import arrow.core.Either
import com.tangem.core.error.UniversalError
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.pay.WithdrawalResult
import com.tangem.domain.pay.repository.TangemPaySwapRepository
import com.tangem.domain.tangempay.TangemPayWithdrawUseCase
import java.math.BigDecimal
@ -18,7 +19,7 @@ internal class DefaultTangemPayWithdrawUseCase @Inject constructor(
cryptoAmount: BigDecimal,
cryptoCurrencyId: CryptoCurrency.RawID,
receiverCexAddress: String,
): Either<UniversalError, Unit> {
): Either<UniversalError, WithdrawalResult> {
return repository.withdraw(
userWalletId = userWalletId,
cryptoAmount = cryptoAmount,