Updated on 2026-08-14

This commit is contained in:
Tangem 2024-06-24 10:50:03 +01:00
commit bc84d8f5f8
579 changed files with 13604 additions and 3422 deletions

View file

@ -1,18 +1,14 @@
package com.tangem.tap.proxy
import com.tangem.core.navigation.AppScreen
import com.tangem.core.navigation.NavigationAction
import com.tangem.core.navigation.ReduxNavController
import com.tangem.domain.models.scan.CardDTO
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.redux.ReduxStateHolder
import com.tangem.domain.redux.StateDialog
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.tap.common.extensions.dispatchOnMain
import com.tangem.tap.common.extensions.dispatchDialogShow
import com.tangem.tap.common.extensions.dispatchWithMain
import com.tangem.tap.common.extensions.onUserWalletSelected
import com.tangem.tap.common.feedback.FeedbackEmail
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.domain.sdk.TangemSdkManager
import com.tangem.tap.network.exchangeServices.ExchangeService
import org.rekotlin.Action
@ -23,7 +19,7 @@ import javax.inject.Inject
* Holds objects from old modules, that missing in DI graph.
* Object sets manually to use in new modules and [AppStateHolder] proxies its to DI.
*/
class AppStateHolder @Inject constructor() : ReduxNavController, ReduxStateHolder {
class AppStateHolder @Inject constructor() : ReduxStateHolder {
@Deprecated("Use scan response from selected user wallet")
var scanResponse: ScanResponse? = null
@ -35,16 +31,6 @@ class AppStateHolder @Inject constructor() : ReduxNavController, ReduxStateHolde
return scanResponse?.card
}
override fun navigate(action: NavigationAction) {
mainStore?.dispatchOnMain(action)
}
override fun getBackStack(): List<AppScreen> = mainStore?.state?.navigationState?.backStack.orEmpty()
override fun popBackStack(screen: AppScreen?) {
mainStore?.dispatchOnMain(NavigationAction.PopBackTo(screen))
}
override fun dispatch(action: Action) {
mainStore?.dispatch(action)
}
@ -57,7 +43,7 @@ class AppStateHolder @Inject constructor() : ReduxNavController, ReduxStateHolde
mainStore?.onUserWalletSelected(userWallet)
}
override fun sendFeedbackEmail() {
mainStore?.dispatch(GlobalAction.SendEmail(FeedbackEmail()))
override fun dispatchDialogShow(dialog: StateDialog) {
mainStore?.dispatchDialogShow(dialog)
}
}

View file

@ -1,19 +1,10 @@
package com.tangem.tap.proxy
import androidx.core.text.isDigitsOnly
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.tangem.Message
import com.tangem.blockchain.blockchains.algorand.AlgorandTransactionExtras
import com.tangem.blockchain.blockchains.binance.BinanceTransactionExtras
import com.tangem.blockchain.blockchains.cosmos.CosmosTransactionExtras
import com.tangem.blockchain.blockchains.ethereum.EthereumTransactionExtras
import com.tangem.blockchain.blockchains.ethereum.EthereumWalletManager
import com.tangem.blockchain.blockchains.hedera.HederaTransactionExtras
import com.tangem.blockchain.blockchains.optimism.EthereumOptimisticRollupWalletManager
import com.tangem.blockchain.blockchains.stellar.StellarMemo
import com.tangem.blockchain.blockchains.stellar.StellarTransactionExtras
import com.tangem.blockchain.blockchains.ton.TonTransactionExtras
import com.tangem.blockchain.blockchains.xrp.XrpTransactionBuilder
import com.tangem.blockchain.common.*
import com.tangem.blockchain.common.transaction.Fee
import com.tangem.blockchain.common.transaction.TransactionFee
@ -65,31 +56,6 @@ class TransactionManagerImpl(
)
}
override suspend fun sendTransaction(
txData: SwapTxData,
isSwap: Boolean,
derivationPath: String?,
analyticsData: AnalyticsData,
): SendTxResult {
val blockchain = requireNotNull(Blockchain.fromNetworkId(txData.networkId)) { "blockchain not found" }
val walletManager = getActualWalletManager(blockchain, derivationPath)
walletManager.update()
val amount = if (isSwap) {
createAmountForSwap(txData.amountToSend, txData.currencyToSend, blockchain)
} else {
createAmount(txData.amountToSend, txData.currencyToSend, blockchain)
}
return sendTransactionInternal(
walletManager = walletManager,
amount = amount,
blockchain = blockchain,
feeAmount = txData.feeAmount,
gasLimit = txData.gasLimit,
destinationAddress = txData.destinationAddress,
dataToSign = txData.dataToSign,
)
}
@Suppress("LongParameterList")
private suspend fun sendTransactionInternal(
walletManager: WalletManager,
@ -125,39 +91,11 @@ class TransactionManagerImpl(
}
}
override fun getMemoExtras(networkId: String, memo: String?): TransactionExtras? {
val blockchain = Blockchain.fromNetworkId(networkId)
if (memo == null) return null
return when (blockchain) {
Blockchain.Stellar -> {
val xlmMemo = if (memo.isNotEmpty() && memo.isDigitsOnly()) {
StellarMemo.Id(memo.toBigInteger())
} else {
StellarMemo.Text(memo)
}
StellarTransactionExtras(xlmMemo)
}
Blockchain.Binance -> BinanceTransactionExtras(memo)
Blockchain.XRP -> memo.toLongOrNull()?.let { XrpTransactionBuilder.XrpTransactionExtras(it) }
Blockchain.Cosmos -> CosmosTransactionExtras(memo)
Blockchain.TON -> TonTransactionExtras(memo)
Blockchain.Hedera -> HederaTransactionExtras(memo)
Blockchain.Algorand -> AlgorandTransactionExtras(memo)
else -> null
}
}
override suspend fun updateWalletManager(networkId: String, derivationPath: String?) {
val blockchain = requireNotNull(Blockchain.fromNetworkId(networkId)) { "blockchain not found" }
getActualWalletManager(blockchain, derivationPath).update()
}
override fun calculateFee(networkId: String, gasPrice: String, estimatedGas: Int): BigDecimal {
val blockchain = requireNotNull(Blockchain.fromNetworkId(networkId)) { "blockchain not found" }
val gasPriceValue = requireNotNull(gasPrice.toLongOrNull()) { "gasprice should be Long" }
return (gasPriceValue * estimatedGas).toBigDecimal().movePointLeft(blockchain.decimals())
}
@Throws(IllegalStateException::class)
override suspend fun getFee(
networkId: String,
@ -512,25 +450,6 @@ class TransactionManagerImpl(
}
}
private fun createAmountForSwap(amount: BigDecimal, currency: Currency?, blockchain: Blockchain): Amount {
return when (currency) {
is Currency.NativeToken,
null,
-> {
Amount(value = amount, blockchain = blockchain)
}
is Currency.NonNativeToken -> {
// 1. when creates swap amount for NonNativeToken, amount should be ZERO
// 2. Amount has .Coin type, as workaround to use destinationAddress in bsdk, not contractAddress
Amount(
currencySymbol = currency.symbol,
value = BigDecimal.ZERO,
decimals = currency.decimalCount,
)
}
}
}
private fun convertNonNativeToken(token: Currency.NonNativeToken): Token {
return Token(
name = token.name,

View file

@ -4,8 +4,11 @@ import com.tangem.core.navigation.email.EmailSender
import com.tangem.domain.card.ScanCardUseCase
import com.tangem.domain.card.repository.CardSdkConfigRepository
import com.tangem.feature.qrscanning.QrScanningRouter
import com.tangem.features.disclaimer.api.DisclaimerRouter
import com.tangem.features.managetokens.navigation.ManageTokensUi
import com.tangem.features.pushnotifications.api.navigation.PushNotificationsRouter
import com.tangem.features.send.api.navigation.SendRouter
import com.tangem.features.staking.api.navigation.StakingRouter
import com.tangem.features.tester.api.TesterRouter
import com.tangem.features.tokendetails.navigation.TokenDetailsRouter
import com.tangem.features.wallet.navigation.WalletRouter
@ -25,5 +28,8 @@ sealed interface DaggerGraphAction : Action {
val sendRouter: SendRouter,
val qrScanningRouter: QrScanningRouter,
val emailSender: EmailSender,
val stakingRouter: StakingRouter,
val disclaimerRouter: DisclaimerRouter,
val pushNotificationsRouter: PushNotificationsRouter,
) : DaggerGraphAction
}

View file

@ -23,6 +23,9 @@ object DaggerGraphReducer {
sendRouter = action.sendRouter,
qrScanningRouter = action.qrScanningRouter,
emailSender = action.emailSender,
stakingRouter = action.stakingRouter,
disclaimerRouter = action.disclaimerRouter,
pushNotificationsRouter = action.pushNotificationsRouter,
)
}
}

View file

@ -2,7 +2,10 @@ package com.tangem.tap.proxy.redux
import com.tangem.TangemSdkLogger
import com.tangem.blockchainsdk.BlockchainSDKFactory
import com.tangem.common.routing.AppRouter
import com.tangem.core.navigation.email.EmailSender
import com.tangem.core.navigation.share.ShareManager
import com.tangem.core.navigation.url.UrlOpener
import com.tangem.datasource.asset.loader.AssetLoader
import com.tangem.datasource.connection.NetworkConnectionManager
import com.tangem.domain.appcurrency.repository.AppCurrencyRepository
@ -24,17 +27,20 @@ import com.tangem.domain.wallets.legacy.UserWalletsListManager
import com.tangem.domain.wallets.repository.WalletsRepository
import com.tangem.domain.wallets.usecase.GenerateWalletNameUseCase
import com.tangem.feature.qrscanning.QrScanningRouter
import com.tangem.features.details.DetailsEntryPoint
import com.tangem.features.details.DetailsFeatureToggles
import com.tangem.features.disclaimer.api.DisclaimerRouter
import com.tangem.features.managetokens.featuretoggles.ManageTokensFeatureToggles
import com.tangem.features.managetokens.navigation.ManageTokensUi
import com.tangem.features.pushnotifications.api.featuretoggles.PushNotificationsFeatureToggles
import com.tangem.features.pushnotifications.api.navigation.PushNotificationsRouter
import com.tangem.features.send.api.featuretoggles.SendFeatureToggles
import com.tangem.features.send.api.navigation.SendRouter
import com.tangem.features.staking.api.navigation.StakingRouter
import com.tangem.features.tester.api.TesterRouter
import com.tangem.features.tokendetails.navigation.TokenDetailsRouter
import com.tangem.features.wallet.navigation.WalletRouter
import com.tangem.tap.domain.walletconnect2.domain.WalletConnectInteractor
import com.tangem.tap.domain.walletconnect2.domain.LegacyWalletConnectRepository
import com.tangem.tap.domain.walletconnect2.domain.WalletConnectInteractor
import com.tangem.tap.domain.walletconnect2.domain.WalletConnectSessionsRepository
import com.tangem.tap.features.customtoken.api.featuretoggles.CustomTokenFeatureToggles
import com.tangem.tap.proxy.AppStateHolder
@ -78,5 +84,11 @@ data class DaggerGraphState(
val saveBlockchainErrorUseCase: SaveBlockchainErrorUseCase? = null,
val assetLoader: AssetLoader? = null,
val detailsFeatureToggles: DetailsFeatureToggles? = null,
val detailsEntryPoint: DetailsEntryPoint? = null,
val stakingRouter: StakingRouter? = null,
val urlOpener: UrlOpener? = null,
val shareManager: ShareManager? = null,
val appRouter: AppRouter? = null,
val disclaimerRouter: DisclaimerRouter? = null,
val pushNotificationsFeatureToggles: PushNotificationsFeatureToggles? = null,
val pushNotificationsRouter: PushNotificationsRouter? = null,
) : StateType