Updated on 2026-08-14
This commit is contained in:
parent
4ad958be89
commit
e0fb0e3587
7 changed files with 118 additions and 3 deletions
|
|
@ -172,4 +172,13 @@ interface TangemTechApi {
|
|||
@Header("Cache-Control") cacheControl: String = "max-age=600",
|
||||
): ApiResponse<PromoBannerResponse>
|
||||
// endregion
|
||||
|
||||
/**
|
||||
* Stores transaction hash in cache to prevent duplicate push
|
||||
* notifications for yield operations (deposit, withdraw, send).
|
||||
* Used when yield operations generate intermediate transactions
|
||||
* that should not trigger notifications.
|
||||
*/
|
||||
@POST("v1/transaction-events")
|
||||
suspend fun transactionEvents(@Body name: TransactionEventBody): ApiResponse<Unit>
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package com.tangem.datasource.api.tangemTech.models
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class TransactionEventBody(
|
||||
@Json(name = "transactionId") val transactionId: String,
|
||||
@Json(name = "operationType") val operationType: OperationType,
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = false)
|
||||
enum class OperationType {
|
||||
|
||||
@Json(name = "YIELD_DEPOSIT")
|
||||
YIELD_DEPOSIT,
|
||||
|
||||
@Json(name = "YIELD_WITHDRAW")
|
||||
YIELD_WITHDRAW,
|
||||
|
||||
@Json(name = "YIELD_SEND")
|
||||
YIELD_SEND,
|
||||
}
|
||||
|
|
@ -20,13 +20,19 @@ import com.tangem.blockchain.common.transaction.Fee
|
|||
import com.tangem.blockchain.nft.models.NFTAsset
|
||||
import com.tangem.blockchainsdk.utils.fromNetworkId
|
||||
import com.tangem.blockchainsdk.utils.toBlockchain
|
||||
import com.tangem.datasource.api.common.response.fold
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.api.tangemTech.models.OperationType
|
||||
import com.tangem.datasource.api.tangemTech.models.TransactionEventBody
|
||||
import com.tangem.datasource.local.walletmanager.WalletManagersStore
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.transaction.TransactionRepository
|
||||
import com.tangem.domain.transaction.models.EventTransactionTypeDto
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.coroutines.runCatching
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
import java.math.BigDecimal
|
||||
|
|
@ -34,6 +40,7 @@ import java.math.BigInteger
|
|||
|
||||
@Suppress("LargeClass")
|
||||
internal class DefaultTransactionRepository(
|
||||
private val tangemTechApi: TangemTechApi,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
private val walletManagersStore: WalletManagersStore,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
|
|
@ -415,6 +422,31 @@ internal class DefaultTransactionRepository(
|
|||
preparer.prepareAndSignMultiple(transactionData, signer)
|
||||
}
|
||||
|
||||
override suspend fun sendTransactionHash(hash: String, transactionType: EventTransactionTypeDto) {
|
||||
runCatching(dispatchers.io) {
|
||||
val operationType = when (transactionType) {
|
||||
EventTransactionTypeDto.DEPOSIT -> OperationType.YIELD_DEPOSIT
|
||||
EventTransactionTypeDto.WITHDRAW -> OperationType.YIELD_WITHDRAW
|
||||
EventTransactionTypeDto.SEND -> OperationType.YIELD_SEND
|
||||
}
|
||||
val body = TransactionEventBody(
|
||||
operationType = operationType,
|
||||
transactionId = hash,
|
||||
)
|
||||
val response = tangemTechApi.transactionEvents(body)
|
||||
response.fold(
|
||||
onSuccess = {
|
||||
Timber.d("Successfully sent yield supply transaction hash: $hash")
|
||||
},
|
||||
onError = { error ->
|
||||
Timber.e(error, "Failed to send yield supply transaction hash: $hash")
|
||||
},
|
||||
)
|
||||
}.onFailure { error ->
|
||||
Timber.e(error, "Failed to send yield supply transaction hash: $hash")
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getPreparer(network: Network, userWalletId: UserWalletId): TransactionPreparer {
|
||||
val blockchain = network.toBlockchain()
|
||||
val walletManager = walletManagersFacade.getOrCreateWalletManager(
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.tangem.data.transaction.DefaultFeeRepository
|
|||
import com.tangem.data.transaction.DefaultTransactionRepository
|
||||
import com.tangem.data.transaction.DefaultWalletAddressServiceRepository
|
||||
import com.tangem.data.transaction.error.DefaultFeeErrorResolver
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.local.walletmanager.WalletManagersStore
|
||||
import com.tangem.domain.demo.models.DemoConfig
|
||||
import com.tangem.domain.transaction.FeeRepository
|
||||
|
|
@ -25,11 +26,13 @@ internal object TransactionDataModule {
|
|||
@Provides
|
||||
@Singleton
|
||||
fun providesTransactionRepository(
|
||||
tangemTechApi: TangemTechApi,
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
walletManagersStore: WalletManagersStore,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): TransactionRepository {
|
||||
return DefaultTransactionRepository(
|
||||
tangemTechApi = tangemTechApi,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
walletManagersStore = walletManagersStore,
|
||||
dispatchers = dispatchers,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
package com.tangem.domain.transaction.models
|
||||
|
||||
/**
|
||||
* DTO representing the type of a transaction event on tangem backend to send
|
||||
* info about transaction happens and its hash
|
||||
*/
|
||||
enum class EventTransactionTypeDto {
|
||||
DEPOSIT,
|
||||
WITHDRAW,
|
||||
SEND,
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ import com.tangem.blockchain.nft.models.NFTAsset
|
|||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.transaction.models.EventTransactionTypeDto
|
||||
import java.math.BigDecimal
|
||||
import java.math.BigInteger
|
||||
|
||||
|
|
@ -123,4 +124,6 @@ interface TransactionRepository {
|
|||
userWalletId: UserWalletId,
|
||||
network: Network,
|
||||
): com.tangem.blockchain.extensions.Result<List<ByteArray>>
|
||||
|
||||
suspend fun sendTransactionHash(hash: String, transactionType: EventTransactionTypeDto)
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ package com.tangem.domain.transaction.usecase
|
|||
import arrow.core.Either
|
||||
import arrow.core.left
|
||||
import arrow.core.right
|
||||
import com.tangem.blockchain.blockchains.ethereum.EthereumTransactionExtras
|
||||
import com.tangem.blockchain.common.BlockchainSdkError
|
||||
import com.tangem.blockchain.common.TransactionData
|
||||
import com.tangem.blockchain.common.TransactionSender
|
||||
|
|
@ -10,21 +11,25 @@ import com.tangem.blockchain.common.TransactionSigner
|
|||
import com.tangem.blockchain.common.transaction.TransactionsSendResult
|
||||
import com.tangem.blockchain.extensions.Result
|
||||
import com.tangem.blockchain.network.ResultChecker
|
||||
import com.tangem.blockchain.yieldsupply.providers.ethereum.yield.EthereumYieldSupplyEnterCallData
|
||||
import com.tangem.blockchain.yieldsupply.providers.ethereum.yield.EthereumYieldSupplyExitCallData
|
||||
import com.tangem.blockchain.yieldsupply.providers.ethereum.yield.EthereumYieldSupplySendCallData
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.core.ui.format.bigdecimal.simple
|
||||
import com.tangem.domain.card.common.TapWorkarounds.isStart2Coin
|
||||
import com.tangem.domain.card.common.TapWorkarounds.isTangemTwins
|
||||
import com.tangem.domain.card.models.TwinKey
|
||||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.domain.demo.models.DemoConfig
|
||||
import com.tangem.domain.demo.DemoTransactionSender
|
||||
import com.tangem.domain.demo.models.DemoConfig
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.networks.single.SingleNetworkStatusFetcher
|
||||
import com.tangem.domain.transaction.TransactionRepository
|
||||
import com.tangem.domain.transaction.error.SendTransactionError
|
||||
import com.tangem.domain.transaction.error.parseWrappedError
|
||||
import com.tangem.domain.transaction.models.EventTransactionTypeDto
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
|
||||
class SendTransactionUseCase(
|
||||
private val demoConfig: DemoConfig,
|
||||
|
|
@ -100,7 +105,10 @@ class SendTransactionUseCase(
|
|||
)
|
||||
}
|
||||
.fold(
|
||||
ifRight = { result -> result.hashes.right() },
|
||||
ifRight = { result ->
|
||||
processSentTransactionsHashes(txsData, result.hashes)
|
||||
result.hashes.right()
|
||||
},
|
||||
ifLeft = { it.left() },
|
||||
)
|
||||
}
|
||||
|
|
@ -114,6 +122,32 @@ class SendTransactionUseCase(
|
|||
.map { it.first() }
|
||||
}
|
||||
|
||||
private suspend fun processSentTransactionsHashes(transactions: List<TransactionData>, hashes: List<String>) {
|
||||
transactions.forEachIndexed { ind, tx ->
|
||||
sendHashToBackendIfNeeded(tx, hashes[ind])
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends tx hash to backend for specific transaction types
|
||||
*/
|
||||
private suspend fun sendHashToBackendIfNeeded(transaction: TransactionData, txHash: String) {
|
||||
(transaction as? TransactionData.Uncompiled)?.let {
|
||||
val extras = it.extras
|
||||
when (extras) {
|
||||
is EthereumTransactionExtras -> {
|
||||
val txType = when (extras.callData) {
|
||||
is EthereumYieldSupplyEnterCallData -> EventTransactionTypeDto.DEPOSIT
|
||||
is EthereumYieldSupplySendCallData -> EventTransactionTypeDto.SEND
|
||||
is EthereumYieldSupplyExitCallData -> EventTransactionTypeDto.WITHDRAW
|
||||
else -> return
|
||||
}
|
||||
transactionRepository.sendTransactionHash(txHash, txType)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun sendDemo(
|
||||
userWallet: UserWallet,
|
||||
network: Network,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue