Updated on 2026-08-14
This commit is contained in:
parent
b73c5486d3
commit
e80ade9558
13 changed files with 470 additions and 10 deletions
|
|
@ -23,9 +23,11 @@ dependencies {
|
|||
|
||||
/** Util */
|
||||
implementation(projects.core.utils)
|
||||
implementation(projects.core.datasource)
|
||||
|
||||
/** Other */
|
||||
implementation(deps.arrow.core)
|
||||
implementation(deps.kotlin.coroutines)
|
||||
implementation(deps.jodatime)
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
package com.tangem.domain.swap.models
|
||||
|
||||
import java.math.BigDecimal
|
||||
import java.math.BigInteger
|
||||
|
||||
data class SwapDataModel(
|
||||
val toTokenAmount: BigDecimal,
|
||||
val transaction: SwapDataTransactionModel,
|
||||
)
|
||||
|
||||
sealed class SwapDataTransactionModel {
|
||||
|
||||
abstract val fromAmount: BigDecimal
|
||||
abstract val toAmount: BigDecimal
|
||||
abstract val txValue: String
|
||||
abstract val txId: String
|
||||
abstract val txTo: String
|
||||
abstract val txExtraId: String?
|
||||
|
||||
/**
|
||||
* @param txValue amount for tx, should use native coin decimals, this value will send as native amount in tx
|
||||
*/
|
||||
data class DEX(
|
||||
override val fromAmount: BigDecimal,
|
||||
override val toAmount: BigDecimal,
|
||||
override val txValue: String,
|
||||
override val txId: String,
|
||||
override val txTo: String,
|
||||
override val txExtraId: String?,
|
||||
val txFrom: String,
|
||||
val txData: String,
|
||||
val otherNativeFeeWei: BigDecimal?,
|
||||
val gas: BigInteger,
|
||||
) : SwapDataTransactionModel()
|
||||
|
||||
data class CEX(
|
||||
override val fromAmount: BigDecimal,
|
||||
override val toAmount: BigDecimal,
|
||||
override val txValue: String,
|
||||
override val txId: String,
|
||||
override val txTo: String,
|
||||
override val txExtraId: String?,
|
||||
val externalTxId: String,
|
||||
val externalTxUrl: String,
|
||||
val txExtraIdName: String?,
|
||||
) : SwapDataTransactionModel()
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.tangem.domain.swap.models
|
||||
|
||||
/**
|
||||
* Refund data
|
||||
*
|
||||
* @param refundAddress address refund send to
|
||||
* @param refundExtraId refund token id
|
||||
*/
|
||||
data class SwapRefundData(
|
||||
val refundAddress: String? = null,
|
||||
val refundExtraId: String? = null,
|
||||
)
|
||||
|
|
@ -3,8 +3,10 @@ package com.tangem.domain.swap
|
|||
import com.tangem.domain.express.models.ExpressProvider
|
||||
import com.tangem.domain.express.models.ExpressRateType
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.swap.models.SwapDataModel
|
||||
import com.tangem.domain.swap.models.SwapPairModel
|
||||
import com.tangem.domain.swap.models.SwapQuoteModel
|
||||
import com.tangem.domain.swap.models.SwapStatusModel
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import java.math.BigDecimal
|
||||
|
|
@ -12,6 +14,7 @@ import java.math.BigDecimal
|
|||
/**
|
||||
* Swap repository
|
||||
*/
|
||||
@Suppress("LongParameterList")
|
||||
interface SwapRepositoryV2 {
|
||||
|
||||
/**
|
||||
|
|
@ -44,7 +47,6 @@ interface SwapRepositoryV2 {
|
|||
* @param provider selected express provider
|
||||
* @param rateType rate type
|
||||
*/
|
||||
@Suppress("LongParameterList")
|
||||
suspend fun getSwapQuote(
|
||||
userWallet: UserWallet,
|
||||
fromCryptoCurrency: CryptoCurrency,
|
||||
|
|
@ -53,4 +55,52 @@ interface SwapRepositoryV2 {
|
|||
provider: ExpressProvider,
|
||||
rateType: ExpressRateType,
|
||||
): SwapQuoteModel
|
||||
|
||||
/**
|
||||
* Returns swap data [SwapDataModel] ready to sign and send on selected quote
|
||||
*
|
||||
* @param userWallet selected user wallet
|
||||
* @param fromCryptoCurrencyStatus currency status being swapped from
|
||||
* @param toCryptoCurrencyStatus currency status being swapped to
|
||||
* @param fromAmount swap amount
|
||||
* @param toAddress destination address (optional, if null send to self)
|
||||
* @param expressProvider selected swap provider
|
||||
* @param rateType selected provider rate type
|
||||
*/
|
||||
suspend fun getSwapData(
|
||||
userWallet: UserWallet,
|
||||
fromCryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
toCryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
fromAmount: String,
|
||||
toAddress: String?,
|
||||
expressProvider: ExpressProvider,
|
||||
rateType: ExpressRateType,
|
||||
): SwapDataModel
|
||||
|
||||
/**
|
||||
* Send ExpressApi info that swap transaction occurred
|
||||
*
|
||||
* @param userWallet selected user wallet
|
||||
* @param fromCryptoCurrencyStatus currency status being swapped from
|
||||
* @param toAddress swap destination address
|
||||
* @param txId transaction id in ExpressApi
|
||||
* @param txHash transaction hash in blockchain
|
||||
* @param txExtraId extra transaction id in ExpressApi
|
||||
*/
|
||||
suspend fun swapTransactionSent(
|
||||
userWallet: UserWallet,
|
||||
fromCryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
toAddress: String,
|
||||
txId: String,
|
||||
txHash: String,
|
||||
txExtraId: String?,
|
||||
)
|
||||
|
||||
/**
|
||||
* Returns status [SwapStatusModel] on active swap
|
||||
*
|
||||
* @param userWallet selected user wallet
|
||||
* @param txId transaction id in ExpressApi
|
||||
*/
|
||||
suspend fun getExchangeStatus(userWallet: UserWallet, txId: String): SwapStatusModel
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
package com.tangem.domain.swap.usecase
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.domain.express.models.ExpressError
|
||||
import com.tangem.domain.express.models.ExpressProvider
|
||||
import com.tangem.domain.express.models.ExpressRateType
|
||||
import com.tangem.domain.swap.SwapErrorResolver
|
||||
import com.tangem.domain.swap.SwapRepositoryV2
|
||||
import com.tangem.domain.swap.models.SwapDataModel
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
class GetSwapDataUseCase(
|
||||
private val swapRepositoryV2: SwapRepositoryV2,
|
||||
private val swapErrorResolver: SwapErrorResolver,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(
|
||||
userWallet: UserWallet,
|
||||
fromCryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
fromAmount: String,
|
||||
toCryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
toAddress: String?,
|
||||
expressProvider: ExpressProvider,
|
||||
rateType: ExpressRateType,
|
||||
): Either<ExpressError, SwapDataModel> = Either.catch {
|
||||
swapRepositoryV2.getSwapData(
|
||||
userWallet = userWallet,
|
||||
fromCryptoCurrencyStatus = fromCryptoCurrencyStatus,
|
||||
fromAmount = fromAmount,
|
||||
toCryptoCurrencyStatus = toCryptoCurrencyStatus,
|
||||
toAddress = toAddress,
|
||||
expressProvider = expressProvider,
|
||||
rateType = rateType,
|
||||
)
|
||||
}.mapLeft { throwable ->
|
||||
swapErrorResolver.resolve(throwable)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
package com.tangem.domain.swap.usecase
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.domain.express.models.ExpressProvider
|
||||
import com.tangem.domain.express.models.ExpressProviderType.Companion.shouldStoreSwapTransaction
|
||||
import com.tangem.domain.swap.SwapErrorResolver
|
||||
import com.tangem.domain.swap.SwapRepositoryV2
|
||||
import com.tangem.domain.swap.SwapTransactionRepository
|
||||
import com.tangem.domain.swap.models.SwapDataTransactionModel
|
||||
import com.tangem.domain.swap.models.SwapStatus
|
||||
import com.tangem.domain.swap.models.SwapStatusModel
|
||||
import com.tangem.domain.swap.models.SwapTransactionModel
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
class SwapTransactionSentUseCase(
|
||||
private val swapRepositoryV2: SwapRepositoryV2,
|
||||
private val swapTransactionRepository: SwapTransactionRepository,
|
||||
private val swapErrorResolver: SwapErrorResolver,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(
|
||||
userWallet: UserWallet,
|
||||
fromCryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
toCryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
swapDataTransactionModel: SwapDataTransactionModel,
|
||||
provider: ExpressProvider,
|
||||
txHash: String,
|
||||
) = Either.catch {
|
||||
swapRepositoryV2.swapTransactionSent(
|
||||
userWallet = userWallet,
|
||||
fromCryptoCurrencyStatus = fromCryptoCurrencyStatus,
|
||||
toAddress = swapDataTransactionModel.txTo,
|
||||
txId = swapDataTransactionModel.txId,
|
||||
txHash = txHash,
|
||||
txExtraId = swapDataTransactionModel.txExtraId,
|
||||
)
|
||||
if (provider.type.shouldStoreSwapTransaction()) {
|
||||
val timestamp = System.currentTimeMillis()
|
||||
swapTransactionRepository.storeTransaction(
|
||||
userWalletId = userWallet.walletId,
|
||||
fromCryptoCurrency = fromCryptoCurrencyStatus.currency,
|
||||
toCryptoCurrency = toCryptoCurrencyStatus.currency,
|
||||
transaction = SwapTransactionModel(
|
||||
txId = swapDataTransactionModel.txId,
|
||||
provider = provider,
|
||||
timestamp = timestamp,
|
||||
fromCryptoAmount = swapDataTransactionModel.fromAmount,
|
||||
toCryptoAmount = swapDataTransactionModel.toAmount,
|
||||
status = SwapStatusModel(
|
||||
providerId = provider.providerId,
|
||||
status = SwapStatus.New,
|
||||
txId = swapDataTransactionModel.txId,
|
||||
txExternalUrl = (swapDataTransactionModel as? SwapDataTransactionModel.CEX)?.externalTxUrl,
|
||||
txExternalId = (swapDataTransactionModel as? SwapDataTransactionModel.CEX)?.externalTxId,
|
||||
averageDuration = null,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
swapTransactionRepository.storeLastSwappedCryptoCurrencyId(
|
||||
userWalletId = userWallet.walletId,
|
||||
cryptoCurrencyId = toCryptoCurrencyStatus.currency.id,
|
||||
)
|
||||
}.mapLeft(swapErrorResolver::resolve)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue