Updated on 2026-08-14
This commit is contained in:
commit
da4a98c4f2
475 changed files with 9814 additions and 4216 deletions
|
|
@ -22,6 +22,9 @@ android {
|
|||
resources.excludes.add("META-INF/LICENSE.md")
|
||||
resources.excludes.add("META-INF/NOTICE.md")
|
||||
}
|
||||
androidResources {
|
||||
generateLocaleConfig = true
|
||||
}
|
||||
}
|
||||
|
||||
configurations.all {
|
||||
|
|
@ -87,6 +90,7 @@ dependencies {
|
|||
implementation(projects.libs.crypto)
|
||||
implementation(projects.libs.auth)
|
||||
implementation(projects.libs.blockchainSdk)
|
||||
implementation(projects.libs.tangemSdkApi)
|
||||
|
||||
implementation(projects.data.appCurrency)
|
||||
implementation(projects.data.appTheme)
|
||||
|
|
@ -143,6 +147,10 @@ dependencies {
|
|||
implementation(projects.features.walletSettings.impl)
|
||||
implementation(projects.features.markets.api)
|
||||
implementation(projects.features.markets.impl)
|
||||
implementation(projects.features.onramp.api)
|
||||
implementation(projects.features.onramp.impl)
|
||||
implementation(projects.features.onboardingV2.api)
|
||||
implementation(projects.features.onboardingV2.impl)
|
||||
|
||||
/** AndroidX libraries */
|
||||
implementation(deps.androidx.core.ktx)
|
||||
|
|
|
|||
|
|
@ -1,16 +1,22 @@
|
|||
package com.tangem.common
|
||||
|
||||
import android.Manifest
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import androidx.compose.ui.test.junit4.createAndroidComposeRule
|
||||
import androidx.test.espresso.intent.Intents
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.rule.GrantPermissionRule
|
||||
import com.kaspersky.components.composesupport.config.withComposeSupport
|
||||
import com.kaspersky.kaspresso.kaspresso.Kaspresso
|
||||
import com.kaspersky.kaspresso.testcases.api.testcase.TestCase
|
||||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||
import com.tangem.tap.MainActivity
|
||||
import com.tangem.tap.domain.sdk.TangemSdkManager
|
||||
import dagger.hilt.android.testing.HiltAndroidRule
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Rule
|
||||
import org.junit.rules.RuleChain
|
||||
import org.junit.runner.RunWith
|
||||
|
|
@ -24,6 +30,9 @@ abstract class BaseTestCase : TestCase(
|
|||
@Inject
|
||||
lateinit var tangemSdkManager: TangemSdkManager
|
||||
|
||||
@Inject
|
||||
lateinit var appPreferencesStore: AppPreferencesStore
|
||||
|
||||
@get:Rule
|
||||
open val composeTestRule = createAndroidComposeRule<MainActivity>()
|
||||
|
||||
|
|
@ -48,9 +57,22 @@ abstract class BaseTestCase : TestCase(
|
|||
hiltRule.inject()
|
||||
Intents.init()
|
||||
additionalBeforeSection()
|
||||
|
||||
runBlocking {
|
||||
delay(INIT_DELAY)
|
||||
}
|
||||
|
||||
}.after {
|
||||
runBlocking {
|
||||
appPreferencesStore.editData { prefs -> prefs.clear() }
|
||||
}
|
||||
|
||||
additionalAfterSection()
|
||||
Intents.release()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val INIT_DELAY = 1000L
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -143,9 +143,6 @@ class DetailsScreenTest : BaseTestCase() {
|
|||
}
|
||||
}
|
||||
ComposeScreen.onComposeScreen<WalletSettingsTestScreen>(composeTestRule) {
|
||||
step("Assert Link more cards button does not exist") {
|
||||
linkMoreCardsButton.assertIsNotDisplayed()
|
||||
}
|
||||
step("Assert Card Settings button is visible") {
|
||||
cardSettingsButton.assertIsDisplayed()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.tests
|
||||
|
||||
import android.content.Intent.ACTION_VIEW
|
||||
import androidx.test.espresso.intent.matcher.UriMatchers
|
||||
import com.tangem.common.BaseTestCase
|
||||
import com.tangem.common.extensions.clickWithAssertion
|
||||
import com.tangem.screens.DisclaimerTestScreen
|
||||
|
|
@ -9,6 +10,7 @@ import com.tangem.tap.features.home.redux.HomeMiddleware.NEW_BUY_WALLET_URL
|
|||
import dagger.hilt.android.testing.HiltAndroidTest
|
||||
import io.github.kakaocup.compose.node.element.ComposeScreen
|
||||
import io.github.kakaocup.kakao.intent.KIntent
|
||||
import org.hamcrest.Matchers
|
||||
import org.junit.Test
|
||||
|
||||
@HiltAndroidTest
|
||||
|
|
@ -29,7 +31,7 @@ class StoriesTest : BaseTestCase() {
|
|||
step("Assert: browser opened") {
|
||||
val expectedIntent = KIntent {
|
||||
hasAction(ACTION_VIEW)
|
||||
hasData(NEW_BUY_WALLET_URL)
|
||||
hasData { toString().startsWith(NEW_BUY_WALLET_URL) }
|
||||
}
|
||||
expectedIntent.intended()
|
||||
device.uiDevice.pressBack()
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit cf01c91626bf58bdf6895c59a706b83c37a9e345
|
||||
Subproject commit adbdabe422b0513640d1750f276298683d342f61
|
||||
|
|
@ -748,6 +748,16 @@
|
|||
"networkId": "core/test"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "casper-network",
|
||||
"name": "Casper",
|
||||
"symbol": "CSPR",
|
||||
"networks": [
|
||||
{
|
||||
"networkId": "casper-network/test"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ import com.tangem.core.analytics.filter.OneTimeEventFilter
|
|||
import com.tangem.core.featuretoggle.manager.FeatureTogglesManager
|
||||
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.datasource.local.config.environment.EnvironmentConfigStorage
|
||||
import com.tangem.datasource.local.config.issuers.IssuersConfigStorage
|
||||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||
import com.tangem.domain.appcurrency.repository.AppCurrencyRepository
|
||||
import com.tangem.domain.apptheme.GetAppThemeModeUseCase
|
||||
|
|
@ -19,21 +19,19 @@ import com.tangem.domain.balancehiding.repositories.BalanceHidingRepository
|
|||
import com.tangem.domain.card.ScanCardProcessor
|
||||
import com.tangem.domain.card.repository.CardRepository
|
||||
import com.tangem.domain.feedback.GetCardInfoUseCase
|
||||
import com.tangem.domain.feedback.SaveBlockchainErrorUseCase
|
||||
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
||||
import com.tangem.domain.onboarding.SaveTwinsOnboardingShownUseCase
|
||||
import com.tangem.domain.onboarding.WasTwinsOnboardingShownUseCase
|
||||
import com.tangem.domain.settings.repositories.SettingsRepository
|
||||
import com.tangem.domain.settings.usercountry.GetUserCountryUseCase
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.wallets.repository.WalletsRepository
|
||||
import com.tangem.domain.wallets.usecase.GenerateWalletNameUseCase
|
||||
import com.tangem.features.onboarding.v2.OnboardingV2FeatureToggles
|
||||
import com.tangem.features.onramp.OnrampFeatureToggles
|
||||
import com.tangem.tap.common.log.TangemAppLoggerInitializer
|
||||
import com.tangem.tap.domain.scanCard.CardScanningFeatureToggles
|
||||
import com.tangem.tap.domain.walletconnect2.domain.WalletConnectSessionsRepository
|
||||
import com.tangem.tap.features.home.featuretoggles.HomeFeatureToggles
|
||||
import com.tangem.tap.proxy.AppStateHolder
|
||||
import dagger.hilt.EntryPoint
|
||||
|
|
@ -50,7 +48,7 @@ interface ApplicationEntryPoint {
|
|||
|
||||
fun getAppStateHolder(): AppStateHolder
|
||||
|
||||
fun getAssetLoader(): AssetLoader
|
||||
fun getIssuersConfigStorage(): IssuersConfigStorage
|
||||
|
||||
fun getFeatureTogglesManager(): FeatureTogglesManager
|
||||
|
||||
|
|
@ -60,18 +58,12 @@ interface ApplicationEntryPoint {
|
|||
|
||||
fun getWalletConnect2Repository(): WalletConnect2Repository
|
||||
|
||||
fun getWalletConnectSessionsRepository(): WalletConnectSessionsRepository
|
||||
|
||||
fun getScanCardProcessor(): ScanCardProcessor
|
||||
|
||||
fun getAppCurrencyRepository(): AppCurrencyRepository
|
||||
|
||||
fun getWalletManagersFacade(): WalletManagersFacade
|
||||
|
||||
fun getNetworksRepository(): NetworksRepository
|
||||
|
||||
fun getCurrenciesRepository(): CurrenciesRepository
|
||||
|
||||
fun getAppThemeModeRepository(): AppThemeModeRepository
|
||||
|
||||
fun getBalanceHidingRepository(): BalanceHidingRepository
|
||||
|
|
@ -102,8 +94,6 @@ interface ApplicationEntryPoint {
|
|||
|
||||
fun getSendFeedbackEmailUseCase(): SendFeedbackEmailUseCase
|
||||
|
||||
fun getSaveBlockchainErrorUseCase(): SaveBlockchainErrorUseCase
|
||||
|
||||
fun getGetCardInfoUseCase(): GetCardInfoUseCase
|
||||
|
||||
fun getUrlOpener(): UrlOpener
|
||||
|
|
@ -119,4 +109,8 @@ interface ApplicationEntryPoint {
|
|||
fun getHomeFeatureToggles(): HomeFeatureToggles
|
||||
|
||||
fun getGetUserCountryCodeUseCase(): GetUserCountryUseCase
|
||||
|
||||
fun getOnrampFeatureToggles(): OnrampFeatureToggles
|
||||
|
||||
fun getOnboardingV2FeatureToggles(): OnboardingV2FeatureToggles
|
||||
}
|
||||
|
|
@ -56,10 +56,10 @@ import com.tangem.features.pushnotifications.api.navigation.PushNotificationsRou
|
|||
import com.tangem.features.pushnotifications.api.utils.PUSH_PERMISSION
|
||||
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.operations.backup.BackupService
|
||||
import com.tangem.sdk.api.TangemSdkManager
|
||||
import com.tangem.sdk.extensions.init
|
||||
import com.tangem.tap.common.ActivityResultCallbackHolder
|
||||
import com.tangem.tap.common.DialogManager
|
||||
|
|
@ -69,7 +69,6 @@ import com.tangem.tap.common.apptheme.MutableAppThemeModeHolder
|
|||
import com.tangem.tap.common.extensions.dispatchNavigationAction
|
||||
import com.tangem.tap.common.extensions.showFragmentAllowingStateLoss
|
||||
import com.tangem.tap.common.redux.NotificationsHandler
|
||||
import com.tangem.tap.domain.sdk.TangemSdkManager
|
||||
import com.tangem.tap.domain.walletconnect2.domain.WalletConnectInteractor
|
||||
import com.tangem.tap.features.intentHandler.IntentProcessor
|
||||
import com.tangem.tap.features.intentHandler.handlers.BackgroundScanIntentHandler
|
||||
|
|
@ -113,9 +112,6 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
|||
lateinit var appStateHolder: AppStateHolder
|
||||
|
||||
/** Router for opening tester menu */
|
||||
@Inject
|
||||
lateinit var testerRouter: TesterRouter
|
||||
|
||||
@Inject
|
||||
lateinit var cardSdkOwner: CardSdkOwner
|
||||
|
||||
|
|
@ -309,17 +305,9 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
|||
|
||||
store.dispatch(
|
||||
DaggerGraphAction.SetActivityDependencies(
|
||||
testerRouter = testerRouter,
|
||||
scanCardUseCase = scanCardUseCase,
|
||||
walletRouter = walletRouter,
|
||||
walletConnectInteractor = walletConnectInteractor,
|
||||
tokenDetailsRouter = tokenDetailsRouter,
|
||||
cardSdkConfigRepository = cardSdkConfigRepository,
|
||||
sendRouter = sendRouter,
|
||||
qrScanningRouter = qrScanningRouter,
|
||||
emailSender = emailSender,
|
||||
stakingRouter = stakingRouter,
|
||||
pushNotificationsRouter = pushNotificationsRouter,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,10 +20,10 @@ import com.tangem.core.analytics.models.Basic.TransactionSent.WalletForm
|
|||
import com.tangem.core.featuretoggle.manager.FeatureTogglesManager
|
||||
import com.tangem.datasource.api.common.MoshiConverter
|
||||
import com.tangem.datasource.api.common.createNetworkLoggingInterceptor
|
||||
import com.tangem.datasource.asset.loader.AssetLoader
|
||||
import com.tangem.datasource.connection.NetworkConnectionManager
|
||||
import com.tangem.datasource.local.config.environment.EnvironmentConfig
|
||||
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage
|
||||
import com.tangem.datasource.local.config.issuers.IssuersConfigStorage
|
||||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||
import com.tangem.domain.appcurrency.repository.AppCurrencyRepository
|
||||
import com.tangem.domain.apptheme.GetAppThemeModeUseCase
|
||||
|
|
@ -33,18 +33,17 @@ import com.tangem.domain.card.ScanCardProcessor
|
|||
import com.tangem.domain.card.repository.CardRepository
|
||||
import com.tangem.domain.common.LogConfig
|
||||
import com.tangem.domain.feedback.GetCardInfoUseCase
|
||||
import com.tangem.domain.feedback.SaveBlockchainErrorUseCase
|
||||
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
||||
import com.tangem.domain.onboarding.SaveTwinsOnboardingShownUseCase
|
||||
import com.tangem.domain.onboarding.WasTwinsOnboardingShownUseCase
|
||||
import com.tangem.domain.settings.repositories.SettingsRepository
|
||||
import com.tangem.domain.settings.usercountry.GetUserCountryUseCase
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.wallets.repository.WalletsRepository
|
||||
import com.tangem.domain.wallets.usecase.GenerateWalletNameUseCase
|
||||
import com.tangem.features.onboarding.v2.OnboardingV2FeatureToggles
|
||||
import com.tangem.features.onramp.OnrampFeatureToggles
|
||||
import com.tangem.tap.common.analytics.AnalyticsFactory
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder
|
||||
import com.tangem.tap.common.analytics.handlers.amplitude.AmplitudeAnalyticsHandler
|
||||
|
|
@ -53,10 +52,8 @@ import com.tangem.tap.common.images.createCoilImageLoader
|
|||
import com.tangem.tap.common.log.TangemAppLoggerInitializer
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.common.redux.appReducer
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.domain.scanCard.CardScanningFeatureToggles
|
||||
import com.tangem.tap.domain.tasks.product.DerivationsFinder
|
||||
import com.tangem.tap.domain.walletconnect2.domain.WalletConnectSessionsRepository
|
||||
import com.tangem.tap.features.home.featuretoggles.HomeFeatureToggles
|
||||
import com.tangem.tap.proxy.AppStateHolder
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
|
|
@ -85,8 +82,8 @@ abstract class TangemApplication : Application(), ImageLoaderFactory {
|
|||
private val environmentConfigStorage: EnvironmentConfigStorage
|
||||
get() = entryPoint.getEnvironmentConfigStorage()
|
||||
|
||||
private val assetLoader: AssetLoader
|
||||
get() = entryPoint.getAssetLoader()
|
||||
private val issuersConfigStorage: IssuersConfigStorage
|
||||
get() = entryPoint.getIssuersConfigStorage()
|
||||
|
||||
private val featureTogglesManager: FeatureTogglesManager
|
||||
get() = entryPoint.getFeatureTogglesManager()
|
||||
|
|
@ -100,9 +97,6 @@ abstract class TangemApplication : Application(), ImageLoaderFactory {
|
|||
private val walletConnect2Repository: WalletConnect2Repository
|
||||
get() = entryPoint.getWalletConnect2Repository()
|
||||
|
||||
private val walletConnectSessionsRepository: WalletConnectSessionsRepository
|
||||
get() = entryPoint.getWalletConnectSessionsRepository()
|
||||
|
||||
private val scanCardProcessor: ScanCardProcessor
|
||||
get() = entryPoint.getScanCardProcessor()
|
||||
|
||||
|
|
@ -112,12 +106,6 @@ abstract class TangemApplication : Application(), ImageLoaderFactory {
|
|||
private val walletManagersFacade: WalletManagersFacade
|
||||
get() = entryPoint.getWalletManagersFacade()
|
||||
|
||||
private val networksRepository: NetworksRepository
|
||||
get() = entryPoint.getNetworksRepository()
|
||||
|
||||
private val currenciesRepository: CurrenciesRepository
|
||||
get() = entryPoint.getCurrenciesRepository()
|
||||
|
||||
private val appThemeModeRepository: AppThemeModeRepository
|
||||
get() = entryPoint.getAppThemeModeRepository()
|
||||
|
||||
|
|
@ -163,9 +151,6 @@ abstract class TangemApplication : Application(), ImageLoaderFactory {
|
|||
private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase
|
||||
get() = entryPoint.getSendFeedbackEmailUseCase()
|
||||
|
||||
private val saveBlockchainErrorUseCase: SaveBlockchainErrorUseCase
|
||||
get() = entryPoint.getSaveBlockchainErrorUseCase()
|
||||
|
||||
private val getCardInfoUseCase: GetCardInfoUseCase
|
||||
get() = entryPoint.getGetCardInfoUseCase()
|
||||
|
||||
|
|
@ -189,6 +174,12 @@ abstract class TangemApplication : Application(), ImageLoaderFactory {
|
|||
|
||||
private val getUserCountryUseCase: GetUserCountryUseCase
|
||||
get() = entryPoint.getGetUserCountryCodeUseCase()
|
||||
|
||||
private val onrampFeatureToggles: OnrampFeatureToggles
|
||||
get() = entryPoint.getOnrampFeatureToggles()
|
||||
|
||||
private val onboardingV2FeatureToggles: OnboardingV2FeatureToggles
|
||||
get() = entryPoint.getOnboardingV2FeatureToggles()
|
||||
// endregion
|
||||
|
||||
override fun onCreate() {
|
||||
|
|
@ -211,10 +202,7 @@ abstract class TangemApplication : Application(), ImageLoaderFactory {
|
|||
runBlocking {
|
||||
featureTogglesManager.init()
|
||||
|
||||
val config = environmentConfigStorage.initialize()
|
||||
store.dispatch(GlobalAction.SetConfigManager(environmentConfigStorage))
|
||||
|
||||
initWithConfigDependency(environmentConfig = config)
|
||||
initWithConfigDependency(environmentConfig = environmentConfigStorage.initialize())
|
||||
}
|
||||
|
||||
loadNativeLibraries()
|
||||
|
|
@ -244,13 +232,10 @@ abstract class TangemApplication : Application(), ImageLoaderFactory {
|
|||
networkConnectionManager = networkConnectionManager,
|
||||
cardScanningFeatureToggles = cardScanningFeatureToggles,
|
||||
walletConnectRepository = walletConnect2Repository,
|
||||
walletConnectSessionsRepository = walletConnectSessionsRepository,
|
||||
scanCardProcessor = scanCardProcessor,
|
||||
appCurrencyRepository = appCurrencyRepository,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
appStateHolder = appStateHolder,
|
||||
networksRepository = networksRepository,
|
||||
currenciesRepository = currenciesRepository,
|
||||
appThemeModeRepository = appThemeModeRepository,
|
||||
balanceHidingRepository = balanceHidingRepository,
|
||||
walletsRepository = walletsRepository,
|
||||
|
|
@ -259,19 +244,20 @@ abstract class TangemApplication : Application(), ImageLoaderFactory {
|
|||
saveTwinsOnboardingShownUseCase = saveTwinsOnboardingShownUseCase,
|
||||
generateWalletNameUseCase = generateWalletNameUseCase,
|
||||
cardRepository = cardRepository,
|
||||
tangemSdkLogger = tangemSdkLogger,
|
||||
settingsRepository = settingsRepository,
|
||||
blockchainSDKFactory = blockchainSDKFactory,
|
||||
saveBlockchainErrorUseCase = saveBlockchainErrorUseCase,
|
||||
sendFeedbackEmailUseCase = sendFeedbackEmailUseCase,
|
||||
getCardInfoUseCase = getCardInfoUseCase,
|
||||
assetLoader = assetLoader,
|
||||
issuersConfigStorage = issuersConfigStorage,
|
||||
urlOpener = urlOpener,
|
||||
shareManager = shareManager,
|
||||
appRouter = appRouter,
|
||||
transactionSignerFactory = transactionSignerFactory,
|
||||
homeFeatureToggles = homeFeatureToggles,
|
||||
getUserCountryUseCase = getUserCountryUseCase,
|
||||
onrampFeatureToggles = onrampFeatureToggles,
|
||||
environmentConfigStorage = environmentConfigStorage,
|
||||
onboardingV2FeatureToggles = onboardingV2FeatureToggles,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.tap.common.analytics.events
|
||||
|
||||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.TOKEN_PARAM
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
@ -17,7 +18,12 @@ sealed class Token(
|
|||
params: Map<String, String> = mapOf(),
|
||||
) : Token("Token / Receive", event, params) {
|
||||
|
||||
class ScreenOpened : Receive("Receive Screen Opened")
|
||||
class ScreenOpened(
|
||||
val token: String,
|
||||
) : Receive(
|
||||
event = "Receive Screen Opened",
|
||||
params = mapOf(TOKEN_PARAM to token),
|
||||
)
|
||||
class ButtonCopyAddress : Receive("Button - Copy Address")
|
||||
class ButtonShareAddress : Receive("Button - Share Address")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ fun Store<*>.dispatchNotification(resId: Int) {
|
|||
dispatchOnMain(GlobalAction.ShowNotification(resId))
|
||||
}
|
||||
|
||||
suspend fun Store<AppState>.onUserWalletSelected(userWallet: UserWallet, sendAnalyticsEvent: Boolean = false) {
|
||||
state.globalState.tapWalletManager.onWalletSelected(userWallet, sendAnalyticsEvent)
|
||||
suspend fun Store<AppState>.onUserWalletSelected(userWallet: UserWallet) {
|
||||
state.globalState.tapWalletManager.onWalletSelected(userWallet)
|
||||
}
|
||||
|
||||
fun Store<*>.dispatchErrorNotification(error: TapError) {
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
package com.tangem.tap.common.feature
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface Feature {
|
||||
fun featureIsSwitchedOn(): Boolean
|
||||
}
|
||||
|
|
@ -2,7 +2,6 @@ package com.tangem.tap.common.redux.global
|
|||
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.redux.StateDialog
|
||||
|
|
@ -74,8 +73,6 @@ sealed class GlobalAction : Action {
|
|||
|
||||
data class IsSignWithRing(val isSignWithRing: Boolean) : GlobalAction()
|
||||
|
||||
data class SetConfigManager(val environmentConfigStorage: EnvironmentConfigStorage) : GlobalAction()
|
||||
|
||||
object ExchangeManager : GlobalAction() {
|
||||
object Init : GlobalAction() {
|
||||
data class Success(
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import com.tangem.domain.models.scan.ScanResponse
|
|||
import com.tangem.domain.redux.StateDialog
|
||||
import com.tangem.tap.common.extensions.*
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.network.exchangeServices.BuyExchangeService
|
||||
import com.tangem.tap.network.exchangeServices.CardExchangeRules
|
||||
import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager
|
||||
import com.tangem.tap.network.exchangeServices.ExchangeService
|
||||
|
|
@ -56,8 +55,7 @@ private fun handleAction(action: Action, appState: () -> AppState?) {
|
|||
restoreAppCurrency()
|
||||
}
|
||||
is GlobalAction.ExchangeManager.Init -> {
|
||||
val appStateSafe = appState() ?: return
|
||||
val config = appStateSafe.globalState.environmentConfigStorage?.getConfigSync() ?: return
|
||||
val config = store.inject(DaggerGraphState::environmentConfigStorage).getConfigSync()
|
||||
|
||||
scope.launch {
|
||||
val scanResponseProvider: () -> ScanResponse? = {
|
||||
|
|
@ -149,15 +147,10 @@ private fun makeSellExchangeService(environmentConfig: EnvironmentConfig): Excha
|
|||
}
|
||||
|
||||
private fun makeBuyExchangeService(environmentConfig: EnvironmentConfig): ExchangeService {
|
||||
return BuyExchangeService(
|
||||
mercuryoService = makeMercuryoExchangeService(environmentConfig),
|
||||
return MercuryoService(
|
||||
environment = MercuryoEnvironment.prod(
|
||||
widgetId = environmentConfig.mercuryoWidgetId,
|
||||
secret = environmentConfig.mercuryoSecret,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun makeMercuryoExchangeService(environmentConfig: EnvironmentConfig): MercuryoService {
|
||||
val mercuryoEnvironment = MercuryoEnvironment.prod(
|
||||
environmentConfig.mercuryoWidgetId,
|
||||
environmentConfig.mercuryoSecret,
|
||||
)
|
||||
return MercuryoService(mercuryoEnvironment)
|
||||
}
|
||||
|
|
@ -47,9 +47,6 @@ fun globalReducer(action: Action, state: AppState, appStateHolder: AppStateHolde
|
|||
is GlobalAction.RestoreAppCurrency.Success -> {
|
||||
globalState.copy(appCurrency = action.appCurrency)
|
||||
}
|
||||
is GlobalAction.SetConfigManager -> {
|
||||
globalState.copy(environmentConfigStorage = action.environmentConfigStorage)
|
||||
}
|
||||
is GlobalAction.UpdateWalletSignedHashes -> {
|
||||
val card = globalState.scanResponse?.card ?: return globalState
|
||||
val wallet = card.wallets
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.tangem.tap.common.redux.global
|
||||
|
||||
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.apptheme.model.AppThemeMode
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
|
|
@ -16,7 +15,6 @@ data class GlobalState(
|
|||
val onboardingState: OnboardingState = OnboardingState(),
|
||||
val cardVerifiedOnline: Boolean = false,
|
||||
val tapWalletManager: TapWalletManager = TapWalletManager(),
|
||||
val environmentConfigStorage: EnvironmentConfigStorage? = null,
|
||||
val appCurrency: AppCurrency = AppCurrency.Default,
|
||||
val scanCardFailsCounter: Int = 0,
|
||||
val dialog: StateDialog? = null,
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ internal class AddressInfoBottomSheetDialog(
|
|||
|
||||
override fun show() {
|
||||
super.show()
|
||||
Analytics.send(Token.Receive.ScreenOpened())
|
||||
Analytics.send(Token.Receive.ScreenOpened(stateDialog.currency.currencySymbol))
|
||||
showData(data = stateDialog.addressData)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ import com.tangem.domain.exchange.RampStateManager
|
|||
import com.tangem.domain.tokens.GetPolkadotCheckHasImmortalUseCase
|
||||
import com.tangem.domain.tokens.GetPolkadotCheckHasResetUseCase
|
||||
import com.tangem.domain.tokens.repository.PolkadotAccountHealthCheckRepository
|
||||
import com.tangem.sdk.api.TangemSdkManager
|
||||
import com.tangem.tap.domain.scanCard.repository.DefaultScanCardRepository
|
||||
import com.tangem.tap.domain.sdk.TangemSdkManager
|
||||
import com.tangem.tap.network.exchangeServices.DefaultRampManager
|
||||
import com.tangem.tap.proxy.AppStateHolder
|
||||
import dagger.Module
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ package com.tangem.tap.di
|
|||
import android.content.Context
|
||||
import com.tangem.domain.card.BuildConfig
|
||||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.sdk.api.TangemSdkManager
|
||||
import com.tangem.tap.domain.sdk.impl.DefaultTangemSdkManager
|
||||
import com.tangem.tap.domain.sdk.impl.MockTangemSdkManager
|
||||
import com.tangem.tap.domain.sdk.TangemSdkManager
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package com.tangem.tap.di.data
|
|||
|
||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.card.repository.DerivationsRepository
|
||||
import com.tangem.tap.domain.sdk.TangemSdkManager
|
||||
import com.tangem.sdk.api.TangemSdkManager
|
||||
import com.tangem.tap.domain.card.DefaultDerivationsRepository
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.Module
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@ import com.tangem.domain.demo.IsDemoCardUseCase
|
|||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.wallets.usecase.IsNeedToBackupUseCase
|
||||
import com.tangem.sdk.api.TangemSdkManager
|
||||
import com.tangem.tap.domain.card.DefaultDeleteSavedAccessCodesUseCase
|
||||
import com.tangem.tap.domain.card.DefaultResetCardUseCase
|
||||
import com.tangem.tap.domain.sdk.TangemSdkManager
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import com.tangem.domain.settings.repositories.PromoSettingsRepository
|
|||
import com.tangem.domain.settings.repositories.SettingsRepository
|
||||
import com.tangem.domain.settings.usercountry.FetchUserCountryUseCase
|
||||
import com.tangem.domain.settings.usercountry.GetUserCountryUseCase
|
||||
import com.tangem.tap.domain.sdk.TangemSdkManager
|
||||
import com.tangem.sdk.api.TangemSdkManager
|
||||
import com.tangem.tap.domain.settings.DefaultLegacySettingsRepository
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
package com.tangem.tap.di.domain
|
||||
|
||||
import com.tangem.domain.staking.*
|
||||
import com.tangem.domain.staking.repositories.StakingErrorResolver
|
||||
import com.tangem.domain.staking.repositories.StakingPendingTransactionRepository
|
||||
import com.tangem.domain.staking.repositories.StakingRepository
|
||||
import com.tangem.domain.staking.repositories.StakingTransactionHashRepository
|
||||
import com.tangem.domain.staking.repositories.*
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
|
|
@ -51,6 +48,32 @@ internal object StakingDomainModule {
|
|||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideFetchActionsUseCase(
|
||||
stakingRepository: StakingRepository,
|
||||
stakingActionRepository: StakingActionRepository,
|
||||
stakingErrorResolver: StakingErrorResolver,
|
||||
): FetchActionsUseCase {
|
||||
return FetchActionsUseCase(
|
||||
stakingRepository = stakingRepository,
|
||||
stakingActionRepository = stakingActionRepository,
|
||||
stakingErrorResolver = stakingErrorResolver,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideGetActionsUseCase(
|
||||
stakingActionRepository: StakingActionRepository,
|
||||
stakingErrorResolver: StakingErrorResolver,
|
||||
): GetActionsUseCase {
|
||||
return GetActionsUseCase(
|
||||
stakingActionRepository = stakingActionRepository,
|
||||
stakingErrorResolver = stakingErrorResolver,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideGetStakingTokensUseCase(
|
||||
|
|
@ -123,38 +146,12 @@ internal object StakingDomainModule {
|
|||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideSavePendingTransactionUseCase(
|
||||
stakingPendingTransactionRepository: StakingPendingTransactionRepository,
|
||||
stakingErrorResolver: StakingErrorResolver,
|
||||
): SavePendingTransactionUseCase {
|
||||
return SavePendingTransactionUseCase(
|
||||
stakingPendingTransactionRepository = stakingPendingTransactionRepository,
|
||||
stakingErrorResolver = stakingErrorResolver,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideInvalidatePendingTransactionsUseCase(
|
||||
stakingPendingTransactionRepository: StakingPendingTransactionRepository,
|
||||
stakingErrorResolver: StakingErrorResolver,
|
||||
): InvalidatePendingTransactionsUseCase {
|
||||
return InvalidatePendingTransactionsUseCase(
|
||||
stakingPendingTransactionRepository = stakingPendingTransactionRepository,
|
||||
stakingErrorResolver = stakingErrorResolver,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideGetPendingTransactionsUseCase(
|
||||
stakingPendingTransactionRepository: StakingPendingTransactionRepository,
|
||||
stakingErrorResolver: StakingErrorResolver,
|
||||
): GetStakingPendingTransactionsUseCase {
|
||||
return GetStakingPendingTransactionsUseCase(
|
||||
stakingPendingTransactionRepository = stakingPendingTransactionRepository,
|
||||
stakingErrorResolver = stakingErrorResolver,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import com.tangem.domain.tokens.*
|
|||
import com.tangem.domain.tokens.repository.*
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.feature.swap.domain.api.SwapRepository
|
||||
import com.tangem.features.markets.MarketsFeatureToggles
|
||||
import com.tangem.features.staking.api.featuretoggles.StakingFeatureToggles
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.Module
|
||||
|
|
@ -68,17 +67,6 @@ internal object TokensDomainModule {
|
|||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideGetCardTokensListUseCase(
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
quotesRepository: QuotesRepository,
|
||||
networksRepository: NetworksRepository,
|
||||
stakingRepository: StakingRepository,
|
||||
): GetNodlTokenListUseCase {
|
||||
return GetNodlTokenListUseCase(currenciesRepository, quotesRepository, networksRepository, stakingRepository)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideRemoveCurrencyUseCase(
|
||||
|
|
@ -234,7 +222,6 @@ internal object TokensDomainModule {
|
|||
networksRepository: NetworksRepository,
|
||||
stakingRepository: StakingRepository,
|
||||
stakingFeatureToggles: StakingFeatureToggles,
|
||||
marketsFeatureToggles: MarketsFeatureToggles,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): GetCryptoCurrencyActionsUseCase {
|
||||
return GetCryptoCurrencyActionsUseCase(
|
||||
|
|
@ -246,7 +233,6 @@ internal object TokensDomainModule {
|
|||
networksRepository = networksRepository,
|
||||
stakingRepository = stakingRepository,
|
||||
stakingFeatureToggles = stakingFeatureToggles,
|
||||
marketsFeatureToggles = marketsFeatureToggles,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
}
|
||||
|
|
@ -287,6 +273,16 @@ internal object TokensDomainModule {
|
|||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideGetMinimumTransactionAmountSyncUseCase(
|
||||
currencyChecksRepository: CurrencyChecksRepository,
|
||||
): GetMinimumTransactionAmountSyncUseCase {
|
||||
return GetMinimumTransactionAmountSyncUseCase(
|
||||
currencyChecksRepository = currencyChecksRepository,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideIsCryptoCurrencyCoinCouldHideUseCase(
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package com.tangem.tap.domain
|
|||
import com.tangem.blockchain.common.Token
|
||||
import com.tangem.blockchain.common.Wallet
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.core.analytics.models.Basic
|
||||
import com.tangem.domain.common.extensions.withMainContext
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.operations.attestation.Attestation
|
||||
|
|
@ -28,19 +27,16 @@ class TapWalletManager(
|
|||
field = value
|
||||
}
|
||||
|
||||
suspend fun onWalletSelected(userWallet: UserWallet, sendAnalyticsEvent: Boolean) {
|
||||
suspend fun onWalletSelected(userWallet: UserWallet) {
|
||||
// If a previous job was running, it gets cancelled before the new one starts,
|
||||
// ensuring that only one job is active at any given time.
|
||||
loadUserWalletDataJob = CoroutineScope(dispatchers.io)
|
||||
.launch { loadUserWalletData(userWallet, sendAnalyticsEvent) }
|
||||
.launch { loadUserWalletData(userWallet) }
|
||||
.also { it.join() }
|
||||
}
|
||||
|
||||
private suspend fun loadUserWalletData(userWallet: UserWallet, sendAnalyticsEvent: Boolean) {
|
||||
private suspend fun loadUserWalletData(userWallet: UserWallet) {
|
||||
Analytics.setContext(userWallet.scanResponse)
|
||||
if (sendAnalyticsEvent) {
|
||||
Analytics.send(Basic.WalletOpened())
|
||||
}
|
||||
val scanResponse = userWallet.scanResponse
|
||||
val card = scanResponse.card
|
||||
val attestationFailed = card.attestation.status == Attestation.Status.Failed
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import arrow.core.right
|
|||
import com.tangem.common.doOnFailure
|
||||
import com.tangem.common.doOnSuccess
|
||||
import com.tangem.domain.card.DeleteSavedAccessCodesUseCase
|
||||
import com.tangem.tap.domain.sdk.TangemSdkManager
|
||||
import com.tangem.sdk.api.TangemSdkManager
|
||||
|
||||
internal class DefaultDeleteSavedAccessCodesUseCase(
|
||||
private val tangemSdkManager: TangemSdkManager,
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import com.tangem.domain.tokens.model.Network
|
|||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.operations.derivation.ExtendedPublicKeysMap
|
||||
import com.tangem.tap.domain.sdk.TangemSdkManager
|
||||
import com.tangem.sdk.api.TangemSdkManager
|
||||
import com.tangem.tap.domain.tasks.UserWalletIdPreflightReadFilter
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.withContext
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import com.tangem.domain.card.ResetCardUseCase
|
|||
import com.tangem.domain.card.ResetCardUserCodeParams
|
||||
import com.tangem.domain.card.models.ResetCardError
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.tap.domain.sdk.TangemSdkManager
|
||||
import com.tangem.sdk.api.TangemSdkManager
|
||||
|
||||
internal class DefaultResetCardUseCase(
|
||||
private val tangemSdkManager: TangemSdkManager,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package com.tangem.tap.domain.scanCard.repository
|
|||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.domain.card.repository.ScanCardRepository
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.tap.domain.sdk.TangemSdkManager
|
||||
import com.tangem.sdk.api.TangemSdkManager
|
||||
import com.tangem.tap.domain.scanCard.utils.ScanCardExceptionConverter
|
||||
|
||||
// TODO: Move to the :data:card module
|
||||
|
|
|
|||
|
|
@ -32,8 +32,9 @@ import com.tangem.operations.pins.SetUserCodeCommand
|
|||
import com.tangem.operations.preflightread.PreflightReadFilter
|
||||
import com.tangem.operations.usersetttings.SetUserCodeRecoveryAllowedTask
|
||||
import com.tangem.operations.wallet.CreateWalletResponse
|
||||
import com.tangem.sdk.api.CreateProductWalletTaskResponse
|
||||
import com.tangem.sdk.api.TangemSdkManager
|
||||
import com.tangem.tap.derivationsFinder
|
||||
import com.tangem.tap.domain.sdk.TangemSdkManager
|
||||
import com.tangem.tap.domain.tasks.product.*
|
||||
import com.tangem.tap.domain.twins.CreateFirstTwinWalletTask
|
||||
import com.tangem.tap.domain.twins.CreateSecondTwinWalletTask
|
||||
|
|
|
|||
|
|
@ -20,9 +20,9 @@ import com.tangem.domain.wallets.models.UserWalletId
|
|||
import com.tangem.operations.derivation.DerivationTaskResponse
|
||||
import com.tangem.operations.preflightread.PreflightReadFilter
|
||||
import com.tangem.operations.wallet.CreateWalletResponse
|
||||
import com.tangem.tap.domain.sdk.TangemSdkManager
|
||||
import com.tangem.sdk.api.CreateProductWalletTaskResponse
|
||||
import com.tangem.sdk.api.TangemSdkManager
|
||||
import com.tangem.tap.domain.sdk.mocks.MockProvider
|
||||
import com.tangem.tap.domain.tasks.product.CreateProductWalletTaskResponse
|
||||
|
||||
@Suppress("TooManyFunctions")
|
||||
class MockTangemSdkManager(
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import com.tangem.domain.models.scan.CardDTO
|
|||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.operations.derivation.DerivationTaskResponse
|
||||
import com.tangem.operations.wallet.CreateWalletResponse
|
||||
import com.tangem.tap.domain.tasks.product.CreateProductWalletTaskResponse
|
||||
import com.tangem.sdk.api.CreateProductWalletTaskResponse
|
||||
|
||||
interface MockContent {
|
||||
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@ import com.tangem.common.CompletionResult
|
|||
import com.tangem.common.core.TangemError
|
||||
import com.tangem.common.core.TangemSdkError
|
||||
import com.tangem.domain.models.scan.ProductType
|
||||
import com.tangem.sdk.api.CreateProductWalletTaskResponse
|
||||
import com.tangem.tap.domain.sdk.mocks.content.NoteMockContent
|
||||
import com.tangem.tap.domain.sdk.mocks.content.WalletMockContent
|
||||
import com.tangem.tap.domain.sdk.mocks.content.Wallet2MockContent
|
||||
import com.tangem.tap.domain.tasks.product.CreateProductWalletTaskResponse
|
||||
|
||||
object MockProvider {
|
||||
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ import com.tangem.domain.models.scan.ScanResponse
|
|||
import com.tangem.operations.attestation.Attestation
|
||||
import com.tangem.operations.derivation.DerivationTaskResponse
|
||||
import com.tangem.operations.wallet.CreateWalletResponse
|
||||
import com.tangem.sdk.api.CreateProductWalletTaskResponse
|
||||
import com.tangem.tap.domain.sdk.mocks.MockContent
|
||||
import com.tangem.tap.domain.tasks.product.CreateProductWalletTaskResponse
|
||||
import java.util.Date
|
||||
|
||||
object NoteMockContent : MockContent {
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ import com.tangem.operations.backup.PrimaryCard
|
|||
import com.tangem.operations.derivation.DerivationTaskResponse
|
||||
import com.tangem.operations.derivation.ExtendedPublicKeysMap
|
||||
import com.tangem.operations.wallet.CreateWalletResponse
|
||||
import com.tangem.sdk.api.CreateProductWalletTaskResponse
|
||||
import com.tangem.tap.domain.sdk.mocks.MockContent
|
||||
import com.tangem.tap.domain.tasks.product.CreateProductWalletTaskResponse
|
||||
import java.util.Date
|
||||
|
||||
object Wallet2MockContent : MockContent {
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ import com.tangem.operations.backup.PrimaryCard
|
|||
import com.tangem.operations.derivation.DerivationTaskResponse
|
||||
import com.tangem.operations.derivation.ExtendedPublicKeysMap
|
||||
import com.tangem.operations.wallet.CreateWalletResponse
|
||||
import com.tangem.sdk.api.CreateProductWalletTaskResponse
|
||||
import com.tangem.tap.domain.sdk.mocks.MockContent
|
||||
import com.tangem.tap.domain.tasks.product.CreateProductWalletTaskResponse
|
||||
import java.util.Date
|
||||
|
||||
object WalletMockContent : MockContent {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package com.tangem.tap.domain.settings
|
||||
|
||||
import com.tangem.domain.settings.repositories.LegacySettingsRepository
|
||||
import com.tangem.tap.domain.sdk.TangemSdkManager
|
||||
import com.tangem.sdk.api.TangemSdkManager
|
||||
|
||||
internal class DefaultLegacySettingsRepository(
|
||||
private val tangemSdkManager: TangemSdkManager,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package com.tangem.tap.domain.tasks.product
|
|||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.common.card.Card
|
||||
import com.tangem.common.card.EllipticCurve
|
||||
import com.tangem.common.card.FirmwareVersion
|
||||
import com.tangem.common.core.CardSession
|
||||
|
|
@ -19,33 +18,15 @@ import com.tangem.domain.common.DerivationStyleProvider
|
|||
import com.tangem.domain.common.TapWorkarounds.isTestCard
|
||||
import com.tangem.domain.common.configs.CardConfig
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
import com.tangem.domain.models.scan.KeyWalletPublicKey
|
||||
import com.tangem.operations.CommandResponse
|
||||
import com.tangem.operations.backup.PrimaryCard
|
||||
import com.tangem.operations.backup.StartPrimaryCardLinkingCommand
|
||||
import com.tangem.operations.derivation.DeriveMultipleWalletPublicKeysTask
|
||||
import com.tangem.operations.derivation.ExtendedPublicKeysMap
|
||||
import com.tangem.operations.read.ReadWalletsListCommand
|
||||
import com.tangem.operations.wallet.CreateWalletTask
|
||||
import com.tangem.sdk.api.CreateProductWalletTaskResponse
|
||||
import com.tangem.tap.features.demo.DemoHelper
|
||||
import com.tangem.operations.wallet.CreateWalletResponse as SdkCreateWalletResponse
|
||||
|
||||
data class CreateProductWalletTaskResponse(
|
||||
val card: CardDTO,
|
||||
val derivedKeys: Map<KeyWalletPublicKey, ExtendedPublicKeysMap> = mapOf(),
|
||||
val primaryCard: PrimaryCard? = null,
|
||||
) : CommandResponse {
|
||||
constructor(
|
||||
card: Card,
|
||||
derivedKeys: Map<KeyWalletPublicKey, ExtendedPublicKeysMap> = mapOf(),
|
||||
primaryCard: PrimaryCard? = null,
|
||||
) : this(
|
||||
card = CardDTO(card),
|
||||
derivedKeys = derivedKeys,
|
||||
primaryCard = primaryCard,
|
||||
)
|
||||
}
|
||||
|
||||
private data class CreateWalletResponse(
|
||||
val cardId: String,
|
||||
val wallet: CardDTO.Wallet,
|
||||
|
|
|
|||
|
|
@ -13,17 +13,19 @@ import com.tangem.tap.common.extensions.inject
|
|||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.tap.tangemSdkManager
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
class TwinCardsManager(card: CardDTO) {
|
||||
|
||||
private val issuersConfigStorage by lazy(mode = LazyThreadSafetyMode.NONE) {
|
||||
store.inject(DaggerGraphState::issuersConfigStorage)
|
||||
}
|
||||
|
||||
private val firstCardId: String = card.cardId
|
||||
private val publicKey: String = card.issuer.publicKey.toHexString()
|
||||
|
||||
private var currentCardPublicKey: String? = null
|
||||
private var secondCardPublicKey: String? = null
|
||||
|
||||
private val issuerKeyPairFlow = MutableStateFlow<KeyPair?>(value = null)
|
||||
|
||||
suspend fun createFirstWallet(message: Message): CompletionResult<CreateWalletResponse> {
|
||||
val response = tangemSdkManager.createFirstTwinWallet(cardId = firstCardId, initialMessage = message)
|
||||
|
||||
|
|
@ -70,23 +72,11 @@ class TwinCardsManager(card: CardDTO) {
|
|||
}
|
||||
|
||||
private suspend fun getIssuerKeys(): KeyPair {
|
||||
issuerKeyPairFlow.value?.let { return it }
|
||||
|
||||
val assetLoader = store.inject(DaggerGraphState::assetLoader)
|
||||
val issuer = assetLoader.loadList<Issuer>(fileName = ISSUERS_FILE_NAME)
|
||||
.first { it.publicKey == publicKey }
|
||||
val issuer = issuersConfigStorage.getConfig().first { it.publicKey == publicKey }
|
||||
|
||||
return KeyPair(
|
||||
publicKey = issuer.publicKey.hexToBytes(),
|
||||
privateKey = issuer.privateKey.hexToBytes(),
|
||||
).also {
|
||||
issuerKeyPairFlow.value = it
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val ISSUERS_FILE_NAME = "tangem-app-config/issuers"
|
||||
}
|
||||
}
|
||||
|
||||
private class Issuer(val privateKey: String, val publicKey: String)
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import com.tangem.blockchain.common.Blockchain
|
|||
import com.tangem.blockchainsdk.utils.fromNetworkId
|
||||
import com.tangem.blockchainsdk.utils.toNetworkId
|
||||
import com.tangem.tap.domain.walletconnect2.domain.WcBlockchainHelper
|
||||
import com.tangem.tap.domain.walletconnect2.domain.models.Account
|
||||
import com.tangem.tap.domain.walletconnect2.toggles.WalletConnectFeatureToggles
|
||||
|
||||
internal class TangemWcBlockchainHelper(
|
||||
|
|
@ -23,6 +24,12 @@ internal class TangemWcBlockchainHelper(
|
|||
return blockchain?.toNetworkId()
|
||||
}
|
||||
|
||||
override fun chainIdsToBlockchains(chainIds: List<String>): List<Blockchain> {
|
||||
return chainIds.mapNotNull {
|
||||
it.parseId()?.chainIdToBlockchain()
|
||||
}.distinct()
|
||||
}
|
||||
|
||||
override fun chainIdToMissingNetworkNameOrNull(chainId: String): String? {
|
||||
val parsedId = chainId.parseId() ?: return null
|
||||
val blockchain = parsedId.chainIdToBlockchain()
|
||||
|
|
@ -35,11 +42,12 @@ internal class TangemWcBlockchainHelper(
|
|||
}
|
||||
}
|
||||
|
||||
override fun networkIdToChainIdOrNull(networkId: String): String? {
|
||||
override fun networkIdToChainIdOrNull(networkId: String): List<String> {
|
||||
val blockchain = Blockchain.fromNetworkId(networkId)
|
||||
val namespace = blockchain?.getCaip2Namespace() ?: return null
|
||||
val chainId = blockchain.getCaip2ChainId() ?: return null
|
||||
return "$namespace$CHAIN_SEPARATOR$chainId"
|
||||
val namespace = blockchain?.getCaip2Namespace() ?: return emptyList()
|
||||
return blockchain.getCaip2ChainIds().map {
|
||||
"$namespace$CHAIN_SEPARATOR$it"
|
||||
}
|
||||
}
|
||||
|
||||
override fun getNamespaceFromFullChainIdOrNull(chainId: String): String? {
|
||||
|
|
@ -52,8 +60,18 @@ internal class TangemWcBlockchainHelper(
|
|||
return Blockchain.fromNetworkId(networkId)?.fullName
|
||||
}
|
||||
|
||||
private fun Blockchain.getCaip2ChainId(): String? {
|
||||
if (this.isEvm()) return this.getChainId()?.toString()
|
||||
override fun chainIdsToAccounts(
|
||||
walletAddress: String,
|
||||
chainIds: List<String>,
|
||||
derivationPath: String?,
|
||||
): List<Account> {
|
||||
return chainIds.map { chainId ->
|
||||
Account(chainId, walletAddress, derivationPath)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Blockchain.getCaip2ChainIds(): List<String> {
|
||||
if (this.isEvm()) return listOfNotNull(this.getChainId()?.toString())
|
||||
|
||||
return when (this) {
|
||||
/*
|
||||
|
|
@ -61,13 +79,12 @@ internal class TangemWcBlockchainHelper(
|
|||
* uncommented is used.
|
||||
* Docs: https://docs.walletconnect.com/advanced/multichain/chain-list
|
||||
*
|
||||
* Blockchain.Solana -> "5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"
|
||||
* */
|
||||
Blockchain.Solana -> "4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ"
|
||||
Blockchain.SolanaTestnet -> "z4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z"
|
||||
Blockchain.Polkadot -> "91b171bb158e2d3848fa23a9f1c25182"
|
||||
Blockchain.Tron -> "0x2b6653dc"
|
||||
else -> null
|
||||
Blockchain.Solana -> listOf("5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", "4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ")
|
||||
Blockchain.SolanaTestnet -> listOf("z4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z")
|
||||
Blockchain.Polkadot -> listOf("91b171bb158e2d3848fa23a9f1c25182")
|
||||
Blockchain.Tron -> listOf("0x2b6653dc")
|
||||
else -> emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -92,6 +109,7 @@ internal class TangemWcBlockchainHelper(
|
|||
second.toIntOrNull()
|
||||
?.let(Blockchain::fromChainId)
|
||||
}
|
||||
SOLANA_NAMESPACE -> Blockchain.Solana
|
||||
else -> {
|
||||
Blockchain.fromNetworkId(networkId = first)
|
||||
.takeIf(supportedNonEvmBlockchains::contains)
|
||||
|
|
@ -101,6 +119,7 @@ internal class TangemWcBlockchainHelper(
|
|||
|
||||
private companion object {
|
||||
const val EVM_NAMESPACE = "eip155"
|
||||
const val SOLANA_NAMESPACE = "solana"
|
||||
const val CHAIN_SEPARATOR = ":"
|
||||
const val TESTNET_SEPARATOR = "/"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ internal class WalletConnectEventsHandlerImpl : WalletConnectEventsHandler {
|
|||
WalletConnectDialog.SessionProposalDialog(
|
||||
sessionProposal = proposal,
|
||||
networks = networksFormatted,
|
||||
onApprove = { store.dispatchOnMain(WalletConnectAction.ApproveProposal) },
|
||||
onApprove = { store.dispatchOnMain(WalletConnectAction.ApproveProposal(proposal)) },
|
||||
onReject = { store.dispatchOnMain(WalletConnectAction.RejectProposal) },
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -207,6 +207,10 @@ internal class DefaultLegacyWalletConnectRepository(
|
|||
Timber.i("onSessionDelete: $sessionDelete")
|
||||
}
|
||||
|
||||
override fun onSessionExtend(session: Wallet.Model.Session) {
|
||||
Timber.i("onSessionExtend: $session")
|
||||
}
|
||||
|
||||
override fun onSessionSettleResponse(settleSessionResponse: Wallet.Model.SettledSessionResponse) {
|
||||
// Triggered when wallet receives the session settlement response from Dapp
|
||||
Timber.i("onSessionSettleResponse: $settleSessionResponse")
|
||||
|
|
@ -264,8 +268,6 @@ internal class DefaultLegacyWalletConnectRepository(
|
|||
}
|
||||
|
||||
override fun approve(userNamespaces: Map<NetworkNamespace, List<Account>>) {
|
||||
this.userNamespaces = userNamespaces
|
||||
|
||||
val sessionProposal: Wallet.Model.SessionProposal = requireNotNull(this.sessionProposal)
|
||||
|
||||
val userChains = userNamespaces.flatMap { namespace ->
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ class WalletConnectInteractor(
|
|||
private suspend fun setupUserChains(userWallet: UserWallet, currencies: List<CryptoCurrency>) {
|
||||
val accounts = getAccountsForWc(
|
||||
userWallet = userWallet,
|
||||
networks = currencies.map { it.network },
|
||||
networks = currencies.map { it.network }.distinct(),
|
||||
)
|
||||
setUserChains(accounts)
|
||||
handleDeeplinkStack(accounts)
|
||||
|
|
@ -403,18 +403,14 @@ class WalletConnectInteractor(
|
|||
derivationPath = it.derivationPath.value,
|
||||
)
|
||||
}
|
||||
return walletManagers.mapNotNull {
|
||||
return walletManagers.flatMap {
|
||||
val wallet = it.wallet
|
||||
val chainId = blockchainHelper.networkIdToChainIdOrNull(
|
||||
wallet.blockchain.toNetworkId(),
|
||||
val chainIds = blockchainHelper.networkIdToChainIdOrNull(wallet.blockchain.toNetworkId())
|
||||
blockchainHelper.chainIdsToAccounts(
|
||||
walletAddress = wallet.address,
|
||||
chainIds = chainIds,
|
||||
derivationPath = wallet.publicKey.derivationPath?.rawPath,
|
||||
)
|
||||
chainId?.let {
|
||||
Account(
|
||||
chainId,
|
||||
wallet.address,
|
||||
wallet.publicKey.derivationPath?.rawPath,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,20 @@
|
|||
package com.tangem.tap.domain.walletconnect2.domain
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.tap.domain.walletconnect2.domain.models.Account
|
||||
|
||||
interface WcBlockchainHelper {
|
||||
fun chainIdToNetworkIdOrNull(chainId: String): String?
|
||||
|
||||
fun chainIdToMissingNetworkNameOrNull(chainId: String): String?
|
||||
|
||||
fun networkIdToChainIdOrNull(networkId: String): String?
|
||||
fun networkIdToChainIdOrNull(networkId: String): List<String>
|
||||
|
||||
fun getNamespaceFromFullChainIdOrNull(chainId: String): String?
|
||||
|
||||
fun chainIdToFullNameOrNull(chainId: String): String?
|
||||
|
||||
fun chainIdsToAccounts(walletAddress: String, chainIds: List<String>, derivationPath: String?): List<Account>
|
||||
|
||||
fun chainIdsToBlockchains(chainIds: List<String>): List<Blockchain>
|
||||
}
|
||||
|
|
@ -223,14 +223,14 @@ internal class WcJrpcRequestsDeserializer @Inject constructor(@SdkMoshi private
|
|||
WcRequest.AddChain(data = deserializedParams)
|
||||
}
|
||||
WcJrpcMethods.SOLANA_SIGN_TX -> {
|
||||
val tx = moshi.adapter<SolanaTransactionRequest>(SolanaTransactionRequest::class.java)
|
||||
val tx = moshi.adapter(SolanaTransactionRequest::class.java)
|
||||
.fromJsonOrNull(params)
|
||||
?: return customRequest
|
||||
|
||||
WcRequest.SolanaSignRequest(data = tx)
|
||||
}
|
||||
WcJrpcMethods.SOLANA_SIGN_MESSAGE -> {
|
||||
val signMessage = moshi.adapter<SolanaSignMessage>(SolanaSignMessage::class.java)
|
||||
val signMessage = moshi.adapter(SolanaSignMessage::class.java)
|
||||
.fromJsonOrNull(params)
|
||||
?: return customRequest
|
||||
val data = WcSignMessage(
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
package com.tangem.tap.domain.walletconnect2.domain
|
||||
|
||||
import com.tangem.tap.domain.walletconnect.WalletConnectSdkHelper
|
||||
import com.tangem.tap.domain.walletconnect2.domain.mapper.mapToTransaction
|
||||
import com.tangem.tap.domain.walletconnect2.domain.models.BnbData
|
||||
import com.tangem.tap.domain.walletconnect2.domain.models.EthTransactionData
|
||||
import com.tangem.tap.domain.walletconnect2.domain.models.WalletConnectError
|
||||
import com.tangem.tap.domain.walletconnect2.domain.models.WalletConnectEvents
|
||||
import com.tangem.tap.features.details.redux.walletconnect.WcEthTransactionType
|
||||
import okio.ByteString.Companion.decodeBase64
|
||||
|
||||
internal class WcSessionRequestConverter(
|
||||
private val blockchainHelper: WcBlockchainHelper,
|
||||
|
|
@ -115,11 +115,11 @@ internal class WcSessionRequestConverter(
|
|||
)
|
||||
}
|
||||
is WcRequest.SolanaSignRequest -> {
|
||||
val data = request.data.mapToTransaction()
|
||||
val transaction = request.data.transaction
|
||||
|
||||
WcPreparedRequest.SignTransaction(
|
||||
preparedRequestData = WcGenericTransactionData(
|
||||
hashToSign = data.getSerializedMessage(),
|
||||
hashToSign = transaction.prepareSolanaTransaction(),
|
||||
dAppName = sessionRequest.metaName,
|
||||
type = TransactionType.SOLANA_TX,
|
||||
),
|
||||
|
|
@ -132,6 +132,16 @@ internal class WcSessionRequestConverter(
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Input transaction in Base64 string
|
||||
*/
|
||||
private fun String.prepareSolanaTransaction(): ByteArray {
|
||||
return this.decodeBase64()
|
||||
?.toByteArray()
|
||||
?.drop(SOLANA_SIGNATURE_PLACEHOLDER_LENGTH)
|
||||
?.toByteArray() ?: ByteArray(0)
|
||||
}
|
||||
|
||||
private fun getWalletAddress(request: WcRequest): String? {
|
||||
return when (request) {
|
||||
is WcRequest.BnbTrade -> request.data.accountNumber
|
||||
|
|
@ -156,4 +166,8 @@ internal class WcSessionRequestConverter(
|
|||
it.chainId == sessionRequest.chainId && it.walletAddress.lowercase() == walletAddress?.lowercase()
|
||||
}?.derivationPath
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val SOLANA_SIGNATURE_PLACEHOLDER_LENGTH = 65
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,9 @@ data class SolanaTransactionRequest(
|
|||
|
||||
@Json(name = "instructions")
|
||||
val instructions: List<Instruction>,
|
||||
|
||||
@Json(name = "transaction")
|
||||
val transaction: String,
|
||||
) : WcRequestData {
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
|
|
@ -22,7 +25,7 @@ data class SolanaTransactionRequest(
|
|||
val programId: String,
|
||||
|
||||
@Json(name = "data")
|
||||
val data: List<Byte>,
|
||||
val data: String,
|
||||
|
||||
@Json(name = "keys")
|
||||
val keys: List<Key>,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.tap.features.details.redux.walletconnect
|
|||
|
||||
import com.tangem.tap.domain.walletconnect2.domain.WcPreparedRequest
|
||||
import com.tangem.tap.domain.walletconnect2.domain.models.WalletConnectError
|
||||
import com.tangem.tap.domain.walletconnect2.domain.models.WalletConnectEvents
|
||||
import com.tangem.tap.features.details.ui.walletconnect.WcSessionForScreen
|
||||
import org.rekotlin.Action
|
||||
|
||||
|
|
@ -22,7 +23,7 @@ sealed class WalletConnectAction : Action {
|
|||
|
||||
data class ShowClipboardOrScanQrDialog(val wcUri: String) : WalletConnectAction()
|
||||
//region WalletConnect 2.0
|
||||
data object ApproveProposal : WalletConnectAction()
|
||||
data class ApproveProposal(val proposal: WalletConnectEvents.SessionProposal) : WalletConnectAction()
|
||||
data object RejectProposal : WalletConnectAction()
|
||||
|
||||
data object SessionEstablished : WalletConnectAction()
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import com.tangem.tap.common.redux.global.GlobalAction
|
|||
import com.tangem.tap.domain.walletconnect2.domain.LegacyWalletConnectRepository
|
||||
import com.tangem.tap.domain.walletconnect2.domain.WalletConnectInteractor
|
||||
import com.tangem.tap.domain.walletconnect2.domain.WcPreparedRequest
|
||||
import com.tangem.tap.domain.walletconnect2.domain.models.Account
|
||||
import com.tangem.tap.domain.walletconnect2.domain.models.WalletConnectError
|
||||
import com.tangem.tap.features.demo.DemoHelper
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
|
|
@ -86,19 +85,21 @@ class WalletConnectMiddleware {
|
|||
}
|
||||
is WalletConnectAction.ApproveProposal -> {
|
||||
scope.launch {
|
||||
val proposalChainIds = action.proposal.requiredChainIds + action.proposal.optionalChainIds
|
||||
val proposalBlockchains =
|
||||
walletConnectInteractor.blockchainHelper.chainIdsToBlockchains(proposalChainIds)
|
||||
val accounts = getWalletManagers()
|
||||
.mapNotNull {
|
||||
.filter { walletManager -> proposalBlockchains.contains(walletManager.wallet.blockchain) }
|
||||
.flatMap {
|
||||
val wallet = it.wallet
|
||||
val chainId = walletConnectInteractor.blockchainHelper.networkIdToChainIdOrNull(
|
||||
val chainIds = walletConnectInteractor.blockchainHelper.networkIdToChainIdOrNull(
|
||||
wallet.blockchain.toNetworkId(),
|
||||
)
|
||||
chainId?.let {
|
||||
Account(
|
||||
chainId,
|
||||
wallet.address,
|
||||
wallet.publicKey.derivationPath?.rawPath,
|
||||
)
|
||||
}
|
||||
walletConnectInteractor.blockchainHelper.chainIdsToAccounts(
|
||||
walletAddress = wallet.address,
|
||||
chainIds = chainIds,
|
||||
derivationPath = wallet.publicKey.derivationPath?.rawPath,
|
||||
)
|
||||
}
|
||||
walletConnectInteractor.approveSessionProposal(accounts)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,13 +18,13 @@ import com.tangem.domain.models.scan.CardDTO
|
|||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.wallets.builder.UserWalletIdBuilder
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.sdk.api.TangemSdkManager
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Settings
|
||||
import com.tangem.tap.common.extensions.dispatchDialogShow
|
||||
import com.tangem.tap.common.extensions.dispatchNavigationAction
|
||||
import com.tangem.tap.common.redux.AppDialog
|
||||
import com.tangem.tap.domain.extensions.signedHashesCount
|
||||
import com.tangem.tap.domain.sdk.TangemSdkManager
|
||||
import com.tangem.tap.features.details.ui.cardsettings.domain.CardSettingsInteractor
|
||||
import com.tangem.tap.features.details.ui.common.utils.*
|
||||
import com.tangem.tap.features.onboarding.products.twins.redux.CreateTwinWalletMode
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@ import com.tangem.common.doOnSuccess
|
|||
import com.tangem.common.routing.AppRouter
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.sdk.api.TangemSdkManager
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Settings
|
||||
import com.tangem.tap.common.extensions.dispatchNavigationAction
|
||||
import com.tangem.tap.domain.sdk.TangemSdkManager
|
||||
import com.tangem.tap.features.details.ui.cardsettings.domain.CardSettingsInteractor
|
||||
import com.tangem.tap.features.details.ui.common.utils.isAccessCodeRecoveryEnabled
|
||||
import com.tangem.tap.store
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@ import com.tangem.common.core.TangemSdkError
|
|||
import com.tangem.common.routing.AppRouter
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.sdk.api.TangemSdkManager
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Settings
|
||||
import com.tangem.tap.common.extensions.dispatchNavigationAction
|
||||
import com.tangem.tap.domain.sdk.TangemSdkManager
|
||||
import com.tangem.tap.features.details.redux.SecurityOption
|
||||
import com.tangem.tap.features.details.ui.cardsettings.domain.CardSettingsInteractor
|
||||
import com.tangem.tap.features.details.ui.common.utils.getAllowedSecurityOptions
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import com.tangem.blockchainsdk.BlockchainSDKFactory
|
|||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.common.routing.AppRouter
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.core.analytics.models.Basic
|
||||
import com.tangem.datasource.api.common.config.managers.ApiConfigsManager
|
||||
import com.tangem.domain.appcurrency.FetchAppCurrenciesUseCase
|
||||
import com.tangem.domain.balancehiding.BalanceHidingSettings
|
||||
|
|
@ -103,7 +102,6 @@ internal class MainViewModel @Inject constructor(
|
|||
.distinctUntilChanged()
|
||||
.onEach { userWallet ->
|
||||
Analytics.setContext(userWallet.scanResponse)
|
||||
Analytics.send(Basic.WalletOpened())
|
||||
}
|
||||
.flowOn(dispatchers.io)
|
||||
.launchIn(viewModelScope)
|
||||
|
|
|
|||
|
|
@ -66,6 +66,10 @@ object OnboardingHelper {
|
|||
}
|
||||
|
||||
fun whereToNavigate(scanResponse: ScanResponse): AppRoute {
|
||||
if (store.inject(DaggerGraphState::onboardingV2FeatureToggles).isOnboardingV2Enabled) {
|
||||
return AppRoute.Onboarding(scanResponse)
|
||||
}
|
||||
|
||||
return when (val type = scanResponse.productType) {
|
||||
ProductType.Note -> AppRoute.OnboardingNote
|
||||
ProductType.Wallet,
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@ package com.tangem.tap.features.onboarding.products.wallet.redux
|
|||
|
||||
import android.net.Uri
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.common.card.Card
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.feature.onboarding.data.model.CreateWalletResponse
|
||||
import com.tangem.feature.onboarding.presentation.wallet2.analytics.SeedPhraseSource
|
||||
import com.tangem.tap.domain.tasks.product.CreateProductWalletTaskResponse
|
||||
import com.tangem.sdk.api.CreateProductWalletTaskResponse
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import org.rekotlin.Action
|
||||
|
||||
|
|
|
|||
|
|
@ -28,13 +28,13 @@ import com.tangem.feature.onboarding.presentation.wallet2.analytics.SeedPhraseSo
|
|||
import com.tangem.feature.wallet.presentation.wallet.domain.BackupValidator
|
||||
import com.tangem.operations.attestation.OnlineCardVerifier
|
||||
import com.tangem.operations.backup.BackupService
|
||||
import com.tangem.sdk.api.CreateProductWalletTaskResponse
|
||||
import com.tangem.tap.*
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Onboarding
|
||||
import com.tangem.tap.common.extensions.*
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.domain.tasks.product.CreateProductWalletTaskResponse
|
||||
import com.tangem.tap.features.demo.DemoHelper
|
||||
import com.tangem.tap.features.home.redux.HomeAction
|
||||
import com.tangem.tap.features.onboarding.OnboardingDialog
|
||||
|
|
|
|||
|
|
@ -54,6 +54,15 @@ object TradeCryptoMiddleware {
|
|||
}
|
||||
|
||||
private fun proceedBuyAction(state: () -> AppState?, action: TradeCryptoAction.Buy) {
|
||||
val isOnrampEnabled = store.inject(DaggerGraphState::onrampFeatureToggles).isFeatureEnabled
|
||||
if (isOnrampEnabled) proceedWithOnramp() else proceedWithLegacyBuyAction(state, action)
|
||||
}
|
||||
|
||||
private fun proceedWithOnramp() {
|
||||
store.dispatchNavigationAction { push(AppRoute.Onramp) }
|
||||
}
|
||||
|
||||
private fun proceedWithLegacyBuyAction(state: () -> AppState?, action: TradeCryptoAction.Buy) {
|
||||
val networkAddress = action.cryptoCurrencyStatus.value.networkAddress
|
||||
?.defaultAddress
|
||||
?.let(NetworkAddress.Address::value)
|
||||
|
|
|
|||
|
|
@ -1,60 +0,0 @@
|
|||
package com.tangem.tap.network.exchangeServices
|
||||
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.tap.domain.model.Currency
|
||||
import com.tangem.tap.network.exchangeServices.mercuryo.MercuryoService
|
||||
import com.tangem.tap.scope
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
* Temporary wrapper for the buy services. Service switches based on selected product type.
|
||||
*/
|
||||
internal class BuyExchangeService(
|
||||
private val mercuryoService: MercuryoService,
|
||||
) : ExchangeService, ExchangeUrlBuilder {
|
||||
|
||||
init {
|
||||
scope.launch {
|
||||
mercuryoService.update()
|
||||
}
|
||||
}
|
||||
|
||||
private val currentService: ExchangeService = mercuryoService
|
||||
|
||||
override suspend fun update() {
|
||||
currentService.update()
|
||||
}
|
||||
|
||||
override fun featureIsSwitchedOn(): Boolean = currentService.featureIsSwitchedOn()
|
||||
|
||||
override fun isBuyAllowed(): Boolean = currentService.isBuyAllowed()
|
||||
|
||||
override fun isSellAllowed(): Boolean = currentService.isSellAllowed()
|
||||
|
||||
override fun availableForBuy(scanResponse: ScanResponse, currency: Currency): Boolean =
|
||||
currentService.availableForBuy(scanResponse, currency)
|
||||
|
||||
override fun availableForSell(currency: Currency): Boolean = currentService.availableForSell(currency)
|
||||
|
||||
override fun getUrl(
|
||||
action: CurrencyExchangeManager.Action,
|
||||
cryptoCurrency: CryptoCurrency,
|
||||
fiatCurrencyName: String,
|
||||
walletAddress: String,
|
||||
isDarkTheme: Boolean,
|
||||
): String? {
|
||||
return currentService.getUrl(
|
||||
action,
|
||||
cryptoCurrency,
|
||||
fiatCurrencyName,
|
||||
walletAddress,
|
||||
isDarkTheme,
|
||||
)
|
||||
}
|
||||
|
||||
override fun getSellCryptoReceiptUrl(action: CurrencyExchangeManager.Action, transactionId: String): String? {
|
||||
return currentService.getSellCryptoReceiptUrl(action, transactionId)
|
||||
}
|
||||
}
|
||||
|
|
@ -13,12 +13,6 @@ class CardExchangeRules(
|
|||
val cardProvider: () -> CardDTO?,
|
||||
) : ExchangeRules {
|
||||
|
||||
override fun featureIsSwitchedOn(): Boolean {
|
||||
val card = cardProvider() ?: return false
|
||||
|
||||
return !card.isStart2Coin
|
||||
}
|
||||
|
||||
override fun isBuyAllowed(): Boolean {
|
||||
val card = cardProvider() ?: return false
|
||||
|
||||
|
|
|
|||
|
|
@ -30,8 +30,6 @@ class CurrencyExchangeManager(
|
|||
private val primaryRules: ExchangeRules,
|
||||
) : ExchangeService {
|
||||
|
||||
override fun featureIsSwitchedOn(): Boolean = primaryRules.featureIsSwitchedOn()
|
||||
|
||||
override suspend fun update() {
|
||||
buyService.update()
|
||||
sellService.update()
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package com.tangem.tap.network.exchangeServices
|
|||
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.tap.common.feature.Feature
|
||||
import com.tangem.tap.domain.model.Currency
|
||||
|
||||
interface Exchanger {
|
||||
|
|
@ -12,12 +11,11 @@ interface Exchanger {
|
|||
fun availableForSell(currency: Currency): Boolean
|
||||
}
|
||||
|
||||
interface ExchangeService : Feature, Exchanger, ExchangeUrlBuilder {
|
||||
interface ExchangeService : Exchanger, ExchangeUrlBuilder {
|
||||
suspend fun update()
|
||||
|
||||
companion object {
|
||||
fun dummy(): ExchangeService = object : ExchangeService {
|
||||
override fun featureIsSwitchedOn(): Boolean = false
|
||||
override suspend fun update() {}
|
||||
override fun isBuyAllowed(): Boolean = false
|
||||
override fun isSellAllowed(): Boolean = false
|
||||
|
|
@ -39,11 +37,10 @@ interface ExchangeService : Feature, Exchanger, ExchangeUrlBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
interface ExchangeRules : Feature, Exchanger {
|
||||
interface ExchangeRules : Exchanger {
|
||||
|
||||
companion object {
|
||||
fun dummy(): ExchangeRules = object : ExchangeRules {
|
||||
override fun featureIsSwitchedOn(): Boolean = false
|
||||
override fun isBuyAllowed(): Boolean = false
|
||||
override fun isSellAllowed(): Boolean = false
|
||||
override fun availableForBuy(scanResponse: ScanResponse, currency: Currency): Boolean = false
|
||||
|
|
|
|||
|
|
@ -0,0 +1,145 @@
|
|||
package com.tangem.tap.network.exchangeServices.mercuryo
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
|
||||
/**
|
||||
* Map [Blockchain] to ids from [link](https://api.mercuryo.io/v1.6/lib/currencies) [crypto_currencies]
|
||||
*/
|
||||
@Suppress("CyclomaticComplexMethod")
|
||||
internal val Blockchain.mercuryoNetwork: String?
|
||||
get() {
|
||||
return when (this) {
|
||||
Blockchain.Algorand -> "ALGORAND"
|
||||
Blockchain.Arbitrum -> "ARBITRUM"
|
||||
Blockchain.Avalanche -> "AVALANCHE"
|
||||
Blockchain.BSC -> "BINANCESMARTCHAIN"
|
||||
Blockchain.Bitcoin -> "BITCOIN"
|
||||
Blockchain.BitcoinCash -> "BITCOINCASH"
|
||||
Blockchain.Cardano -> "CARDANO"
|
||||
Blockchain.Cosmos -> "COSMOS"
|
||||
Blockchain.Dash -> "DASH"
|
||||
Blockchain.Dogecoin -> "DOGECOIN"
|
||||
Blockchain.Ethereum -> "ETHEREUM"
|
||||
Blockchain.Fantom -> "FANTOM"
|
||||
Blockchain.Kusama -> "KUSAMA"
|
||||
Blockchain.Litecoin -> "LITECOIN"
|
||||
Blockchain.Near -> "NEAR_PROTOCOL"
|
||||
Blockchain.TON -> "NEWTON"
|
||||
Blockchain.Optimism -> "OPTIMISM"
|
||||
Blockchain.Polkadot -> "POLKADOT"
|
||||
Blockchain.Polygon -> "POLYGON"
|
||||
Blockchain.XRP -> "RIPPLE"
|
||||
Blockchain.Solana -> "SOLANA"
|
||||
Blockchain.Stellar -> "STELLAR"
|
||||
Blockchain.Tezos -> "TEZOS"
|
||||
Blockchain.Tron -> "TRON"
|
||||
Blockchain.ZkSyncEra -> "ZKSYNC"
|
||||
Blockchain.Base -> "BASE"
|
||||
Blockchain.ArbitrumTestnet -> null
|
||||
Blockchain.AvalancheTestnet -> null
|
||||
Blockchain.Binance -> null
|
||||
Blockchain.BinanceTestnet -> null
|
||||
Blockchain.BSCTestnet -> null
|
||||
Blockchain.BitcoinTestnet -> null
|
||||
Blockchain.BitcoinCashTestnet -> null
|
||||
Blockchain.CosmosTestnet -> null
|
||||
Blockchain.Ducatus -> null
|
||||
Blockchain.EthereumTestnet -> null
|
||||
Blockchain.EthereumClassic -> null
|
||||
Blockchain.EthereumClassicTestnet -> null
|
||||
Blockchain.FantomTestnet -> null
|
||||
Blockchain.NearTestnet -> null
|
||||
Blockchain.PolkadotTestnet -> null
|
||||
Blockchain.Kava -> null
|
||||
Blockchain.KavaTestnet -> null
|
||||
Blockchain.PolygonTestnet -> null
|
||||
Blockchain.RSK -> null
|
||||
Blockchain.Sei -> null
|
||||
Blockchain.SeiTestnet -> null
|
||||
Blockchain.StellarTestnet -> null
|
||||
Blockchain.SolanaTestnet -> null
|
||||
Blockchain.TronTestnet -> null
|
||||
Blockchain.Gnosis -> null
|
||||
Blockchain.OptimismTestnet -> null
|
||||
Blockchain.Dischain -> null
|
||||
Blockchain.EthereumPow -> null
|
||||
Blockchain.EthereumPowTestnet -> null
|
||||
Blockchain.Kaspa -> null
|
||||
Blockchain.Telos -> null
|
||||
Blockchain.TelosTestnet -> null
|
||||
Blockchain.TONTestnet -> null
|
||||
Blockchain.Ravencoin -> null
|
||||
Blockchain.RavencoinTestnet -> null
|
||||
Blockchain.TerraV1 -> null
|
||||
Blockchain.TerraV2 -> null
|
||||
Blockchain.Cronos -> null
|
||||
Blockchain.AlephZero -> null
|
||||
Blockchain.AlephZeroTestnet -> null
|
||||
Blockchain.OctaSpace -> null
|
||||
Blockchain.OctaSpaceTestnet -> null
|
||||
Blockchain.Chia -> null
|
||||
Blockchain.ChiaTestnet -> null
|
||||
Blockchain.Decimal -> null
|
||||
Blockchain.DecimalTestnet -> null
|
||||
Blockchain.XDC -> null
|
||||
Blockchain.XDCTestnet -> null
|
||||
Blockchain.VeChain -> null
|
||||
Blockchain.VeChainTestnet -> null
|
||||
Blockchain.Aptos -> null
|
||||
Blockchain.AptosTestnet -> null
|
||||
Blockchain.Playa3ull -> null
|
||||
Blockchain.Shibarium -> null
|
||||
Blockchain.ShibariumTestnet -> null
|
||||
Blockchain.AlgorandTestnet -> null
|
||||
Blockchain.Hedera -> null
|
||||
Blockchain.HederaTestnet -> null
|
||||
Blockchain.Aurora -> null
|
||||
Blockchain.AuroraTestnet -> null
|
||||
Blockchain.Areon -> null
|
||||
Blockchain.AreonTestnet -> null
|
||||
Blockchain.PulseChain -> null
|
||||
Blockchain.PulseChainTestnet -> null
|
||||
Blockchain.ZkSyncEraTestnet -> null
|
||||
Blockchain.Nexa -> null
|
||||
Blockchain.NexaTestnet -> null
|
||||
Blockchain.Moonbeam -> null
|
||||
Blockchain.MoonbeamTestnet -> null
|
||||
Blockchain.Manta -> null
|
||||
Blockchain.MantaTestnet -> null
|
||||
Blockchain.PolygonZkEVM -> null
|
||||
Blockchain.PolygonZkEVMTestnet -> null
|
||||
Blockchain.Radiant -> null
|
||||
Blockchain.BaseTestnet -> null
|
||||
Blockchain.Moonriver -> null
|
||||
Blockchain.MoonriverTestnet -> null
|
||||
Blockchain.Mantle -> null
|
||||
Blockchain.MantleTestnet -> null
|
||||
Blockchain.Flare -> null
|
||||
Blockchain.FlareTestnet -> null
|
||||
Blockchain.Taraxa -> null
|
||||
Blockchain.TaraxaTestnet -> null
|
||||
Blockchain.Koinos -> null
|
||||
Blockchain.KoinosTestnet -> null
|
||||
Blockchain.Joystream -> null
|
||||
Blockchain.Bittensor -> null
|
||||
Blockchain.Filecoin -> null
|
||||
Blockchain.Blast -> null
|
||||
Blockchain.BlastTestnet -> null
|
||||
Blockchain.Cyber -> null
|
||||
Blockchain.CyberTestnet -> null
|
||||
Blockchain.InternetComputer -> null
|
||||
Blockchain.Sui -> null
|
||||
Blockchain.SuiTestnet -> null
|
||||
Blockchain.EnergyWebChain -> null
|
||||
Blockchain.EnergyWebChainTestnet -> null
|
||||
Blockchain.EnergyWebX -> null
|
||||
Blockchain.EnergyWebXTestnet -> null
|
||||
Blockchain.Casper -> null
|
||||
Blockchain.CasperTestnet -> null
|
||||
Blockchain.Core -> null
|
||||
Blockchain.CoreTestnet -> null
|
||||
Blockchain.Unknown -> null
|
||||
Blockchain.Xodex -> null
|
||||
Blockchain.Canxium -> null
|
||||
}
|
||||
}
|
||||
|
|
@ -23,8 +23,6 @@ internal class MercuryoService(private val environment: MercuryoEnvironment) : E
|
|||
|
||||
private val availableMercuryoCurrencies = CopyOnWriteArrayList<MercuryoCurrenciesResponse.MercuryoCryptoCurrency>()
|
||||
|
||||
override fun featureIsSwitchedOn(): Boolean = true
|
||||
|
||||
override fun isBuyAllowed(): Boolean = true
|
||||
|
||||
override fun isSellAllowed(): Boolean = false
|
||||
|
|
@ -32,7 +30,7 @@ internal class MercuryoService(private val environment: MercuryoEnvironment) : E
|
|||
override fun availableForBuy(scanResponse: ScanResponse, currency: Currency): Boolean {
|
||||
if (!isBuyAllowed()) return false
|
||||
|
||||
val mercuryoNetwork = currency.blockchain.mercuryoNetwork()
|
||||
val mercuryoNetwork = currency.blockchain.mercuryoNetwork
|
||||
val contractAddress = (currency as? Currency.Token)?.token?.contractAddress ?: ""
|
||||
val availableCurrency = availableMercuryoCurrencies.firstOrNull {
|
||||
it.currencySymbol == currency.currencySymbol &&
|
||||
|
|
@ -79,7 +77,7 @@ internal class MercuryoService(private val environment: MercuryoEnvironment) : E
|
|||
.appendQueryParameter("redirect_url", ExchangeUrlBuilder.SUCCESS_URL)
|
||||
if (isDarkTheme) builder.appendQueryParameter("theme", "1inch")
|
||||
|
||||
blockchain.mercuryoNetwork()?.let {
|
||||
blockchain.mercuryoNetwork?.let {
|
||||
builder.appendQueryParameter("network", it)
|
||||
}
|
||||
|
||||
|
|
@ -93,37 +91,6 @@ internal class MercuryoService(private val environment: MercuryoEnvironment) : E
|
|||
availableMercuryoCurrencies.addAll(data.config.cryptoCurrencies)
|
||||
}
|
||||
|
||||
@Suppress("CyclomaticComplexMethod")
|
||||
private fun Blockchain.mercuryoNetwork(): String? {
|
||||
return when (this) {
|
||||
// Blockchain.Algorand -> "ALGORAND" //TODO: Uncomment with algo support
|
||||
Blockchain.Arbitrum -> "ARBITRUM"
|
||||
Blockchain.Avalanche -> "AVALANCHE"
|
||||
Blockchain.BSC -> "BINANCESMARTCHAIN"
|
||||
Blockchain.Bitcoin -> "BITCOIN"
|
||||
Blockchain.BitcoinCash -> "BITCOINCASH"
|
||||
Blockchain.Cardano -> "CARDANO"
|
||||
Blockchain.Cosmos -> "COSMOS"
|
||||
Blockchain.Dash -> "DASH"
|
||||
Blockchain.Dogecoin -> "DOGECOIN"
|
||||
Blockchain.Ethereum -> "ETHEREUM"
|
||||
Blockchain.Fantom -> "FANTOM"
|
||||
Blockchain.Kusama -> "KUSAMA"
|
||||
Blockchain.Litecoin -> "LITECOIN"
|
||||
Blockchain.Near -> "NEAR_PROTOCOL"
|
||||
Blockchain.TON -> "NEWTON"
|
||||
Blockchain.Optimism -> "OPTIMISM"
|
||||
Blockchain.Polkadot -> "POLKADOT"
|
||||
Blockchain.Polygon -> "POLYGON"
|
||||
Blockchain.XRP -> "RIPPLE"
|
||||
Blockchain.Solana -> "SOLANA"
|
||||
Blockchain.Stellar -> "STELLAR"
|
||||
Blockchain.Tezos -> "TEZOS"
|
||||
Blockchain.Tron -> "TRON"
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun signature(address: String) = (address + environment.secret).calculateSha512().toHexString().lowercase()
|
||||
|
||||
private companion object {
|
||||
|
|
|
|||
|
|
@ -1,37 +0,0 @@
|
|||
package com.tangem.tap.network.exchangeServices.moonpay
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.Blockchain.*
|
||||
import com.tangem.tap.network.exchangeServices.moonpay.models.MoonPaySupportedCurrency
|
||||
|
||||
internal val Blockchain.moonPaySupportedCurrency: MoonPaySupportedCurrency?
|
||||
get() = when (this) {
|
||||
Algorand -> MoonPaySupportedCurrency(networkCode = "algorand", currencyCode = "algo")
|
||||
Aptos -> MoonPaySupportedCurrency(networkCode = "aptos", currencyCode = "apt")
|
||||
Arbitrum -> MoonPaySupportedCurrency(networkCode = "arbitrum", currencyCode = "eth_arbitrum")
|
||||
Avalanche -> MoonPaySupportedCurrency(networkCode = "avalanche_c_chain", currencyCode = "avax_cchain")
|
||||
Binance -> MoonPaySupportedCurrency(networkCode = "bnb_chain", currencyCode = "bnb")
|
||||
Bitcoin -> MoonPaySupportedCurrency(networkCode = "bitcoin", currencyCode = "btc")
|
||||
BitcoinCash -> MoonPaySupportedCurrency(networkCode = "bitcoin_cash", currencyCode = "bch")
|
||||
BSC -> MoonPaySupportedCurrency(networkCode = "binance_smart_chain", currencyCode = "bnb_bsc")
|
||||
Cardano -> MoonPaySupportedCurrency(networkCode = "cardano", currencyCode = "ada")
|
||||
Cosmos -> MoonPaySupportedCurrency(networkCode = "cosmos", currencyCode = "atom")
|
||||
Dogecoin -> MoonPaySupportedCurrency(networkCode = "dogecoin", currencyCode = "doge")
|
||||
Ethereum -> MoonPaySupportedCurrency(networkCode = "ethereum", currencyCode = "eth")
|
||||
EthereumClassic -> MoonPaySupportedCurrency(networkCode = "ethereum_classic", currencyCode = "etc")
|
||||
Hedera -> MoonPaySupportedCurrency(networkCode = "hedera", currencyCode = "hbar")
|
||||
Litecoin -> MoonPaySupportedCurrency(networkCode = "litecoin", currencyCode = "ltc")
|
||||
Near -> MoonPaySupportedCurrency(networkCode = "near", currencyCode = "near")
|
||||
Optimism -> MoonPaySupportedCurrency(networkCode = "optimism", currencyCode = "eth_optimism")
|
||||
Polkadot -> MoonPaySupportedCurrency(networkCode = "polkadot", currencyCode = "dot")
|
||||
Polygon -> MoonPaySupportedCurrency(networkCode = "polygon", currencyCode = "matic_polygon")
|
||||
Ravencoin -> MoonPaySupportedCurrency(networkCode = "ravencoin", currencyCode = "rvn")
|
||||
Solana -> MoonPaySupportedCurrency(networkCode = "solana", currencyCode = "sol")
|
||||
Stellar -> MoonPaySupportedCurrency(networkCode = "stellar", currencyCode = "xlm")
|
||||
Tezos -> MoonPaySupportedCurrency(networkCode = "tezos", currencyCode = "xtz")
|
||||
TON -> MoonPaySupportedCurrency(networkCode = "ton", currencyCode = "ton")
|
||||
Tron -> MoonPaySupportedCurrency(networkCode = "tron", currencyCode = "trx")
|
||||
VeChain -> MoonPaySupportedCurrency(networkCode = "vechain", currencyCode = "vet")
|
||||
XRP -> MoonPaySupportedCurrency(networkCode = "ripple", currencyCode = "xrp")
|
||||
else -> null
|
||||
}
|
||||
|
|
@ -32,8 +32,6 @@ class MoonPayService(
|
|||
|
||||
private var status: MoonPayStatus? = null
|
||||
|
||||
override fun featureIsSwitchedOn(): Boolean = true
|
||||
|
||||
override suspend fun update() {
|
||||
withIOContext {
|
||||
performRequest {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,145 @@
|
|||
package com.tangem.tap.network.exchangeServices.moonpay
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.Blockchain.*
|
||||
import com.tangem.tap.network.exchangeServices.moonpay.models.MoonPaySupportedCurrency
|
||||
|
||||
/**
|
||||
* Map [Blockchain] to [MoonPaySupportedCurrency.networkCode] and [MoonPaySupportedCurrency.currencyCode]
|
||||
* from [link](https://api.moonpay.com/v3/currencies/)
|
||||
*/
|
||||
internal val Blockchain.moonPaySupportedCurrency: MoonPaySupportedCurrency?
|
||||
get() = when (this) {
|
||||
Algorand -> MoonPaySupportedCurrency(networkCode = "algorand", currencyCode = "algo")
|
||||
Aptos -> MoonPaySupportedCurrency(networkCode = "aptos", currencyCode = "apt")
|
||||
Arbitrum -> MoonPaySupportedCurrency(networkCode = "arbitrum", currencyCode = "eth_arbitrum")
|
||||
Avalanche -> MoonPaySupportedCurrency(networkCode = "avalanche_c_chain", currencyCode = "avax_cchain")
|
||||
Binance -> MoonPaySupportedCurrency(networkCode = "bnb_chain", currencyCode = "bnb")
|
||||
Bitcoin -> MoonPaySupportedCurrency(networkCode = "bitcoin", currencyCode = "btc")
|
||||
BitcoinCash -> MoonPaySupportedCurrency(networkCode = "bitcoin_cash", currencyCode = "bch")
|
||||
BSC -> MoonPaySupportedCurrency(networkCode = "binance_smart_chain", currencyCode = "bnb_bsc")
|
||||
Cardano -> MoonPaySupportedCurrency(networkCode = "cardano", currencyCode = "ada")
|
||||
Cosmos -> MoonPaySupportedCurrency(networkCode = "cosmos", currencyCode = "atom")
|
||||
Dogecoin -> MoonPaySupportedCurrency(networkCode = "dogecoin", currencyCode = "doge")
|
||||
Ethereum -> MoonPaySupportedCurrency(networkCode = "ethereum", currencyCode = "eth")
|
||||
EthereumClassic -> MoonPaySupportedCurrency(networkCode = "ethereum_classic", currencyCode = "etc")
|
||||
Hedera -> MoonPaySupportedCurrency(networkCode = "hedera", currencyCode = "hbar")
|
||||
Litecoin -> MoonPaySupportedCurrency(networkCode = "litecoin", currencyCode = "ltc")
|
||||
Near -> MoonPaySupportedCurrency(networkCode = "near", currencyCode = "near")
|
||||
Optimism -> MoonPaySupportedCurrency(networkCode = "optimism", currencyCode = "eth_optimism")
|
||||
Polkadot -> MoonPaySupportedCurrency(networkCode = "polkadot", currencyCode = "dot")
|
||||
Polygon -> MoonPaySupportedCurrency(networkCode = "polygon", currencyCode = "matic_polygon")
|
||||
Ravencoin -> MoonPaySupportedCurrency(networkCode = "ravencoin", currencyCode = "rvn")
|
||||
Solana -> MoonPaySupportedCurrency(networkCode = "solana", currencyCode = "sol")
|
||||
Stellar -> MoonPaySupportedCurrency(networkCode = "stellar", currencyCode = "xlm")
|
||||
Tezos -> MoonPaySupportedCurrency(networkCode = "tezos", currencyCode = "xtz")
|
||||
TON -> MoonPaySupportedCurrency(networkCode = "ton", currencyCode = "ton")
|
||||
Tron -> MoonPaySupportedCurrency(networkCode = "tron", currencyCode = "trx")
|
||||
VeChain -> MoonPaySupportedCurrency(networkCode = "vechain", currencyCode = "vet")
|
||||
XRP -> MoonPaySupportedCurrency(networkCode = "ripple", currencyCode = "xrp")
|
||||
Sei -> MoonPaySupportedCurrency(networkCode = "sei", currencyCode = "sei_sei")
|
||||
ZkSyncEra -> MoonPaySupportedCurrency(networkCode = "zksync", currencyCode = "eth_zksync")
|
||||
Base -> MoonPaySupportedCurrency(networkCode = "base", currencyCode = "eth_base")
|
||||
Filecoin -> MoonPaySupportedCurrency(networkCode = "filecoin", currencyCode = "fil")
|
||||
Sui -> MoonPaySupportedCurrency(networkCode = "sui", currencyCode = "sui")
|
||||
Core -> MoonPaySupportedCurrency(networkCode = "core", currencyCode = "core")
|
||||
ArbitrumTestnet -> null
|
||||
AvalancheTestnet -> null
|
||||
BinanceTestnet -> null
|
||||
BSCTestnet -> null
|
||||
BitcoinTestnet -> null
|
||||
BitcoinCashTestnet -> null
|
||||
CosmosTestnet -> null
|
||||
Ducatus -> null
|
||||
EthereumTestnet -> null
|
||||
EthereumClassicTestnet -> null
|
||||
Fantom -> null
|
||||
FantomTestnet -> null
|
||||
NearTestnet -> null
|
||||
PolkadotTestnet -> null
|
||||
Kava -> null // doesn't support KavaEvm
|
||||
KavaTestnet -> null
|
||||
Kusama -> null
|
||||
PolygonTestnet -> null
|
||||
RSK -> null
|
||||
SeiTestnet -> null
|
||||
StellarTestnet -> null
|
||||
SolanaTestnet -> null
|
||||
TronTestnet -> null
|
||||
Gnosis -> null
|
||||
Dash -> null
|
||||
OptimismTestnet -> null
|
||||
Dischain -> null
|
||||
EthereumPow -> null
|
||||
EthereumPowTestnet -> null
|
||||
Kaspa -> null
|
||||
Telos -> null
|
||||
TelosTestnet -> null
|
||||
TONTestnet -> null
|
||||
RavencoinTestnet -> null
|
||||
TerraV1 -> null
|
||||
TerraV2 -> null
|
||||
Cronos -> null
|
||||
AlephZero -> null
|
||||
AlephZeroTestnet -> null
|
||||
OctaSpace -> null
|
||||
OctaSpaceTestnet -> null
|
||||
Chia -> null
|
||||
ChiaTestnet -> null
|
||||
Decimal -> null
|
||||
DecimalTestnet -> null
|
||||
XDC -> null
|
||||
XDCTestnet -> null
|
||||
VeChainTestnet -> null
|
||||
AptosTestnet -> null
|
||||
Playa3ull -> null
|
||||
Shibarium -> null
|
||||
ShibariumTestnet -> null
|
||||
AlgorandTestnet -> null
|
||||
HederaTestnet -> null
|
||||
Aurora -> null
|
||||
AuroraTestnet -> null
|
||||
Areon -> null
|
||||
AreonTestnet -> null
|
||||
PulseChain -> null
|
||||
PulseChainTestnet -> null
|
||||
ZkSyncEraTestnet -> null
|
||||
Nexa -> null
|
||||
NexaTestnet -> null
|
||||
Moonbeam -> null
|
||||
MoonbeamTestnet -> null
|
||||
Manta -> null
|
||||
MantaTestnet -> null
|
||||
PolygonZkEVM -> null
|
||||
PolygonZkEVMTestnet -> null
|
||||
Radiant -> null
|
||||
BaseTestnet -> null
|
||||
Moonriver -> null
|
||||
MoonriverTestnet -> null
|
||||
Mantle -> null
|
||||
MantleTestnet -> null
|
||||
Flare -> null
|
||||
FlareTestnet -> null
|
||||
Taraxa -> null
|
||||
TaraxaTestnet -> null
|
||||
Koinos -> null
|
||||
KoinosTestnet -> null
|
||||
Joystream -> null
|
||||
Bittensor -> null
|
||||
Blast -> null
|
||||
BlastTestnet -> null
|
||||
Cyber -> null
|
||||
CyberTestnet -> null
|
||||
InternetComputer -> null
|
||||
SuiTestnet -> null
|
||||
EnergyWebChain -> null
|
||||
EnergyWebChainTestnet -> null
|
||||
EnergyWebX -> null
|
||||
EnergyWebXTestnet -> null
|
||||
Casper -> null
|
||||
CasperTestnet -> null
|
||||
CoreTestnet -> null
|
||||
Unknown -> null
|
||||
Xodex -> null
|
||||
Canxium -> null
|
||||
}
|
||||
|
|
@ -5,11 +5,11 @@ 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.sdk.api.TangemSdkManager
|
||||
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.redux.AppState
|
||||
import com.tangem.tap.domain.sdk.TangemSdkManager
|
||||
import com.tangem.tap.network.exchangeServices.ExchangeService
|
||||
import org.rekotlin.Action
|
||||
import org.rekotlin.Store
|
||||
|
|
|
|||
|
|
@ -1,31 +1,15 @@
|
|||
package com.tangem.tap.proxy.redux
|
||||
|
||||
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.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
|
||||
import com.tangem.tap.domain.walletconnect2.domain.WalletConnectInteractor
|
||||
import org.rekotlin.Action
|
||||
|
||||
sealed interface DaggerGraphAction : Action {
|
||||
|
||||
data class SetActivityDependencies(
|
||||
val testerRouter: TesterRouter,
|
||||
val scanCardUseCase: ScanCardUseCase,
|
||||
val walletRouter: WalletRouter,
|
||||
val walletConnectInteractor: WalletConnectInteractor,
|
||||
val tokenDetailsRouter: TokenDetailsRouter,
|
||||
val cardSdkConfigRepository: CardSdkConfigRepository,
|
||||
val sendRouter: SendRouter,
|
||||
val qrScanningRouter: QrScanningRouter,
|
||||
val emailSender: EmailSender,
|
||||
val stakingRouter: StakingRouter,
|
||||
val pushNotificationsRouter: PushNotificationsRouter,
|
||||
) : DaggerGraphAction
|
||||
}
|
||||
|
|
@ -13,17 +13,9 @@ object DaggerGraphReducer {
|
|||
private fun internalReduce(action: DaggerGraphAction, state: AppState): DaggerGraphState {
|
||||
return when (action) {
|
||||
is DaggerGraphAction.SetActivityDependencies -> state.daggerGraphState.copy(
|
||||
testerRouter = action.testerRouter,
|
||||
scanCardUseCase = action.scanCardUseCase,
|
||||
walletRouter = action.walletRouter,
|
||||
walletConnectInteractor = action.walletConnectInteractor,
|
||||
tokenDetailsRouter = action.tokenDetailsRouter,
|
||||
cardSdkConfigRepository = action.cardSdkConfigRepository,
|
||||
sendRouter = action.sendRouter,
|
||||
qrScanningRouter = action.qrScanningRouter,
|
||||
emailSender = action.emailSender,
|
||||
stakingRouter = action.stakingRouter,
|
||||
pushNotificationsRouter = action.pushNotificationsRouter,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
package com.tangem.tap.proxy.redux
|
||||
|
||||
import com.tangem.TangemSdkLogger
|
||||
import com.tangem.blockchainsdk.BlockchainSDKFactory
|
||||
import com.tangem.blockchainsdk.signer.TransactionSignerFactory
|
||||
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.datasource.local.config.environment.EnvironmentConfigStorage
|
||||
import com.tangem.datasource.local.config.issuers.IssuersConfigStorage
|
||||
import com.tangem.domain.appcurrency.repository.AppCurrencyRepository
|
||||
import com.tangem.domain.apptheme.repository.AppThemeModeRepository
|
||||
import com.tangem.domain.balancehiding.repositories.BalanceHidingRepository
|
||||
|
|
@ -17,43 +16,32 @@ import com.tangem.domain.card.ScanCardUseCase
|
|||
import com.tangem.domain.card.repository.CardRepository
|
||||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.domain.feedback.GetCardInfoUseCase
|
||||
import com.tangem.domain.feedback.SaveBlockchainErrorUseCase
|
||||
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
||||
import com.tangem.domain.onboarding.SaveTwinsOnboardingShownUseCase
|
||||
import com.tangem.domain.onboarding.WasTwinsOnboardingShownUseCase
|
||||
import com.tangem.domain.settings.repositories.SettingsRepository
|
||||
import com.tangem.domain.settings.usercountry.GetUserCountryUseCase
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
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.onboarding.v2.OnboardingV2FeatureToggles
|
||||
import com.tangem.features.onramp.OnrampFeatureToggles
|
||||
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
|
||||
import com.tangem.tap.domain.scanCard.CardScanningFeatureToggles
|
||||
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.home.featuretoggles.HomeFeatureToggles
|
||||
import com.tangem.tap.proxy.AppStateHolder
|
||||
import org.rekotlin.StateType
|
||||
|
||||
data class DaggerGraphState(
|
||||
val testerRouter: TesterRouter? = null,
|
||||
val networkConnectionManager: NetworkConnectionManager? = null,
|
||||
val cardScanningFeatureToggles: CardScanningFeatureToggles? = null,
|
||||
val scanCardUseCase: ScanCardUseCase? = null,
|
||||
val walletRouter: WalletRouter? = null,
|
||||
val walletConnectRepository: LegacyWalletConnectRepository? = null,
|
||||
val walletConnectSessionsRepository: WalletConnectSessionsRepository? = null,
|
||||
val walletConnectInteractor: WalletConnectInteractor? = null,
|
||||
val tokenDetailsRouter: TokenDetailsRouter? = null,
|
||||
val scanCardProcessor: ScanCardProcessor? = null,
|
||||
val cardSdkConfigRepository: CardSdkConfigRepository? = null,
|
||||
val appCurrencyRepository: AppCurrencyRepository? = null,
|
||||
|
|
@ -62,23 +50,16 @@ data class DaggerGraphState(
|
|||
val appThemeModeRepository: AppThemeModeRepository? = null,
|
||||
val balanceHidingRepository: BalanceHidingRepository? = null,
|
||||
val walletsRepository: WalletsRepository? = null,
|
||||
val networksRepository: NetworksRepository? = null,
|
||||
val sendRouter: SendRouter? = null,
|
||||
val qrScanningRouter: QrScanningRouter? = null,
|
||||
val currenciesRepository: CurrenciesRepository? = null,
|
||||
val generalUserWalletsListManager: UserWalletsListManager? = null,
|
||||
val wasTwinsOnboardingShownUseCase: WasTwinsOnboardingShownUseCase? = null,
|
||||
val saveTwinsOnboardingShownUseCase: SaveTwinsOnboardingShownUseCase? = null,
|
||||
val generateWalletNameUseCase: GenerateWalletNameUseCase? = null,
|
||||
val cardRepository: CardRepository? = null,
|
||||
val tangemSdkLogger: TangemSdkLogger? = null,
|
||||
val settingsRepository: SettingsRepository? = null,
|
||||
val blockchainSDKFactory: BlockchainSDKFactory? = null,
|
||||
val emailSender: EmailSender? = null,
|
||||
val saveBlockchainErrorUseCase: SaveBlockchainErrorUseCase? = null,
|
||||
val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase? = null,
|
||||
val getCardInfoUseCase: GetCardInfoUseCase? = null,
|
||||
val assetLoader: AssetLoader? = null,
|
||||
val issuersConfigStorage: IssuersConfigStorage? = null,
|
||||
val stakingRouter: StakingRouter? = null,
|
||||
val urlOpener: UrlOpener? = null,
|
||||
val shareManager: ShareManager? = null,
|
||||
|
|
@ -87,4 +68,7 @@ data class DaggerGraphState(
|
|||
val transactionSignerFactory: TransactionSignerFactory? = null,
|
||||
val homeFeatureToggles: HomeFeatureToggles? = null,
|
||||
val getUserCountryUseCase: GetUserCountryUseCase? = null,
|
||||
val onrampFeatureToggles: OnrampFeatureToggles? = null,
|
||||
val environmentConfigStorage: EnvironmentConfigStorage? = null,
|
||||
val onboardingV2FeatureToggles: OnboardingV2FeatureToggles? = null,
|
||||
) : StateType
|
||||
|
|
@ -11,6 +11,10 @@ import com.tangem.features.disclaimer.api.components.DisclaimerComponent
|
|||
import com.tangem.features.managetokens.component.ManageTokensComponent
|
||||
import com.tangem.features.managetokens.component.ManageTokensSource
|
||||
import com.tangem.features.markets.details.MarketsTokenDetailsComponent
|
||||
import com.tangem.features.onramp.component.BuyCryptoComponent
|
||||
import com.tangem.features.onboarding.v2.entry.OnboardingEntryComponent
|
||||
import com.tangem.features.onramp.component.OnrampComponent
|
||||
import com.tangem.features.onramp.component.SellCryptoComponent
|
||||
import com.tangem.features.pushnotifications.api.navigation.PushNotificationsRouter
|
||||
import com.tangem.features.send.api.navigation.SendRouter
|
||||
import com.tangem.features.staking.api.navigation.StakingRouter
|
||||
|
|
@ -46,6 +50,10 @@ internal class ChildFactory @Inject constructor(
|
|||
private val disclaimerComponentFactory: DisclaimerComponent.Factory,
|
||||
private val manageTokensComponentFactory: ManageTokensComponent.Factory,
|
||||
private val marketsTokenDetailsComponentFactory: MarketsTokenDetailsComponent.Factory,
|
||||
private val onrampComponentFactory: OnrampComponent.Factory,
|
||||
private val buyCryptoComponentFactory: BuyCryptoComponent.Factory,
|
||||
private val sellCryptoComponentFactory: SellCryptoComponent.Factory,
|
||||
private val onboardingEntryComponentFactory: OnboardingEntryComponent.Factory,
|
||||
private val sendRouter: SendRouter,
|
||||
private val tokenDetailsRouter: TokenDetailsRouter,
|
||||
private val walletRouter: WalletRouter,
|
||||
|
|
@ -186,6 +194,34 @@ internal class ChildFactory @Inject constructor(
|
|||
componentFactory = marketsTokenDetailsComponentFactory,
|
||||
)
|
||||
}
|
||||
is AppRoute.Onramp -> {
|
||||
route.asComponentChild(
|
||||
contextProvider = contextProvider(route, contextFactory),
|
||||
params = OnrampComponent.Params(),
|
||||
componentFactory = onrampComponentFactory,
|
||||
)
|
||||
}
|
||||
is AppRoute.BuyCrypto -> {
|
||||
route.asComponentChild(
|
||||
contextProvider = contextProvider(route, contextFactory),
|
||||
params = BuyCryptoComponent.Params(userWalletId = route.userWalletId),
|
||||
componentFactory = buyCryptoComponentFactory,
|
||||
)
|
||||
}
|
||||
is AppRoute.SellCrypto -> {
|
||||
route.asComponentChild(
|
||||
contextProvider = contextProvider(route, contextFactory),
|
||||
params = SellCryptoComponent.Params(userWalletId = route.userWalletId),
|
||||
componentFactory = sellCryptoComponentFactory,
|
||||
)
|
||||
}
|
||||
is AppRoute.Onboarding -> {
|
||||
route.asComponentChild(
|
||||
contextProvider = contextProvider(route, contextFactory),
|
||||
params = OnboardingEntryComponent.Params(route.scanResponse),
|
||||
componentFactory = onboardingEntryComponentFactory,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
1
app/src/main/res/resources.properties
Normal file
1
app/src/main/res/resources.properties
Normal file
|
|
@ -0,0 +1 @@
|
|||
unqualifiedResLocale=en-US
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
|
||||
|
||||
plugins {
|
||||
alias(deps.plugins.kotlin.android) apply false
|
||||
alias(deps.plugins.kotlin.jvm) apply false
|
||||
|
|
@ -20,6 +22,16 @@ interface Injected {
|
|||
val fs: FileSystemOperations
|
||||
}
|
||||
|
||||
// Test Logging
|
||||
subprojects {
|
||||
tasks.withType<Test> {
|
||||
testLogging {
|
||||
exceptionFormat = TestExceptionFormat.FULL
|
||||
showStandardStreams = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val assembleInternalQA by tasks.registering {
|
||||
group = "build"
|
||||
description = "Builds internal APK to 'build/outputs' directory"
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import com.tangem.common.routing.entity.SerializableIntent
|
|||
import com.tangem.core.decompose.navigation.Route
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.markets.TokenMarketParams
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.qrscanning.models.SourceType
|
||||
import com.tangem.domain.staking.model.stakekit.Yield
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
|
|
@ -117,10 +118,6 @@ sealed class AppRoute(val path: String) : Route {
|
|||
) : AppRoute(path = "/details/security"), RouteBundleParams {
|
||||
|
||||
override fun getBundle(): Bundle = bundle(serializer())
|
||||
|
||||
companion object {
|
||||
const val USER_WALLET_ID_KEY = "userWalletId"
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
|
|
@ -288,4 +285,20 @@ sealed class AppRoute(val path: String) : Route {
|
|||
val source: String,
|
||||
)
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data object Onramp : AppRoute(path = "/onramp")
|
||||
|
||||
@Serializable
|
||||
data class BuyCrypto(
|
||||
val userWalletId: UserWalletId,
|
||||
) : AppRoute(path = "/buy_crypto/${userWalletId.stringValue}")
|
||||
|
||||
@Serializable
|
||||
data class SellCrypto(
|
||||
val userWalletId: UserWalletId,
|
||||
) : AppRoute(path = "/sell_crypto/${userWalletId.stringValue}")
|
||||
|
||||
// Onboarding V2
|
||||
data class Onboarding(val scanResponse: ScanResponse) : AppRoute(path = "/onboarding_v2")
|
||||
}
|
||||
|
|
@ -4,10 +4,15 @@ import androidx.compose.foundation.text.KeyboardOptions
|
|||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import com.tangem.common.ui.R
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.common.ui.amountScreen.models.EnterAmountBoundary
|
||||
import com.tangem.common.ui.amountScreen.utils.checkExceedBalance
|
||||
import com.tangem.common.ui.amountScreen.utils.getFiatValue
|
||||
import com.tangem.common.ui.amountScreen.utils.getKeyboardAction
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.core.ui.utils.parseBigDecimal
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.utils.isNullOrZero
|
||||
|
|
@ -22,8 +27,12 @@ import java.math.BigDecimal
|
|||
*/
|
||||
class AmountReduceByTransformer(
|
||||
private val cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
private val minimumTransactionAmount: EnterAmountBoundary?,
|
||||
private val value: ReduceByData,
|
||||
) : Transformer<AmountState> {
|
||||
|
||||
private val maxEnterAmountConverter = MaxEnterAmountConverter()
|
||||
|
||||
override fun transform(prevState: AmountState): AmountState {
|
||||
if (prevState !is AmountState.Data) return prevState
|
||||
|
||||
|
|
@ -40,24 +49,41 @@ class AmountReduceByTransformer(
|
|||
decimals = fiatDecimals,
|
||||
)
|
||||
|
||||
val maxEnterAmount = maxEnterAmountConverter.convert(cryptoCurrencyStatus)
|
||||
|
||||
val checkValue = if (amountTextField.isFiatValue) fiatValue else cryptoValue
|
||||
val isExceedBalance = checkValue.checkExceedBalance(cryptoCurrencyStatus, amountTextField)
|
||||
val isExceedBalance = checkValue.checkExceedBalance(maxEnterAmount, amountTextField)
|
||||
val isLessThanMinimumIfProvided = minimumTransactionAmount?.amount?.let { decimalCryptoValue < it } ?: false
|
||||
val isZero = if (amountTextField.isFiatValue) {
|
||||
decimalFiatValue.isNullOrZero()
|
||||
} else {
|
||||
decimalCryptoValue.isNullOrZero()
|
||||
}
|
||||
val isCheckFailed = isExceedBalance || isLessThanMinimumIfProvided
|
||||
return prevState.copy(
|
||||
isPrimaryButtonEnabled = !isExceedBalance && !isZero,
|
||||
isPrimaryButtonEnabled = !isZero && !isCheckFailed,
|
||||
amountTextField = amountTextField.copy(
|
||||
value = cryptoValue,
|
||||
fiatValue = fiatValue,
|
||||
isError = isExceedBalance,
|
||||
error = resourceReference(R.string.send_validation_amount_exceeds_balance),
|
||||
isError = isCheckFailed,
|
||||
error = when {
|
||||
isExceedBalance -> resourceReference(R.string.send_validation_amount_exceeds_balance)
|
||||
isLessThanMinimumIfProvided -> {
|
||||
val minimumAmount = minimumTransactionAmount
|
||||
?.amount
|
||||
?.format { crypto(cryptoCurrencyStatus.currency) }
|
||||
.orEmpty()
|
||||
resourceReference(
|
||||
R.string.transfer_notification_invalid_minimum_transaction_amount_text,
|
||||
wrappedList(minimumAmount, minimumAmount),
|
||||
)
|
||||
}
|
||||
else -> TextReference.EMPTY
|
||||
},
|
||||
cryptoAmount = amountTextField.cryptoAmount.copy(value = decimalCryptoValue),
|
||||
fiatAmount = amountTextField.fiatAmount.copy(value = decimalFiatValue),
|
||||
keyboardOptions = KeyboardOptions(
|
||||
imeAction = getKeyboardAction(isExceedBalance, decimalCryptoValue),
|
||||
imeAction = getKeyboardAction(isCheckFailed, decimalCryptoValue),
|
||||
keyboardType = KeyboardType.Number,
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -4,11 +4,17 @@ import androidx.compose.foundation.text.KeyboardOptions
|
|||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import com.tangem.common.ui.R
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.common.ui.amountScreen.models.EnterAmountBoundary
|
||||
import com.tangem.common.ui.amountScreen.utils.checkExceedBalance
|
||||
import com.tangem.common.ui.amountScreen.utils.getFiatValue
|
||||
import com.tangem.common.ui.amountScreen.utils.getKeyboardAction
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.core.ui.utils.parseBigDecimal
|
||||
import com.tangem.core.ui.utils.parseToBigDecimal
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.utils.isNullOrZero
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
|
|
@ -22,8 +28,11 @@ import java.math.BigDecimal
|
|||
*/
|
||||
class AmountReduceToTransformer(
|
||||
private val cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
private val minimumTransactionAmount: EnterAmountBoundary?,
|
||||
private val value: BigDecimal,
|
||||
) : Transformer<AmountState> {
|
||||
private val maxEnterAmountConverter = MaxEnterAmountConverter()
|
||||
|
||||
override fun transform(prevState: AmountState): AmountState {
|
||||
if (prevState !is AmountState.Data) return prevState
|
||||
|
||||
|
|
@ -32,26 +41,44 @@ class AmountReduceToTransformer(
|
|||
val fiatDecimals = amountTextField.fiatAmount.decimals
|
||||
|
||||
val cryptoValue = value.parseBigDecimal(cryptoDecimals)
|
||||
val decimalCryptoValue = cryptoValue.parseToBigDecimal(cryptoDecimals)
|
||||
val (fiatValue, decimalFiatValue) = cryptoValue.getFiatValue(
|
||||
fiatRate = cryptoCurrencyStatus.value.fiatRate,
|
||||
isFiatValue = false,
|
||||
decimals = fiatDecimals,
|
||||
)
|
||||
|
||||
val maxEnterAmount = maxEnterAmountConverter.convert(cryptoCurrencyStatus)
|
||||
|
||||
val checkValue = if (amountTextField.isFiatValue) fiatValue else cryptoValue
|
||||
val isExceedBalance = checkValue.checkExceedBalance(cryptoCurrencyStatus, amountTextField)
|
||||
val isExceedBalance = checkValue.checkExceedBalance(maxEnterAmount, amountTextField)
|
||||
val isLessThanMinimumIfProvided = minimumTransactionAmount?.amount?.let { decimalCryptoValue < it } ?: false
|
||||
val isZero = if (amountTextField.isFiatValue) decimalFiatValue.isNullOrZero() else value.isNullOrZero()
|
||||
val isCheckFailed = isExceedBalance || isLessThanMinimumIfProvided
|
||||
return prevState.copy(
|
||||
isPrimaryButtonEnabled = !isExceedBalance && !isZero,
|
||||
isPrimaryButtonEnabled = !isZero && !isCheckFailed,
|
||||
amountTextField = amountTextField.copy(
|
||||
value = cryptoValue,
|
||||
fiatValue = fiatValue,
|
||||
isError = isExceedBalance,
|
||||
error = resourceReference(R.string.send_validation_amount_exceeds_balance),
|
||||
isError = isCheckFailed,
|
||||
error = when {
|
||||
isExceedBalance -> resourceReference(R.string.send_validation_amount_exceeds_balance)
|
||||
isLessThanMinimumIfProvided -> {
|
||||
val minimumAmount = minimumTransactionAmount
|
||||
?.amount
|
||||
?.format { crypto(cryptoCurrencyStatus.currency) }
|
||||
.orEmpty()
|
||||
resourceReference(
|
||||
R.string.transfer_notification_invalid_minimum_transaction_amount_text,
|
||||
wrappedList(minimumAmount, minimumAmount),
|
||||
)
|
||||
}
|
||||
else -> TextReference.EMPTY
|
||||
},
|
||||
cryptoAmount = amountTextField.cryptoAmount.copy(value = value),
|
||||
fiatAmount = amountTextField.fiatAmount.copy(value = decimalFiatValue),
|
||||
keyboardOptions = KeyboardOptions(
|
||||
imeAction = getKeyboardAction(isExceedBalance, value),
|
||||
imeAction = getKeyboardAction(isCheckFailed, decimalCryptoValue),
|
||||
keyboardType = KeyboardType.Number,
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -3,17 +3,19 @@ package com.tangem.common.ui.amountScreen.converters
|
|||
import com.tangem.common.ui.R
|
||||
import com.tangem.common.ui.amountScreen.AmountScreenClickIntents
|
||||
import com.tangem.common.ui.amountScreen.converters.field.AmountFieldConverter
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.common.ui.amountScreen.models.AmountParameters
|
||||
import com.tangem.common.ui.amountScreen.models.AmountSegmentedButtonsConfig
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.common.ui.amountScreen.models.EnterAmountBoundary
|
||||
import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter.formatCryptoAmount
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter.formatFiatAmount
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.fiat
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.utils.Provider
|
||||
import com.tangem.utils.converter.Converter
|
||||
import com.tangem.utils.isNullOrZero
|
||||
|
|
@ -24,17 +26,17 @@ import kotlinx.collections.immutable.persistentListOf
|
|||
*
|
||||
* @property clickIntents amount screen clicks
|
||||
* @property appCurrencyProvider selected app currency provider
|
||||
* @property userWalletProvider selected user wallet provider
|
||||
* @property maxEnterAmount max enter amount data
|
||||
* @property cryptoCurrencyStatusProvider current cryptocurrency status provider
|
||||
* @property iconStateConverter currency icon converter
|
||||
*/
|
||||
class AmountStateConverter(
|
||||
private val clickIntents: AmountScreenClickIntents,
|
||||
private val appCurrencyProvider: Provider<AppCurrency>,
|
||||
private val userWalletProvider: Provider<UserWallet>,
|
||||
private val cryptoCurrencyStatusProvider: Provider<CryptoCurrencyStatus>,
|
||||
private val maxEnterAmount: EnterAmountBoundary,
|
||||
private val iconStateConverter: CryptoCurrencyToIconStateConverter,
|
||||
) : Converter<String, AmountState> {
|
||||
) : Converter<AmountParameters, AmountState> {
|
||||
|
||||
private val amountFieldConverter by lazy(LazyThreadSafetyMode.NONE) {
|
||||
AmountFieldConverter(
|
||||
|
|
@ -44,19 +46,18 @@ class AmountStateConverter(
|
|||
)
|
||||
}
|
||||
|
||||
override fun convert(value: String): AmountState {
|
||||
val userWallet = userWalletProvider()
|
||||
override fun convert(value: AmountParameters): AmountState {
|
||||
val appCurrency = appCurrencyProvider()
|
||||
val status = cryptoCurrencyStatusProvider()
|
||||
val fiat = formatFiatAmount(status.value.fiatAmount, appCurrency.code, appCurrency.symbol)
|
||||
val crypto = formatCryptoAmount(status.value.amount, status.currency.symbol, status.currency.decimals)
|
||||
val fiat = maxEnterAmount.fiatAmount.format { fiat(appCurrency.code, appCurrency.symbol) }
|
||||
val crypto = maxEnterAmount.amount.format { crypto(status.currency) }
|
||||
val noFeeRate = status.value.fiatRate.isNullOrZero()
|
||||
|
||||
return AmountState.Data(
|
||||
walletName = userWallet.name,
|
||||
walletBalance = resourceReference(R.string.common_crypto_fiat_format, wrappedList(crypto, fiat)),
|
||||
title = value.title,
|
||||
availableBalance = resourceReference(R.string.common_crypto_fiat_format, wrappedList(crypto, fiat)),
|
||||
tokenIconState = iconStateConverter.convert(status),
|
||||
amountTextField = amountFieldConverter.convert(value),
|
||||
amountTextField = amountFieldConverter.convert(value.value),
|
||||
isPrimaryButtonEnabled = false,
|
||||
appCurrencyCode = appCurrency.code,
|
||||
segmentedButtonConfig = persistentListOf(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
package com.tangem.common.ui.amountScreen.converters
|
||||
|
||||
import com.tangem.common.ui.amountScreen.models.EnterAmountBoundary
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
||||
/**
|
||||
* Converts [CryptoCurrencyStatus] to [EnterAmountBoundary]
|
||||
*/
|
||||
class MaxEnterAmountConverter : Converter<CryptoCurrencyStatus, EnterAmountBoundary> {
|
||||
|
||||
override fun convert(value: CryptoCurrencyStatus): EnterAmountBoundary {
|
||||
return EnterAmountBoundary(
|
||||
amount = value.value.amount,
|
||||
fiatAmount = value.value.fiatAmount,
|
||||
fiatRate = value.value.fiatRate,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -5,12 +5,16 @@ import androidx.compose.ui.text.input.ImeAction
|
|||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import com.tangem.common.ui.R
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.common.ui.amountScreen.models.EnterAmountBoundary
|
||||
import com.tangem.common.ui.amountScreen.utils.checkExceedBalance
|
||||
import com.tangem.common.ui.amountScreen.utils.getCryptoValue
|
||||
import com.tangem.common.ui.amountScreen.utils.getFiatValue
|
||||
import com.tangem.common.ui.amountScreen.utils.getKeyboardAction
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.core.ui.utils.parseToBigDecimal
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.utils.isNullOrZero
|
||||
|
|
@ -20,11 +24,13 @@ import java.math.BigDecimal
|
|||
/**
|
||||
* Amount value change
|
||||
*
|
||||
* @property cryptoCurrencyStatus current cryptocurrency status
|
||||
* @property maxEnterAmount max amount to enter
|
||||
* @property value amount value
|
||||
*/
|
||||
class AmountFieldChangeTransformer(
|
||||
private val cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
private val maxEnterAmount: EnterAmountBoundary,
|
||||
private val minimumTransactionAmount: EnterAmountBoundary?,
|
||||
private val value: String,
|
||||
) : Transformer<AmountState> {
|
||||
|
||||
|
|
@ -39,36 +45,50 @@ class AmountFieldChangeTransformer(
|
|||
|
||||
val trimmedValue = value.trim()
|
||||
val cryptoValue = trimmedValue.getCryptoValue(
|
||||
fiatRate = cryptoCurrencyStatus.value.fiatRate,
|
||||
fiatRate = maxEnterAmount.fiatRate,
|
||||
isFiatValue = amountTextField.isFiatValue,
|
||||
decimals = cryptoDecimals,
|
||||
)
|
||||
val decimalCryptoValue = cryptoValue.parseToBigDecimal(cryptoDecimals)
|
||||
val (fiatValue, decimalFiatValue) = trimmedValue.getFiatValue(
|
||||
fiatRate = cryptoCurrencyStatus.value.fiatRate,
|
||||
fiatRate = maxEnterAmount.fiatRate,
|
||||
isFiatValue = amountTextField.isFiatValue,
|
||||
decimals = fiatDecimals,
|
||||
)
|
||||
|
||||
val checkValue = if (amountTextField.isFiatValue) fiatValue else cryptoValue
|
||||
val isExceedBalance = checkValue.checkExceedBalance(cryptoCurrencyStatus, amountTextField)
|
||||
val isExceedBalance = checkValue.checkExceedBalance(maxEnterAmount, amountTextField)
|
||||
val isLessThanMinimumIfProvided = minimumTransactionAmount?.amount?.let { decimalCryptoValue < it } ?: false
|
||||
val isZero = if (amountTextField.isFiatValue) {
|
||||
decimalFiatValue.isNullOrZero()
|
||||
} else {
|
||||
decimalCryptoValue.isNullOrZero()
|
||||
}
|
||||
val isCheckFailed = isExceedBalance || isLessThanMinimumIfProvided
|
||||
return prevState.copy(
|
||||
isPrimaryButtonEnabled = !isExceedBalance && !isZero,
|
||||
isPrimaryButtonEnabled = !isZero && !isCheckFailed,
|
||||
amountTextField = amountTextField.copy(
|
||||
value = cryptoValue,
|
||||
fiatValue = fiatValue,
|
||||
isError = isExceedBalance,
|
||||
error = resourceReference(R.string.send_validation_amount_exceeds_balance).takeIf { isExceedBalance }
|
||||
?: TextReference.EMPTY,
|
||||
isError = isCheckFailed,
|
||||
error = when {
|
||||
isExceedBalance -> resourceReference(R.string.send_validation_amount_exceeds_balance)
|
||||
isLessThanMinimumIfProvided -> {
|
||||
val minimumAmount = minimumTransactionAmount
|
||||
?.amount
|
||||
?.format { crypto(cryptoCurrencyStatus.currency) }
|
||||
.orEmpty()
|
||||
resourceReference(
|
||||
R.string.transfer_notification_invalid_minimum_transaction_amount_text,
|
||||
wrappedList(minimumAmount, minimumAmount),
|
||||
)
|
||||
}
|
||||
else -> TextReference.EMPTY
|
||||
},
|
||||
cryptoAmount = amountTextField.cryptoAmount.copy(value = decimalCryptoValue),
|
||||
fiatAmount = amountTextField.fiatAmount.copy(value = decimalFiatValue),
|
||||
keyboardOptions = KeyboardOptions(
|
||||
imeAction = getKeyboardAction(isExceedBalance, decimalCryptoValue),
|
||||
imeAction = getKeyboardAction(isCheckFailed, decimalCryptoValue),
|
||||
keyboardType = KeyboardType.Number,
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,53 +0,0 @@
|
|||
package com.tangem.common.ui.amountScreen.converters.field
|
||||
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.core.ui.utils.parseBigDecimal
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.utils.isNullOrZero
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
import java.math.RoundingMode
|
||||
|
||||
/**
|
||||
* Selects maximum amount value
|
||||
*
|
||||
* @property cryptoCurrencyStatus current cryptocurrency status
|
||||
*/
|
||||
class AmountFieldMaxAmountTransformer(
|
||||
private val cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
) : Transformer<AmountState> {
|
||||
|
||||
override fun transform(prevState: AmountState): AmountState {
|
||||
if (prevState !is AmountState.Data) return prevState
|
||||
|
||||
val amountTextField = prevState.amountTextField
|
||||
|
||||
val cryptoDecimals = amountTextField.cryptoAmount.decimals
|
||||
val fiatDecimals = amountTextField.fiatAmount.decimals
|
||||
val decimalCryptoValue = cryptoCurrencyStatus.value.amount
|
||||
val decimalFiatValue = cryptoCurrencyStatus.value.fiatAmount
|
||||
|
||||
if (decimalCryptoValue.isNullOrZero()) return prevState
|
||||
|
||||
val isDoneActionEnabled = !decimalCryptoValue.isNullOrZero()
|
||||
val cryptoValue = decimalCryptoValue?.parseBigDecimal(cryptoDecimals).orEmpty()
|
||||
val fiatValue = decimalFiatValue?.parseBigDecimal(fiatDecimals, roundingMode = RoundingMode.HALF_UP).orEmpty()
|
||||
return prevState.copy(
|
||||
isPrimaryButtonEnabled = true,
|
||||
amountTextField = amountTextField.copy(
|
||||
isValuePasted = true,
|
||||
value = cryptoValue,
|
||||
fiatValue = fiatValue,
|
||||
isError = false,
|
||||
cryptoAmount = amountTextField.cryptoAmount.copy(value = decimalCryptoValue),
|
||||
fiatAmount = amountTextField.fiatAmount.copy(value = decimalFiatValue),
|
||||
keyboardOptions = KeyboardOptions(
|
||||
imeAction = if (isDoneActionEnabled) ImeAction.Done else ImeAction.None,
|
||||
keyboardType = KeyboardType.Number,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
package com.tangem.common.ui.amountScreen.converters.field
|
||||
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import com.tangem.common.ui.R
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.common.ui.amountScreen.models.EnterAmountBoundary
|
||||
import com.tangem.common.ui.amountScreen.utils.getKeyboardAction
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.core.ui.utils.parseBigDecimal
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.utils.extensions.isZero
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
import java.math.RoundingMode
|
||||
|
||||
/**
|
||||
* Selects maximum amount value
|
||||
*
|
||||
* @property maxAmount maximum enter amount
|
||||
*/
|
||||
class AmountFieldSetMaxAmountTransformer(
|
||||
private val cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
private val maxAmount: EnterAmountBoundary,
|
||||
private val minAmount: EnterAmountBoundary?,
|
||||
) : Transformer<AmountState> {
|
||||
|
||||
override fun transform(prevState: AmountState): AmountState {
|
||||
if (prevState !is AmountState.Data) return prevState
|
||||
|
||||
val amountTextField = prevState.amountTextField
|
||||
|
||||
val cryptoDecimals = amountTextField.cryptoAmount.decimals
|
||||
val fiatDecimals = amountTextField.fiatAmount.decimals
|
||||
val decimalCryptoValue = maxAmount.amount
|
||||
val decimalFiatValue = maxAmount.fiatAmount
|
||||
|
||||
if (decimalCryptoValue == null || decimalCryptoValue.isZero()) return prevState
|
||||
|
||||
val cryptoValue = decimalCryptoValue.parseBigDecimal(cryptoDecimals)
|
||||
val fiatValue = decimalFiatValue?.parseBigDecimal(fiatDecimals, roundingMode = RoundingMode.HALF_UP).orEmpty()
|
||||
val isLessThanMinimumIfProvided = minAmount?.amount?.let { decimalCryptoValue < it } ?: false
|
||||
return prevState.copy(
|
||||
isPrimaryButtonEnabled = !isLessThanMinimumIfProvided,
|
||||
amountTextField = amountTextField.copy(
|
||||
isValuePasted = true,
|
||||
value = cryptoValue,
|
||||
fiatValue = fiatValue,
|
||||
isError = isLessThanMinimumIfProvided,
|
||||
error = when {
|
||||
isLessThanMinimumIfProvided -> {
|
||||
val minimumAmount = minAmount
|
||||
?.amount
|
||||
?.format { crypto(cryptoCurrencyStatus.currency) }
|
||||
.orEmpty()
|
||||
resourceReference(
|
||||
R.string.transfer_notification_invalid_minimum_transaction_amount_text,
|
||||
wrappedList(minimumAmount, minimumAmount),
|
||||
)
|
||||
}
|
||||
else -> TextReference.EMPTY
|
||||
},
|
||||
cryptoAmount = amountTextField.cryptoAmount.copy(value = decimalCryptoValue),
|
||||
fiatAmount = amountTextField.fiatAmount.copy(value = decimalFiatValue),
|
||||
keyboardOptions = KeyboardOptions(
|
||||
imeAction = getKeyboardAction(isLessThanMinimumIfProvided, decimalCryptoValue),
|
||||
keyboardType = KeyboardType.Number,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package com.tangem.common.ui.amountScreen.models
|
||||
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
|
||||
data class AmountParameters(
|
||||
val title: TextReference,
|
||||
val value: String,
|
||||
)
|
||||
|
|
@ -13,8 +13,8 @@ sealed class AmountState {
|
|||
|
||||
/**
|
||||
* @param isPrimaryButtonEnabled indicates if next state button enabled
|
||||
* @param walletName user wallet name
|
||||
* @param walletBalance user crypto currency balance in wallet
|
||||
* @param title title
|
||||
* @param availableBalance user crypto currency balance
|
||||
* @param tokenIconState crypto currency icon state
|
||||
* @param segmentedButtonConfig currency switcher config
|
||||
* @param selectedButton selected currency index
|
||||
|
|
@ -24,8 +24,8 @@ sealed class AmountState {
|
|||
*/
|
||||
data class Data(
|
||||
override val isPrimaryButtonEnabled: Boolean,
|
||||
val walletName: String,
|
||||
val walletBalance: TextReference,
|
||||
val title: TextReference,
|
||||
val availableBalance: TextReference,
|
||||
val tokenIconState: CurrencyIconState,
|
||||
val segmentedButtonConfig: PersistentList<AmountSegmentedButtonsConfig>,
|
||||
val selectedButton: Int,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
package com.tangem.common.ui.amountScreen.models
|
||||
|
||||
import java.math.BigDecimal
|
||||
|
||||
data class EnterAmountBoundary(
|
||||
val amount: BigDecimal? = null,
|
||||
val fiatAmount: BigDecimal? = null,
|
||||
val fiatRate: BigDecimal? = null,
|
||||
) {
|
||||
constructor(
|
||||
amount: BigDecimal? = null,
|
||||
fiatRate: BigDecimal? = null,
|
||||
) : this(
|
||||
amount = amount,
|
||||
fiatAmount = if (amount != null && fiatRate != null) {
|
||||
amount * fiatRate
|
||||
} else {
|
||||
null
|
||||
},
|
||||
fiatRate = fiatRate,
|
||||
)
|
||||
}
|
||||
|
|
@ -17,8 +17,8 @@ object AmountStatePreviewData {
|
|||
|
||||
val amountState = AmountState.Data(
|
||||
isPrimaryButtonEnabled = false,
|
||||
walletName = "Family Wallet",
|
||||
walletBalance = stringReference("2 130,88 USDT (2 129,92 \$)"),
|
||||
title = stringReference("Family Wallet"),
|
||||
availableBalance = stringReference("2 130,88 USDT (2 129,92 \$)"),
|
||||
tokenIconState = CurrencyIconState.Loading,
|
||||
segmentedButtonConfig = persistentListOf(
|
||||
AmountSegmentedButtonsConfig(
|
||||
|
|
|
|||
|
|
@ -19,16 +19,20 @@ import com.tangem.common.ui.amountScreen.models.AmountState
|
|||
import com.tangem.common.ui.amountScreen.preview.AmountStatePreviewData
|
||||
import com.tangem.core.ui.components.ResizableText
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIcon
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.core.ui.format.bigdecimal.anyDecimals
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
import java.math.BigDecimal
|
||||
|
||||
@Composable
|
||||
fun AmountBlock(amountState: AmountState, isClickDisabled: Boolean, isEditingDisabled: Boolean, onClick: () -> Unit) {
|
||||
if (amountState !is AmountState.Data) return
|
||||
val amount = amountState.amountTextField
|
||||
|
||||
val cryptoAmount = BigDecimalFormatter.formatWithSymbol(amount.value, amount.cryptoAmount.currencySymbol)
|
||||
val cryptoAmount = formatWithSymbol(amount.value, amount.cryptoAmount.currencySymbol)
|
||||
val fiatAmount = BigDecimalFormatter.formatFiatAmount(
|
||||
fiatAmount = amount.fiatAmount.value,
|
||||
fiatCurrencySymbol = amount.fiatAmount.currencySymbol,
|
||||
|
|
@ -77,6 +81,9 @@ fun AmountBlock(amountState: AmountState, isClickDisabled: Boolean, isEditingDis
|
|||
}
|
||||
}
|
||||
|
||||
fun formatWithSymbol(amount: String, symbol: String) =
|
||||
BigDecimal.ZERO.format { crypto(symbol, 0).anyDecimals() }.replace("0", amount)
|
||||
|
||||
// region Preview
|
||||
@Preview
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ import com.tangem.core.ui.components.fields.AmountTextField
|
|||
import com.tangem.core.ui.components.fields.visualtransformations.AmountVisualTransformation
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
import com.tangem.core.ui.utils.rememberDecimalFormat
|
||||
|
|
@ -92,11 +94,7 @@ private fun AmountSecondary(amountField: AmountFieldModel, appCurrencyCode: Stri
|
|||
),
|
||||
) {
|
||||
val text = if (amountField.isFiatValue) {
|
||||
BigDecimalFormatter.formatCryptoAmount(
|
||||
cryptoAmount = secondaryAmount.value,
|
||||
cryptoCurrency = secondaryAmount.currencySymbol,
|
||||
decimals = secondaryAmount.decimals,
|
||||
)
|
||||
secondaryAmount.value.format { crypto(secondaryAmount.currencySymbol, secondaryAmount.decimals) }
|
||||
} else {
|
||||
BigDecimalFormatter.formatFiatAmount(
|
||||
fiatAmount = secondaryAmount.value,
|
||||
|
|
@ -140,7 +138,7 @@ private fun AmountFieldError(
|
|||
exit = fadeOut(),
|
||||
modifier = modifier,
|
||||
) {
|
||||
val errorText = remember(this) { error }
|
||||
val errorText = remember(this, error) { error }
|
||||
val color = if (isError) TangemTheme.colors.text.warning else TangemTheme.colors.text.attention
|
||||
Text(
|
||||
text = errorText.resolveReference(),
|
||||
|
|
|
|||
|
|
@ -34,14 +34,14 @@ internal fun LazyListScope.amountField(
|
|||
.background(TangemTheme.colors.background.action),
|
||||
) {
|
||||
Text(
|
||||
text = amountState.walletName,
|
||||
text = amountState.title.resolveReference(),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
modifier = Modifier
|
||||
.padding(top = TangemTheme.dimens.spacing14),
|
||||
)
|
||||
|
||||
val balance = amountState.walletBalance.orMaskWithStars(isBalanceHidden).resolveReference()
|
||||
val balance = amountState.availableBalance.orMaskWithStars(isBalanceHidden).resolveReference()
|
||||
AnimatedContent(
|
||||
targetState = balance,
|
||||
label = "Hide Balance Animation",
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@ package com.tangem.common.ui.amountScreen.utils
|
|||
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import com.tangem.common.ui.amountScreen.models.AmountFieldModel
|
||||
import com.tangem.common.ui.amountScreen.models.EnterAmountBoundary
|
||||
import com.tangem.core.ui.utils.parseBigDecimal
|
||||
import com.tangem.core.ui.utils.parseToBigDecimal
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.utils.isNullOrZero
|
||||
import com.tangem.utils.extensions.isZero
|
||||
import java.math.BigDecimal
|
||||
import java.math.RoundingMode
|
||||
|
||||
|
|
@ -37,11 +37,11 @@ internal fun String.getFiatValue(
|
|||
}
|
||||
|
||||
internal fun String.checkExceedBalance(
|
||||
cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
maxEnterAmount: EnterAmountBoundary,
|
||||
amountTextField: AmountFieldModel,
|
||||
): Boolean {
|
||||
val currencyCryptoAmount = cryptoCurrencyStatus.value.amount ?: BigDecimal.ZERO
|
||||
val currencyFiatAmount = cryptoCurrencyStatus.value.fiatAmount ?: BigDecimal.ZERO
|
||||
val currencyCryptoAmount = maxEnterAmount.amount ?: BigDecimal.ZERO
|
||||
val currencyFiatAmount = maxEnterAmount.fiatAmount ?: BigDecimal.ZERO
|
||||
val fiatDecimal = parseToBigDecimal(amountTextField.fiatAmount.decimals)
|
||||
val cryptoDecimal = parseToBigDecimal(amountTextField.cryptoAmount.decimals)
|
||||
return if (amountTextField.isFiatValue) {
|
||||
|
|
@ -51,8 +51,8 @@ internal fun String.checkExceedBalance(
|
|||
}
|
||||
}
|
||||
|
||||
internal fun getKeyboardAction(isExceedBalance: Boolean, decimalCryptoValue: BigDecimal) =
|
||||
if (!isExceedBalance && !decimalCryptoValue.isNullOrZero()) {
|
||||
internal fun getKeyboardAction(isCheckFailed: Boolean, decimalCryptoValue: BigDecimal) =
|
||||
if (!isCheckFailed && !decimalCryptoValue.isZero()) {
|
||||
ImeAction.Done
|
||||
} else {
|
||||
ImeAction.None
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@ import com.tangem.core.ui.components.notifications.NotificationConfig
|
|||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.core.ui.format.bigdecimal.shorted
|
||||
import java.math.BigDecimal
|
||||
|
||||
sealed class NotificationUM(val config: NotificationConfig) {
|
||||
|
|
@ -45,6 +47,14 @@ sealed class NotificationUM(val config: NotificationConfig) {
|
|||
),
|
||||
)
|
||||
|
||||
data class MinimumSendAmountError(val amount: String) : Error(
|
||||
title = resourceReference(R.string.send_notification_invalid_amount_title),
|
||||
subtitle = resourceReference(
|
||||
R.string.transfer_notification_invalid_minimum_transaction_amount_text,
|
||||
wrappedList(amount, amount),
|
||||
),
|
||||
)
|
||||
|
||||
data class TransactionLimitError(
|
||||
val cryptoCurrency: String,
|
||||
val utxoLimit: String,
|
||||
|
|
@ -267,8 +277,8 @@ sealed class NotificationUM(val config: NotificationConfig) {
|
|||
subtitle = resourceReference(
|
||||
R.string.koinos_insufficient_mana_to_send_koin_description,
|
||||
formatArgs = wrappedList(
|
||||
BigDecimalFormatter.formatCryptoAmountShorted(mana, "", Blockchain.Koinos.decimals()),
|
||||
BigDecimalFormatter.formatCryptoAmountShorted(maxMana, "", Blockchain.Koinos.decimals()),
|
||||
mana.format { crypto("", Blockchain.Koinos.decimals()).shorted() },
|
||||
maxMana.format { crypto("", Blockchain.Koinos.decimals()).shorted() },
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
@ -286,11 +296,9 @@ sealed class NotificationUM(val config: NotificationConfig) {
|
|||
subtitle = resourceReference(
|
||||
R.string.koinos_mana_exceeds_koin_balance_description,
|
||||
formatArgs = wrappedList(
|
||||
BigDecimalFormatter.formatCryptoAmount(
|
||||
availableKoinForTransfer,
|
||||
Blockchain.Koinos.currency,
|
||||
Blockchain.Koinos.decimals(),
|
||||
),
|
||||
availableKoinForTransfer.format {
|
||||
crypto(Blockchain.Koinos.currency, Blockchain.Koinos.decimals())
|
||||
},
|
||||
),
|
||||
),
|
||||
buttonState = NotificationConfig.ButtonsState.PrimaryButtonConfig(
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@ import com.tangem.common.ui.R
|
|||
import com.tangem.common.ui.amountScreen.models.AmountFieldModel
|
||||
import com.tangem.common.ui.amountScreen.utils.getFiatString
|
||||
import com.tangem.core.ui.extensions.networkIconResId
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.core.ui.format.bigdecimal.uncapped
|
||||
import com.tangem.core.ui.utils.parseBigDecimal
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
|
|
@ -65,10 +67,23 @@ object NotificationsFactory {
|
|||
if (!isAccountFunded && reserveAmount != null && reserveAmount > sendingAmount) {
|
||||
add(
|
||||
NotificationUM.Error.ReserveAmount(
|
||||
BigDecimalFormatter.formatCryptoAmount(
|
||||
cryptoAmount = reserveAmount,
|
||||
cryptoCurrency = cryptoCurrency,
|
||||
),
|
||||
reserveAmount.format {
|
||||
crypto(cryptoCurrency)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun MutableList<NotificationUM>.addMinimumAmountErrorNotification(
|
||||
minimumSendAmount: BigDecimal?,
|
||||
sendingAmount: BigDecimal,
|
||||
cryptoCurrency: CryptoCurrency,
|
||||
) {
|
||||
if (minimumSendAmount != null && minimumSendAmount > sendingAmount) {
|
||||
add(
|
||||
NotificationUM.Error.MinimumSendAmountError(
|
||||
amount = minimumSendAmount.format { crypto(cryptoCurrency) },
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -87,10 +102,7 @@ object NotificationsFactory {
|
|||
NotificationUM.Error.TransactionLimitError(
|
||||
cryptoCurrency = cryptoCurrency.name,
|
||||
utxoLimit = utxoLimit.maxLimit.toPlainString(),
|
||||
amountLimit = BigDecimalFormatter.formatCryptoAmount(
|
||||
cryptoAmount = utxoLimit.maxAmount,
|
||||
cryptoCurrency = cryptoCurrency,
|
||||
),
|
||||
amountLimit = utxoLimit.maxAmount.format { crypto(cryptoCurrency) },
|
||||
onConfirmClick = {
|
||||
onReduceClick(
|
||||
utxoLimit.maxAmount,
|
||||
|
|
@ -124,10 +136,7 @@ object NotificationsFactory {
|
|||
if (existentialDeposit != null && diff >= BigDecimal.ZERO && existentialDeposit > diff) {
|
||||
add(
|
||||
NotificationUM.Error.ExistentialDeposit(
|
||||
deposit = BigDecimalFormatter.formatCryptoAmountUncapped(
|
||||
cryptoAmount = existentialDeposit,
|
||||
cryptoCurrency = cryptoCurrency,
|
||||
),
|
||||
deposit = existentialDeposit.format { crypto(cryptoCurrency).uncapped() },
|
||||
onConfirmClick = {
|
||||
onReduceClick(
|
||||
existentialDeposit,
|
||||
|
|
@ -155,10 +164,7 @@ object NotificationsFactory {
|
|||
if (isFeeCoverage) {
|
||||
add(
|
||||
NotificationUM.Warning.FeeCoverageNotification(
|
||||
cryptoAmount = BigDecimalFormatter.formatCryptoAmountUncapped(
|
||||
cryptoAmount = cryptoDiff,
|
||||
cryptoCurrency = cryptoCurrency,
|
||||
),
|
||||
cryptoAmount = cryptoDiff.format { crypto(cryptoCurrency).uncapped() },
|
||||
fiatAmount = getFiatString(
|
||||
value = cryptoDiff,
|
||||
rate = fiatRate,
|
||||
|
|
@ -187,7 +193,7 @@ object NotificationsFactory {
|
|||
if (isExceedsLimit) {
|
||||
add(
|
||||
NotificationUM.Error.MinimumAmountError(
|
||||
amount = dustValue.parseBigDecimal(cryptoCurrencyStatus.currency.decimals),
|
||||
amount = dustValue.format { crypto(cryptoCurrencyStatus.currency) },
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -295,7 +301,7 @@ object NotificationsFactory {
|
|||
dustValue?.let {
|
||||
add(
|
||||
NotificationUM.Error.MinimumAmountError(
|
||||
amount = it.parseBigDecimal(sendingCurrency.decimals),
|
||||
amount = it.format { crypto(sendingCurrency) },
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,13 @@
|
|||
package com.tangem.common.ui.tokens
|
||||
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
|
||||
import com.tangem.core.ui.components.marketprice.PriceChangeType
|
||||
import com.tangem.core.ui.components.marketprice.utils.PriceChangeConverter
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.core.ui.format.bigdecimal.percent
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.staking.model.stakekit.YieldBalance
|
||||
|
|
@ -25,16 +29,20 @@ import java.math.BigDecimal
|
|||
*/
|
||||
class TokenItemStateConverter(
|
||||
private val appCurrency: AppCurrency,
|
||||
private val iconStateProvider: (CryptoCurrencyStatus) -> CurrencyIconState = {
|
||||
CryptoCurrencyToIconStateConverter().convert(it)
|
||||
},
|
||||
private val titleStateProvider: (CryptoCurrencyStatus) -> TokenItemState.TitleState = Companion::createTitleState,
|
||||
private val subtitleStateProvider: (CryptoCurrencyStatus) -> TokenItemState.SubtitleState? = {
|
||||
createSubtitleState(it, appCurrency)
|
||||
},
|
||||
private val fiatAmountStateProvider: (CryptoCurrencyStatus) -> TokenItemState.FiatAmountState? = {
|
||||
createFiatAmountState(it, appCurrency)
|
||||
},
|
||||
private val onItemClick: (CryptoCurrencyStatus) -> Unit,
|
||||
private val onItemLongClick: ((CryptoCurrencyStatus) -> Unit)? = null,
|
||||
) : Converter<CryptoCurrencyStatus, TokenItemState> {
|
||||
|
||||
private val iconStateConverter by lazy(::CryptoCurrencyToIconStateConverter)
|
||||
|
||||
override fun convert(value: CryptoCurrencyStatus): TokenItemState {
|
||||
return when (value.value) {
|
||||
is CryptoCurrencyStatus.Loading -> value.mapToLoadingState()
|
||||
|
|
@ -53,7 +61,7 @@ class TokenItemStateConverter(
|
|||
private fun CryptoCurrencyStatus.mapToLoadingState(): TokenItemState.Loading {
|
||||
return TokenItemState.Loading(
|
||||
id = currency.id.value,
|
||||
iconState = iconStateConverter.convert(value = this),
|
||||
iconState = iconStateProvider(this),
|
||||
titleState = titleStateProvider(this) as TokenItemState.TitleState.Content,
|
||||
subtitleState = requireNotNull(subtitleStateProvider(this)),
|
||||
)
|
||||
|
|
@ -62,13 +70,10 @@ class TokenItemStateConverter(
|
|||
private fun CryptoCurrencyStatus.mapToTokenItemState(): TokenItemState.Content {
|
||||
return TokenItemState.Content(
|
||||
id = currency.id.value,
|
||||
iconState = iconStateConverter.convert(value = this),
|
||||
iconState = iconStateProvider(this),
|
||||
titleState = titleStateProvider(this),
|
||||
subtitleState = requireNotNull(subtitleStateProvider(this)),
|
||||
fiatAmountState = TokenItemState.FiatAmountState.Content(
|
||||
text = getFormattedFiatAmount(),
|
||||
hasStaked = !getStakedBalance().isZero(),
|
||||
),
|
||||
fiatAmountState = requireNotNull(fiatAmountStateProvider(this)),
|
||||
subtitle2State = TokenItemState.Subtitle2State.TextContent(text = getFormattedAmount()),
|
||||
onItemClick = { onItemClick(this) },
|
||||
onItemLongClick = onItemLongClick?.let {
|
||||
|
|
@ -80,23 +85,13 @@ class TokenItemStateConverter(
|
|||
private fun CryptoCurrencyStatus.getFormattedAmount(): String {
|
||||
val amount = value.amount?.plus(getStakedBalance()) ?: return DASH_SIGN
|
||||
|
||||
return BigDecimalFormatter.formatCryptoAmount(amount, currency.symbol, currency.decimals)
|
||||
return amount.format { crypto(currency) }
|
||||
}
|
||||
|
||||
private fun CryptoCurrencyStatus.getFormattedFiatAmount(): String {
|
||||
val fiatYieldBalance = value.fiatRate?.times(getStakedBalance()).orZero()
|
||||
val fiatAmount = value.fiatAmount?.plus(fiatYieldBalance) ?: return DASH_SIGN
|
||||
|
||||
return BigDecimalFormatter.formatFiatAmount(fiatAmount, appCurrency.code, appCurrency.symbol)
|
||||
}
|
||||
|
||||
private fun CryptoCurrencyStatus.getStakedBalance() =
|
||||
(value.yieldBalance as? YieldBalance.Data)?.getTotalWithRewardsStakingBalance().orZero()
|
||||
|
||||
private fun CryptoCurrencyStatus.mapToUnreachableTokenItemState(): TokenItemState.Unreachable {
|
||||
return TokenItemState.Unreachable(
|
||||
id = currency.id.value,
|
||||
iconState = iconStateConverter.convert(value = this),
|
||||
iconState = iconStateProvider(this),
|
||||
titleState = titleStateProvider(this),
|
||||
subtitleState = subtitleStateProvider(this),
|
||||
onItemClick = { onItemClick(this) },
|
||||
|
|
@ -109,7 +104,7 @@ class TokenItemStateConverter(
|
|||
private fun CryptoCurrencyStatus.mapToNoAddressTokenItemState(): TokenItemState.NoAddress {
|
||||
return TokenItemState.NoAddress(
|
||||
id = currency.id.value,
|
||||
iconState = iconStateConverter.convert(this),
|
||||
iconState = iconStateProvider(this),
|
||||
titleState = titleStateProvider(this),
|
||||
subtitleState = subtitleStateProvider(this),
|
||||
onItemLongClick = onItemLongClick?.let {
|
||||
|
|
@ -118,9 +113,9 @@ class TokenItemStateConverter(
|
|||
)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
companion object {
|
||||
|
||||
fun createTitleState(currencyStatus: CryptoCurrencyStatus): TokenItemState.TitleState {
|
||||
private fun createTitleState(currencyStatus: CryptoCurrencyStatus): TokenItemState.TitleState {
|
||||
return when (val value = currencyStatus.value) {
|
||||
is CryptoCurrencyStatus.Loading,
|
||||
is CryptoCurrencyStatus.MissedDerivation,
|
||||
|
|
@ -142,7 +137,7 @@ class TokenItemStateConverter(
|
|||
}
|
||||
}
|
||||
|
||||
fun createSubtitleState(
|
||||
private fun createSubtitleState(
|
||||
currencyStatus: CryptoCurrencyStatus,
|
||||
appCurrency: AppCurrency,
|
||||
): TokenItemState.SubtitleState? {
|
||||
|
|
@ -160,6 +155,29 @@ class TokenItemStateConverter(
|
|||
}
|
||||
}
|
||||
|
||||
private fun createFiatAmountState(
|
||||
status: CryptoCurrencyStatus,
|
||||
appCurrency: AppCurrency,
|
||||
): TokenItemState.FiatAmountState? {
|
||||
return when (status.value) {
|
||||
is CryptoCurrencyStatus.Loaded,
|
||||
is CryptoCurrencyStatus.Custom,
|
||||
is CryptoCurrencyStatus.NoQuote,
|
||||
is CryptoCurrencyStatus.NoAccount,
|
||||
-> {
|
||||
TokenItemState.FiatAmountState.Content(
|
||||
text = status.getFormattedFiatAmount(appCurrency),
|
||||
hasStaked = !status.getStakedBalance().isZero(),
|
||||
)
|
||||
}
|
||||
is CryptoCurrencyStatus.Unreachable,
|
||||
is CryptoCurrencyStatus.NoAmount,
|
||||
is CryptoCurrencyStatus.MissedDerivation,
|
||||
is CryptoCurrencyStatus.Loading,
|
||||
-> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun CryptoCurrencyStatus.getCryptoPriceState(appCurrency: AppCurrency): TokenItemState.SubtitleState {
|
||||
val fiatRate = value.fiatRate
|
||||
val priceChange = value.priceChange
|
||||
|
|
@ -167,10 +185,7 @@ class TokenItemStateConverter(
|
|||
return if (fiatRate != null && priceChange != null) {
|
||||
TokenItemState.SubtitleState.CryptoPriceContent(
|
||||
price = fiatRate.getFormattedCryptoPrice(appCurrency),
|
||||
priceChangePercent = BigDecimalFormatter.formatPercent(
|
||||
percent = priceChange,
|
||||
useAbsoluteValue = true,
|
||||
),
|
||||
priceChangePercent = priceChange.format { percent() },
|
||||
type = priceChange.getPriceChangeType(),
|
||||
)
|
||||
} else {
|
||||
|
|
@ -189,5 +204,15 @@ class TokenItemStateConverter(
|
|||
private fun BigDecimal.getPriceChangeType(): PriceChangeType {
|
||||
return PriceChangeConverter.fromBigDecimal(value = this)
|
||||
}
|
||||
|
||||
fun CryptoCurrencyStatus.getFormattedFiatAmount(appCurrency: AppCurrency): String {
|
||||
val fiatYieldBalance = value.fiatRate?.times(getStakedBalance()).orZero()
|
||||
val fiatAmount = value.fiatAmount?.plus(fiatYieldBalance) ?: return DASH_SIGN
|
||||
|
||||
return BigDecimalFormatter.formatFiatAmount(fiatAmount, appCurrency.code, appCurrency.symbol)
|
||||
}
|
||||
|
||||
private fun CryptoCurrencyStatus.getStakedBalance() =
|
||||
(value.yieldBalance as? YieldBalance.Data)?.getTotalWithRewardsStakingBalance().orZero()
|
||||
}
|
||||
}
|
||||
|
|
@ -78,8 +78,6 @@ sealed class Basic(
|
|||
error = error,
|
||||
)
|
||||
|
||||
class WalletOpened : Basic(event = "Wallet Opened")
|
||||
|
||||
class ButtonSupport(source: AnalyticsParam.ScreensSources) : Basic(
|
||||
event = "Request Support",
|
||||
params = mapOf(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.datasource.api.express.models.response
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import java.math.BigDecimal
|
||||
|
||||
data class ExchangeProvider(
|
||||
@Json(name = "id")
|
||||
|
|
@ -26,6 +27,9 @@ data class ExchangeProvider(
|
|||
|
||||
@Json(name = "recommended")
|
||||
val isRecommended: Boolean = false,
|
||||
|
||||
@Json(name = "slippage")
|
||||
val slippage: BigDecimal?,
|
||||
)
|
||||
|
||||
enum class ExchangeProviderType {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,178 @@
|
|||
package com.tangem.datasource.api.onramp
|
||||
|
||||
import com.tangem.datasource.api.common.response.ApiResponse
|
||||
import com.tangem.datasource.api.onramp.models.common.OnrampDestinationDTO
|
||||
import com.tangem.datasource.api.onramp.models.request.OnrampPairsRequest
|
||||
import com.tangem.datasource.api.onramp.models.response.OnrampDataResponse
|
||||
import com.tangem.datasource.api.onramp.models.response.OnrampQuoteResponse
|
||||
import com.tangem.datasource.api.onramp.models.response.OnrampStatusResponse
|
||||
import com.tangem.datasource.api.onramp.models.response.model.OnrampCountryDTO
|
||||
import com.tangem.datasource.api.onramp.models.response.model.OnrampCurrencyDTO
|
||||
import com.tangem.datasource.api.onramp.models.response.model.OnrampPairDTO
|
||||
import com.tangem.datasource.api.onramp.models.response.model.PaymentMethodDTO
|
||||
|
||||
internal class MockedOnrampApi : OnrampApi {
|
||||
override suspend fun getCurrencies(): ApiResponse<List<OnrampCurrencyDTO>> = ApiResponse.Success(
|
||||
COUNTRIES.map(OnrampCountryDTO::defaultCurrency),
|
||||
)
|
||||
|
||||
override suspend fun getCountries(): ApiResponse<List<OnrampCountryDTO>> = ApiResponse.Success(COUNTRIES + RUSSIA)
|
||||
|
||||
override suspend fun getCountryByIp(): ApiResponse<OnrampCountryDTO> = ApiResponse.Success(RUSSIA)
|
||||
|
||||
override suspend fun getPaymentMethods(): ApiResponse<List<PaymentMethodDTO>> = ApiResponse.Success(
|
||||
listOf(
|
||||
PaymentMethodDTO(id = "google", name = "Google Play", image = ""),
|
||||
PaymentMethodDTO(id = "apple", name = "Apple Pay", image = ""),
|
||||
PaymentMethodDTO(id = "card", name = "Card", image = ""),
|
||||
),
|
||||
)
|
||||
|
||||
override suspend fun getPairs(body: OnrampPairsRequest): ApiResponse<List<OnrampPairDTO>> = ApiResponse.Success(
|
||||
listOf(
|
||||
OnrampPairDTO(
|
||||
fromCurrencyCode = "USD",
|
||||
to = OnrampDestinationDTO(contractAddress = "0xcontract_address", network = "ethereum"),
|
||||
providers = listOf(),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
override suspend fun getQuote(
|
||||
fromCurrencyCode: String,
|
||||
toContractAddress: String,
|
||||
toNetwork: String,
|
||||
paymentMethod: String,
|
||||
countryCode: String,
|
||||
fromAmount: String,
|
||||
toDecimals: Int,
|
||||
providerId: String,
|
||||
): ApiResponse<OnrampQuoteResponse> {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override suspend fun getData(
|
||||
fromCurrencyCode: String,
|
||||
toContractAddress: String,
|
||||
toNetwork: String,
|
||||
paymentMethod: String,
|
||||
countryCode: String,
|
||||
fromAmount: String,
|
||||
toDecimals: Int,
|
||||
providerId: String,
|
||||
toAddress: String,
|
||||
redirectUrl: String,
|
||||
language: String?,
|
||||
theme: String?,
|
||||
requestId: String,
|
||||
): ApiResponse<OnrampDataResponse> {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override suspend fun getStatus(txId: String): ApiResponse<OnrampStatusResponse> {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val RUSSIA = OnrampCountryDTO(
|
||||
name = "Russia",
|
||||
code = "RU",
|
||||
image = "https://hatscripts.github.io/circle-flags/flags/ru.svg",
|
||||
alpha3 = "RUS",
|
||||
continent = "",
|
||||
defaultCurrency = OnrampCurrencyDTO(
|
||||
name = "Russian ruble",
|
||||
code = "RUB",
|
||||
image = "https://hatscripts.github.io/circle-flags/flags/ru.svg",
|
||||
precision = 2,
|
||||
),
|
||||
onrampAvailable = false,
|
||||
)
|
||||
private val COUNTRIES = listOf(
|
||||
OnrampCountryDTO(
|
||||
name = "United States of America",
|
||||
code = "USA",
|
||||
image = "https://hatscripts.github.io/circle-flags/flags/us.svg",
|
||||
alpha3 = "USA",
|
||||
continent = "",
|
||||
defaultCurrency = OnrampCurrencyDTO(
|
||||
name = "US Dollar",
|
||||
code = "USD",
|
||||
image = "https://hatscripts.github.io/circle-flags/flags/us.svg",
|
||||
precision = 2,
|
||||
),
|
||||
onrampAvailable = true,
|
||||
),
|
||||
OnrampCountryDTO(
|
||||
name = "Europe Union",
|
||||
code = "EU",
|
||||
image = "https://hatscripts.github.io/circle-flags/flags/eu.svg",
|
||||
alpha3 = "EUR",
|
||||
continent = "",
|
||||
defaultCurrency = OnrampCurrencyDTO(
|
||||
name = "Euro",
|
||||
code = "EUR",
|
||||
image = "https://hatscripts.github.io/circle-flags/flags/eu.svg",
|
||||
precision = 2,
|
||||
),
|
||||
onrampAvailable = true,
|
||||
),
|
||||
OnrampCountryDTO(
|
||||
name = "Great Britain",
|
||||
code = "GB",
|
||||
image = "https://hatscripts.github.io/circle-flags/flags/gb.svg",
|
||||
alpha3 = "GB",
|
||||
continent = "",
|
||||
defaultCurrency = OnrampCurrencyDTO(
|
||||
name = "British Pound Sterling",
|
||||
code = "GBP",
|
||||
image = "https://hatscripts.github.io/circle-flags/flags/gb.svg",
|
||||
precision = 2,
|
||||
),
|
||||
onrampAvailable = true,
|
||||
),
|
||||
OnrampCountryDTO(
|
||||
name = "CANADA",
|
||||
code = "CA",
|
||||
image = "https://hatscripts.github.io/circle-flags/flags/ca.svg",
|
||||
alpha3 = "CA",
|
||||
continent = "",
|
||||
defaultCurrency = OnrampCurrencyDTO(
|
||||
name = "Canadian Dollar",
|
||||
code = "CAD",
|
||||
image = "https://hatscripts.github.io/circle-flags/flags/ca.svg",
|
||||
precision = 2,
|
||||
),
|
||||
onrampAvailable = true,
|
||||
),
|
||||
OnrampCountryDTO(
|
||||
name = "Hon Kong",
|
||||
code = "HK",
|
||||
image = "https://hatscripts.github.io/circle-flags/flags/hk.svg",
|
||||
alpha3 = "HK",
|
||||
continent = "",
|
||||
defaultCurrency = OnrampCurrencyDTO(
|
||||
name = "Hon Kong Dollar",
|
||||
code = "HKD",
|
||||
image = "https://hatscripts.github.io/circle-flags/flags/hk.svg",
|
||||
precision = 2,
|
||||
),
|
||||
onrampAvailable = true,
|
||||
),
|
||||
OnrampCountryDTO(
|
||||
name = "Australia",
|
||||
code = "AU",
|
||||
image = "https://hatscripts.github.io/circle-flags/flags/au.svg",
|
||||
alpha3 = "AU",
|
||||
continent = "",
|
||||
defaultCurrency = OnrampCurrencyDTO(
|
||||
name = "Australian Dollar",
|
||||
code = "AUD",
|
||||
image = "https://hatscripts.github.io/circle-flags/flags/au.svg",
|
||||
precision = 2,
|
||||
),
|
||||
onrampAvailable = true,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,8 @@ package com.tangem.datasource.api.stakekit
|
|||
import com.tangem.datasource.api.common.response.ApiResponse
|
||||
import com.tangem.datasource.api.stakekit.models.request.*
|
||||
import com.tangem.datasource.api.stakekit.models.response.EnabledYieldsResponse
|
||||
import com.tangem.datasource.api.stakekit.models.response.EnterActionResponse
|
||||
import com.tangem.datasource.api.stakekit.models.response.ActionDTO
|
||||
import com.tangem.datasource.api.stakekit.models.response.GetActionsResponse
|
||||
import com.tangem.datasource.api.stakekit.models.response.model.BalanceDTO
|
||||
import com.tangem.datasource.api.stakekit.models.response.model.YieldBalanceWrapperDTO
|
||||
import com.tangem.datasource.api.stakekit.models.response.model.transaction.StakingGasEstimateDTO
|
||||
|
|
@ -35,14 +36,23 @@ interface StakeKitApi {
|
|||
@Body body: YieldBalanceRequestBody,
|
||||
): ApiResponse<List<BalanceDTO>>
|
||||
|
||||
@GET("actions")
|
||||
suspend fun getActions(
|
||||
@Query("walletAddress") walletAddress: String,
|
||||
@Query("network") network: String,
|
||||
@Query("status") status: String,
|
||||
@Query("sort") sort: String = "createdAtDesc",
|
||||
@Query("limit") limit: Int = 50,
|
||||
): ApiResponse<GetActionsResponse>
|
||||
|
||||
@POST("actions/enter")
|
||||
suspend fun createEnterAction(@Body body: ActionRequestBody): ApiResponse<EnterActionResponse>
|
||||
suspend fun createEnterAction(@Body body: ActionRequestBody): ApiResponse<ActionDTO>
|
||||
|
||||
@POST("actions/exit")
|
||||
suspend fun createExitAction(@Body body: ActionRequestBody): ApiResponse<EnterActionResponse>
|
||||
suspend fun createExitAction(@Body body: ActionRequestBody): ApiResponse<ActionDTO>
|
||||
|
||||
@POST("actions/pending")
|
||||
suspend fun createPendingAction(@Body body: PendingActionRequestBody): ApiResponse<EnterActionResponse>
|
||||
suspend fun createPendingAction(@Body body: PendingActionRequestBody): ApiResponse<ActionDTO>
|
||||
|
||||
@POST("actions/enter/estimate-gas")
|
||||
suspend fun estimateGasOnEnter(@Body body: ActionRequestBody): ApiResponse<StakingGasEstimateDTO>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import org.joda.time.DateTime
|
|||
import java.math.BigDecimal
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class EnterActionResponse(
|
||||
data class ActionDTO(
|
||||
@Json(name = "id")
|
||||
val id: String,
|
||||
@Json(name = "integrationId")
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package com.tangem.datasource.api.stakekit.models.response
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class GetActionsResponse(
|
||||
@Json(name = "data")
|
||||
val data: List<ActionDTO>,
|
||||
@Json(name = "hasNextPage")
|
||||
val hasNextPage: Boolean,
|
||||
@Json(name = "limit")
|
||||
val limit: Int,
|
||||
@Json(name = "page")
|
||||
val page: Int,
|
||||
)
|
||||
|
|
@ -7,33 +7,33 @@ import java.math.BigDecimal
|
|||
@JsonClass(generateAdapter = true)
|
||||
data class YieldDTO(
|
||||
@Json(name = "id")
|
||||
val id: String,
|
||||
val id: String?,
|
||||
@Json(name = "token")
|
||||
val token: TokenDTO,
|
||||
val token: TokenDTO?,
|
||||
@Json(name = "tokens")
|
||||
val tokens: List<TokenDTO>,
|
||||
val tokens: List<TokenDTO>?,
|
||||
@Json(name = "args")
|
||||
val args: ArgsDTO,
|
||||
val args: ArgsDTO?,
|
||||
@Json(name = "status")
|
||||
val status: StatusDTO,
|
||||
val status: StatusDTO?,
|
||||
@Json(name = "apy")
|
||||
val apy: BigDecimal,
|
||||
val apy: BigDecimal?,
|
||||
@Json(name = "rewardRate")
|
||||
val rewardRate: Double,
|
||||
val rewardRate: Double?,
|
||||
@Json(name = "rewardType")
|
||||
val rewardType: RewardTypeDTO,
|
||||
val rewardType: RewardTypeDTO?,
|
||||
@Json(name = "metadata")
|
||||
val metadata: MetadataDTO,
|
||||
val metadata: MetadataDTO?,
|
||||
@Json(name = "validators")
|
||||
val validators: List<ValidatorDTO>,
|
||||
val validators: List<ValidatorDTO>?,
|
||||
@Json(name = "isAvailable")
|
||||
val isAvailable: Boolean,
|
||||
val isAvailable: Boolean?,
|
||||
) {
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class StatusDTO(
|
||||
@Json(name = "enter")
|
||||
val enter: Boolean,
|
||||
val enter: Boolean?,
|
||||
@Json(name = "exit")
|
||||
val exit: Boolean?,
|
||||
)
|
||||
|
|
@ -41,21 +41,21 @@ data class YieldDTO(
|
|||
@JsonClass(generateAdapter = true)
|
||||
data class ArgsDTO(
|
||||
@Json(name = "enter")
|
||||
val enter: Enter,
|
||||
val enter: Enter?,
|
||||
@Json(name = "exit")
|
||||
val exit: Enter?,
|
||||
) {
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class Enter(
|
||||
@Json(name = "addresses")
|
||||
val addresses: Addresses,
|
||||
val addresses: Addresses?,
|
||||
@Json(name = "args")
|
||||
val args: Map<String, AddressArgumentDTO>,
|
||||
val args: Map<String, AddressArgumentDTO>?,
|
||||
) {
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class Addresses(
|
||||
@Json(name = "address")
|
||||
val address: AddressArgumentDTO,
|
||||
val address: AddressArgumentDTO?,
|
||||
@Json(name = "additionalAddresses")
|
||||
val additionalAddresses: Map<String, AddressArgumentDTO>? = null,
|
||||
)
|
||||
|
|
@ -65,11 +65,11 @@ data class YieldDTO(
|
|||
@JsonClass(generateAdapter = true)
|
||||
data class ValidatorDTO(
|
||||
@Json(name = "address")
|
||||
val address: String,
|
||||
val address: String?,
|
||||
@Json(name = "status")
|
||||
val status: ValidatorStatusDTO,
|
||||
val status: ValidatorStatusDTO?,
|
||||
@Json(name = "name")
|
||||
val name: String,
|
||||
val name: String?,
|
||||
@Json(name = "image")
|
||||
val image: String?,
|
||||
@Json(name = "website")
|
||||
|
|
@ -83,7 +83,7 @@ data class YieldDTO(
|
|||
@Json(name = "votingPower")
|
||||
val votingPower: Double?,
|
||||
@Json(name = "preferred")
|
||||
val preferred: Boolean,
|
||||
val preferred: Boolean?,
|
||||
) {
|
||||
@JsonClass(generateAdapter = true)
|
||||
enum class ValidatorStatusDTO {
|
||||
|
|
@ -106,51 +106,51 @@ data class YieldDTO(
|
|||
@JsonClass(generateAdapter = true)
|
||||
data class MetadataDTO(
|
||||
@Json(name = "name")
|
||||
val name: String,
|
||||
val name: String?,
|
||||
@Json(name = "logoURI")
|
||||
val logoUri: String,
|
||||
val logoUri: String?,
|
||||
@Json(name = "description")
|
||||
val description: String,
|
||||
val description: String?,
|
||||
@Json(name = "documentation")
|
||||
val documentation: String?,
|
||||
@Json(name = "gasFeeToken")
|
||||
val gasFeeTokenDTO: TokenDTO,
|
||||
val gasFeeTokenDTO: TokenDTO?,
|
||||
@Json(name = "token")
|
||||
val tokenDTO: TokenDTO,
|
||||
val tokenDTO: TokenDTO?,
|
||||
@Json(name = "tokens")
|
||||
val tokensDTO: List<TokenDTO>,
|
||||
val tokensDTO: List<TokenDTO>?,
|
||||
@Json(name = "type")
|
||||
val type: String,
|
||||
val type: String?,
|
||||
@Json(name = "rewardSchedule")
|
||||
val rewardSchedule: RewardScheduleDTO,
|
||||
val rewardSchedule: RewardScheduleDTO?,
|
||||
@Json(name = "cooldownPeriod")
|
||||
val cooldownPeriod: PeriodDTO?,
|
||||
@Json(name = "warmupPeriod")
|
||||
val warmupPeriod: PeriodDTO,
|
||||
val warmupPeriod: PeriodDTO?,
|
||||
@Json(name = "rewardClaiming")
|
||||
val rewardClaiming: RewardClaimingDTO,
|
||||
val rewardClaiming: RewardClaimingDTO?,
|
||||
@Json(name = "defaultValidator")
|
||||
val defaultValidator: String?,
|
||||
@Json(name = "minimumStake")
|
||||
val minimumStake: Int?,
|
||||
@Json(name = "supportsMultipleValidators")
|
||||
val supportsMultipleValidators: Boolean,
|
||||
val supportsMultipleValidators: Boolean?,
|
||||
@Json(name = "revshare")
|
||||
val revshare: EnabledDTO,
|
||||
val revshare: EnabledDTO?,
|
||||
@Json(name = "fee")
|
||||
val fee: EnabledDTO,
|
||||
val fee: EnabledDTO?,
|
||||
) {
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class PeriodDTO(
|
||||
@Json(name = "days")
|
||||
val days: Int,
|
||||
val days: Int?,
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class EnabledDTO(
|
||||
@Json(name = "enabled")
|
||||
val enabled: Boolean,
|
||||
val enabled: Boolean?,
|
||||
)
|
||||
|
||||
enum class RewardScheduleDTO {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import com.tangem.datasource.api.common.config.managers.ProdApiConfigsManager
|
|||
import com.tangem.datasource.api.common.response.ApiResponseCallAdapterFactory
|
||||
import com.tangem.datasource.api.express.TangemExpressApi
|
||||
import com.tangem.datasource.api.markets.TangemTechMarketsApi
|
||||
import com.tangem.datasource.api.onramp.MockedOnrampApi
|
||||
import com.tangem.datasource.api.onramp.OnrampApi
|
||||
import com.tangem.datasource.api.stakekit.StakeKitApi
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
|
|
@ -98,22 +99,24 @@ internal object NetworkModule {
|
|||
@Provides
|
||||
@Singleton
|
||||
fun provideOnrampApi(
|
||||
@NetworkMoshi moshi: Moshi,
|
||||
@ApplicationContext context: Context,
|
||||
apiConfigsManager: ApiConfigsManager,
|
||||
appLogsStore: AppLogsStore,
|
||||
// @NetworkMoshi moshi: Moshi,
|
||||
// @ApplicationContext context: Context,
|
||||
// apiConfigsManager: ApiConfigsManager,
|
||||
// appLogsStore: AppLogsStore,
|
||||
): OnrampApi {
|
||||
return createApi(
|
||||
id = ApiConfig.ID.Express,
|
||||
moshi = moshi,
|
||||
context = context,
|
||||
apiConfigsManager = apiConfigsManager,
|
||||
clientBuilder = {
|
||||
addInterceptor(
|
||||
NetworkLogsSaveInterceptor(appLogsStore),
|
||||
)
|
||||
},
|
||||
)
|
||||
// TODO: Remove when backend will be ready - [REDACTED_TASK_KEY]
|
||||
return MockedOnrampApi()
|
||||
// return createApi(
|
||||
// id = ApiConfig.ID.Express,
|
||||
// moshi = moshi,
|
||||
// context = context,
|
||||
// apiConfigsManager = apiConfigsManager,
|
||||
// clientBuilder = {
|
||||
// addInterceptor(
|
||||
// NetworkLogsSaveInterceptor(appLogsStore),
|
||||
// )
|
||||
// },
|
||||
// )
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue