From 0b6257796a4db2df37e566118d8e54ca07baa858 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 17 Feb 2025 15:57:47 +0300 Subject: [PATCH 01/33] Updated on 2026-08-14 --- .../main/java/com/tangem/tap/MainActivity.kt | 4 - .../tangem/tap/routing/utils/ChildFactory.kt | 32 +++++- features/send/api/build.gradle.kts | 7 ++ .../tangem/features/send/api/SendComponent.kt | 20 ++++ .../send/api/navigation/SendRouter.kt | 8 -- features/send/impl/build.gradle.kts | 1 + .../send/impl/DefaultSendComponent.kt | 35 ++++++ .../features/send/impl/di/SendModule.kt | 38 +++++++ .../features/send/impl/di/SendRouterModule.kt | 25 ----- .../send/impl/navigation/DefaultSendRouter.kt | 9 +- .../send/impl/navigation/InnerSendRouter.kt | 3 +- .../send/impl/presentation/SendFragment.kt | 78 -------------- .../{viewmodel => model}/SendClickIntents.kt | 2 +- .../SendViewModel.kt => model/SendModel.kt} | 101 +++++++++--------- .../state/SendEventStateFactory.kt | 2 +- .../presentation/state/SendStateFactory.kt | 2 +- .../impl/presentation/state/SendUiState.kt | 2 +- .../impl/presentation/state/StateRouter.kt | 2 +- .../state/confirm/SendNotificationFactory.kt | 2 +- .../presentation/state/fee/FeeConverter.kt | 2 +- .../state/fee/FeeNotificationFactory.kt | 2 +- .../presentation/state/fee/FeeStateFactory.kt | 2 +- .../state/fee/SendFeeCustomFieldConverter.kt | 2 +- .../fee/custom/BitcoinCustomFeeConverter.kt | 2 +- .../fee/custom/EthereumCustomFeeConverter.kt | 2 +- .../custom/EthereumEIPCustomFeeConverter.kt | 2 +- .../EthereumLegacyCustomFeeConverter.kt | 2 +- .../fee/custom/KaspaCustomFeeConverter.kt | 2 +- .../state/previewdata/SendClickIntentsStub.kt | 2 +- .../SendRecipientAddressFieldConverter.kt | 2 +- .../SendRecipientMemoFieldConverter.kt | 2 +- .../recipient/SendRecipientStateConverter.kt | 2 +- .../ui/fee/SendSpeedAndFeeContent.kt | 2 +- .../presentation/ui/fee/SendSpeedSelector.kt | 2 +- .../ui/recipient/SendRecipientContent.kt | 2 +- 35 files changed, 204 insertions(+), 201 deletions(-) create mode 100644 features/send/api/src/main/kotlin/com/tangem/features/send/api/SendComponent.kt delete mode 100644 features/send/api/src/main/kotlin/com/tangem/features/send/api/navigation/SendRouter.kt create mode 100644 features/send/impl/src/main/java/com/tangem/features/send/impl/DefaultSendComponent.kt create mode 100644 features/send/impl/src/main/java/com/tangem/features/send/impl/di/SendModule.kt delete mode 100644 features/send/impl/src/main/java/com/tangem/features/send/impl/di/SendRouterModule.kt delete mode 100644 features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/SendFragment.kt rename features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/{viewmodel => model}/SendClickIntents.kt (96%) rename features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/{viewmodel/SendViewModel.kt => model/SendModel.kt} (94%) diff --git a/app/src/main/java/com/tangem/tap/MainActivity.kt b/app/src/main/java/com/tangem/tap/MainActivity.kt index 0e5b92b3ea..c96a550db8 100644 --- a/app/src/main/java/com/tangem/tap/MainActivity.kt +++ b/app/src/main/java/com/tangem/tap/MainActivity.kt @@ -64,7 +64,6 @@ import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnaly import com.tangem.features.onboarding.v2.OnboardingV2FeatureToggles import com.tangem.features.pushnotifications.api.navigation.PushNotificationsRouter import com.tangem.features.pushnotifications.api.utils.PUSH_PERMISSION -import com.tangem.features.send.api.navigation.SendRouter import com.tangem.features.tokendetails.navigation.TokenDetailsRouter import com.tangem.features.wallet.navigation.WalletRouter import com.tangem.google.GoogleServicesHelper @@ -147,9 +146,6 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac @Inject lateinit var walletConnectInteractor: WalletConnectInteractor - @Inject - lateinit var sendRouter: SendRouter - @Inject lateinit var qrScanningRouter: QrScanningRouter diff --git a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt index ad15758549..10fc7890b2 100644 --- a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt +++ b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt @@ -14,7 +14,7 @@ import com.tangem.features.markets.details.MarketsTokenDetailsComponent import com.tangem.features.onboarding.v2.entry.OnboardingEntryComponent import com.tangem.features.onramp.component.* import com.tangem.features.pushnotifications.api.navigation.PushNotificationsRouter -import com.tangem.features.send.api.navigation.SendRouter +import com.tangem.features.send.api.SendComponent import com.tangem.features.swap.SwapComponent import com.tangem.features.staking.api.StakingComponent import com.tangem.features.tester.api.TesterRouter @@ -58,9 +58,9 @@ internal class ChildFactory @Inject constructor( private val onboardingEntryComponentFactory: OnboardingEntryComponent.Factory, private val welcomeComponentFactory: WelcomeComponent.Factory, private val storiesComponentFactory: StoriesComponent.Factory, + private val sendComponentFactory: SendComponent.Factory, private val stakingComponentFactory: StakingComponent.Factory, private val swapComponentFactory: SwapComponent.Factory, - private val sendRouter: SendRouter, private val tokenDetailsRouter: TokenDetailsRouter, private val walletRouter: WalletRouter, private val qrScanningRouter: QrScanningRouter, @@ -235,10 +235,23 @@ internal class ChildFactory @Inject constructor( componentFactory = swapComponentFactory, ) } + is AppRoute.Send -> { + createComponentChild( + contextProvider = contextProvider(route, contextFactory), + params = SendComponent.Params( + userWalletId = route.userWalletId, + currency = route.currency, + transactionId = route.transactionId, + amount = route.amount, + tag = route.tag, + destinationAddress = route.destinationAddress, + ), + componentFactory = sendComponentFactory, + ) + } is AppRoute.AccessCodeRecovery, is AppRoute.AppCurrencySelector, is AppRoute.SaveWallet, - is AppRoute.Send, is AppRoute.AppSettings, is AppRoute.CardSettings, is AppRoute.DetailsSecurity, @@ -278,7 +291,18 @@ internal class ChildFactory @Inject constructor( route.asFragmentChild(Provider { SaveWalletBottomSheetFragment() }) } is AppRoute.Send -> { - route.asFragmentChild(Provider { sendRouter.getEntryFragment() }) + route.asComponentChild( + contextProvider = contextProvider(route, contextFactory), + params = SendComponent.Params( + userWalletId = route.userWalletId, + currency = route.currency, + transactionId = route.transactionId, + amount = route.amount, + tag = route.tag, + destinationAddress = route.destinationAddress, + ), + componentFactory = sendComponentFactory, + ) } is AppRoute.AppSettings -> { route.asFragmentChild(Provider { AppSettingsFragment() }) diff --git a/features/send/api/build.gradle.kts b/features/send/api/build.gradle.kts index eb561fcf20..b5867a273b 100644 --- a/features/send/api/build.gradle.kts +++ b/features/send/api/build.gradle.kts @@ -10,6 +10,13 @@ android { } dependencies { + /** Core */ + implementation(projects.core.decompose) + implementation(projects.core.ui) + + /** Domain models */ + implementation(projects.domain.wallets.models) + implementation(projects.domain.tokens.models) /** AndroidX */ implementation(deps.androidx.fragment.ktx) diff --git a/features/send/api/src/main/kotlin/com/tangem/features/send/api/SendComponent.kt b/features/send/api/src/main/kotlin/com/tangem/features/send/api/SendComponent.kt new file mode 100644 index 0000000000..987d2e79dc --- /dev/null +++ b/features/send/api/src/main/kotlin/com/tangem/features/send/api/SendComponent.kt @@ -0,0 +1,20 @@ +package com.tangem.features.send.api + +import com.tangem.core.decompose.factory.ComponentFactory +import com.tangem.core.ui.decompose.ComposableContentComponent +import com.tangem.domain.tokens.model.CryptoCurrency +import com.tangem.domain.wallets.models.UserWalletId + +interface SendComponent : ComposableContentComponent { + + data class Params( + val userWalletId: UserWalletId, + val currency: CryptoCurrency, + val transactionId: String? = null, + val amount: String? = null, + val tag: String? = null, + val destinationAddress: String? = null, + ) + + interface Factory : ComponentFactory +} \ No newline at end of file diff --git a/features/send/api/src/main/kotlin/com/tangem/features/send/api/navigation/SendRouter.kt b/features/send/api/src/main/kotlin/com/tangem/features/send/api/navigation/SendRouter.kt deleted file mode 100644 index 286f908ad8..0000000000 --- a/features/send/api/src/main/kotlin/com/tangem/features/send/api/navigation/SendRouter.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.tangem.features.send.api.navigation - -import androidx.fragment.app.Fragment - -interface SendRouter { - - fun getEntryFragment(): Fragment -} \ No newline at end of file diff --git a/features/send/impl/build.gradle.kts b/features/send/impl/build.gradle.kts index 176864f05a..2126c0ac09 100644 --- a/features/send/impl/build.gradle.kts +++ b/features/send/impl/build.gradle.kts @@ -50,6 +50,7 @@ dependencies { implementation(projects.core.analytics) implementation(projects.core.analytics.models) implementation(projects.core.datasource) + implementation(projects.core.decompose) /** Common */ implementation(projects.common.ui) diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/DefaultSendComponent.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/DefaultSendComponent.kt new file mode 100644 index 0000000000..e08ff5f208 --- /dev/null +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/DefaultSendComponent.kt @@ -0,0 +1,35 @@ +package com.tangem.features.send.impl + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.tangem.core.decompose.context.AppComponentContext +import com.tangem.core.decompose.model.getOrCreateModel +import com.tangem.features.send.api.SendComponent +import com.tangem.features.send.impl.presentation.model.SendModel +import com.tangem.features.send.impl.presentation.ui.SendScreen +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject + +internal class DefaultSendComponent @AssistedInject constructor( + @Assisted appComponentContext: AppComponentContext, + @Assisted params: SendComponent.Params, +) : SendComponent, AppComponentContext by appComponentContext { + + private val model: SendModel = getOrCreateModel(params) + + @Composable + override fun Content(modifier: Modifier) { + val currentState = model.stateRouter.currentState.collectAsStateWithLifecycle() + val uiState by model.uiState.collectAsStateWithLifecycle() + + SendScreen(uiState, currentState.value) + } + + @AssistedFactory + interface Factory : SendComponent.Factory { + override fun create(context: AppComponentContext, params: SendComponent.Params): DefaultSendComponent + } +} \ No newline at end of file diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/di/SendModule.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/di/SendModule.kt new file mode 100644 index 0000000000..da5936ec7d --- /dev/null +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/di/SendModule.kt @@ -0,0 +1,38 @@ +package com.tangem.features.send.impl.di + +import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.model.Model +import com.tangem.features.send.api.SendComponent +import com.tangem.features.send.impl.DefaultSendComponent +import com.tangem.features.send.impl.navigation.DefaultSendRouter +import com.tangem.features.send.impl.navigation.InnerSendRouter +import com.tangem.features.send.impl.presentation.model.SendModel +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import dagger.multibindings.ClassKey +import dagger.multibindings.IntoMap + +@Module +@InstallIn(SingletonComponent::class) +internal interface SendModule { + + @Binds + fun bindComponentFactory(factory: DefaultSendComponent.Factory): SendComponent.Factory + + @Binds + @IntoMap + @ClassKey(SendModel::class) + fun bindModel(model: SendModel): Model +} + +@Module +@InstallIn(DecomposeComponent::class) +internal interface SendModelModule { + + @Binds + @ComponentScoped + fun bindRouter(router: DefaultSendRouter): InnerSendRouter +} \ No newline at end of file diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/di/SendRouterModule.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/di/SendRouterModule.kt deleted file mode 100644 index b99742c742..0000000000 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/di/SendRouterModule.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.tangem.features.send.impl.di - -import com.tangem.common.routing.AppRouter -import com.tangem.core.navigation.url.UrlOpener -import com.tangem.features.send.api.navigation.SendRouter -import com.tangem.features.send.impl.navigation.DefaultSendRouter -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.android.components.ActivityComponent -import dagger.hilt.android.scopes.ActivityScoped - -/** - * DI module provides implementation of [SendRouter] - */ -@Module -@InstallIn(ActivityComponent::class) -internal object SendRouterModule { - - @Provides - @ActivityScoped - fun provideSendRouter(appRouter: AppRouter, urlOpener: UrlOpener): SendRouter { - return DefaultSendRouter(appRouter, urlOpener) - } -} \ No newline at end of file diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/navigation/DefaultSendRouter.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/navigation/DefaultSendRouter.kt index ed9f1f7b14..fabef6c208 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/navigation/DefaultSendRouter.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/navigation/DefaultSendRouter.kt @@ -1,21 +1,20 @@ package com.tangem.features.send.impl.navigation -import androidx.fragment.app.Fragment import com.tangem.common.routing.AppRoute import com.tangem.common.routing.AppRouter +import com.tangem.core.decompose.di.ComponentScoped import com.tangem.core.navigation.url.UrlOpener import com.tangem.domain.qrscanning.models.SourceType import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.wallets.models.UserWalletId -import com.tangem.features.send.impl.presentation.SendFragment +import javax.inject.Inject -internal class DefaultSendRouter( +@ComponentScoped +internal class DefaultSendRouter @Inject constructor( private val router: AppRouter, private val urlOpener: UrlOpener, ) : InnerSendRouter { - override fun getEntryFragment(): Fragment = SendFragment.create() - override fun openUrl(url: String) { urlOpener.openUrl(url) } diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/navigation/InnerSendRouter.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/navigation/InnerSendRouter.kt index f061eaba01..9774e13bfe 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/navigation/InnerSendRouter.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/navigation/InnerSendRouter.kt @@ -2,9 +2,8 @@ package com.tangem.features.send.impl.navigation import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.wallets.models.UserWalletId -import com.tangem.features.send.api.navigation.SendRouter -interface InnerSendRouter : SendRouter { +interface InnerSendRouter { /** Open website by [url] */ fun openUrl(url: String) diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/SendFragment.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/SendFragment.kt deleted file mode 100644 index 48899c5eb3..0000000000 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/SendFragment.kt +++ /dev/null @@ -1,78 +0,0 @@ -package com.tangem.features.send.impl.presentation - -import android.os.Bundle -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.ui.Modifier -import androidx.fragment.app.viewModels -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.tangem.common.routing.AppRoute -import com.tangem.common.routing.AppRouter -import com.tangem.core.analytics.api.AnalyticsEventHandler -import com.tangem.core.ui.UiDependencies -import com.tangem.core.ui.screen.ComposeFragment -import com.tangem.features.send.api.navigation.SendRouter -import com.tangem.features.send.impl.navigation.InnerSendRouter -import com.tangem.features.send.impl.presentation.state.StateRouter -import com.tangem.features.send.impl.presentation.ui.SendScreen -import com.tangem.features.send.impl.presentation.viewmodel.SendViewModel -import dagger.hilt.android.AndroidEntryPoint -import javax.inject.Inject - -/** - * Send fragment - */ -@AndroidEntryPoint -internal class SendFragment : ComposeFragment() { - - @Inject - override lateinit var uiDependencies: UiDependencies - - @Inject - lateinit var router: SendRouter - - @Inject - lateinit var appRouter: AppRouter - - @Inject - lateinit var analyticsEventsHandler: AnalyticsEventHandler - - private val viewModel by viewModels() - private val innerSendRouter: InnerSendRouter - get() = requireNotNull(router as? InnerSendRouter) { - "innerSendRouter should be instance of InnerSendRouter" - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - lifecycle.addObserver(viewModel) - - val isEditingDisabled = arguments?.getString(AppRoute.Send.TRANSACTION_ID_KEY) != null - viewModel.setRouter( - innerSendRouter, - StateRouter( - appRouter = appRouter, - isEditingDisabled = isEditingDisabled, - analyticsEventsHandler = analyticsEventsHandler, - ), - ) - } - - @Composable - override fun ScreenContent(modifier: Modifier) { - val currentState = viewModel.stateRouter.currentState.collectAsStateWithLifecycle() - val uiState by viewModel.uiState.collectAsStateWithLifecycle() - - SendScreen(uiState, currentState.value) - } - - override fun onDestroy() { - lifecycle.removeObserver(viewModel) - super.onDestroy() - } - - companion object { - /** Create send fragment instance */ - fun create(): SendFragment = SendFragment() - } -} \ No newline at end of file diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/viewmodel/SendClickIntents.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/model/SendClickIntents.kt similarity index 96% rename from features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/viewmodel/SendClickIntents.kt rename to features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/model/SendClickIntents.kt index e77536f76c..8ec20b06ce 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/viewmodel/SendClickIntents.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/model/SendClickIntents.kt @@ -1,4 +1,4 @@ -package com.tangem.features.send.impl.presentation.viewmodel +package com.tangem.features.send.impl.presentation.model import com.tangem.common.ui.amountScreen.AmountScreenClickIntents import com.tangem.common.ui.notifications.NotificationUM diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/viewmodel/SendViewModel.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/model/SendModel.kt similarity index 94% rename from features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/viewmodel/SendViewModel.kt rename to features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/model/SendModel.kt index 945c953dba..6c91254744 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/viewmodel/SendViewModel.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/model/SendModel.kt @@ -1,20 +1,21 @@ -package com.tangem.features.send.impl.presentation.viewmodel +package com.tangem.features.send.impl.presentation.model -import android.os.Bundle import android.os.SystemClock -import androidx.lifecycle.* +import androidx.compose.runtime.Stable import arrow.core.Either import arrow.core.getOrElse import arrow.core.left import com.tangem.blockchain.common.AmountType import com.tangem.blockchain.common.TransactionData import com.tangem.blockchain.common.transaction.TransactionFee -import com.tangem.common.routing.AppRoute -import com.tangem.common.routing.bundle.unbundle +import com.tangem.common.routing.AppRouter import com.tangem.common.ui.amountScreen.models.AmountState import com.tangem.common.ui.amountScreen.models.EnterAmountBoundary import com.tangem.common.ui.notifications.NotificationUM import com.tangem.core.analytics.api.AnalyticsEventHandler +import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.model.Model +import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.navigation.share.ShareManager import com.tangem.core.ui.utils.parseBigDecimal import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase @@ -47,6 +48,7 @@ import com.tangem.domain.wallets.models.UserWallet import com.tangem.domain.wallets.models.UserWalletId import com.tangem.domain.wallets.usecase.GetUserWalletUseCase import com.tangem.domain.wallets.usecase.GetWalletsUseCase +import com.tangem.features.send.api.SendComponent import com.tangem.features.send.impl.navigation.InnerSendRouter import com.tangem.features.send.impl.presentation.analytics.EnterAddressSource import com.tangem.features.send.impl.presentation.analytics.SendAnalyticEvents @@ -63,7 +65,6 @@ import com.tangem.utils.Provider import com.tangem.utils.coroutines.* import com.tangem.utils.extensions.orZero import com.tangem.utils.extensions.stripZeroPlainString -import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.* import kotlinx.coroutines.flow.* import timber.log.Timber @@ -73,9 +74,10 @@ import javax.inject.Inject import kotlin.properties.Delegates @Suppress("LongParameterList", "TooManyFunctions", "LargeClass") -@HiltViewModel -internal class SendViewModel @Inject constructor( - private val dispatchers: CoroutineDispatcherProvider, +@Stable +@ComponentScoped +internal class SendModel @Inject constructor( + override val dispatchers: CoroutineDispatcherProvider, private val getUserWalletUseCase: GetUserWalletUseCase, private val getCryptoCurrencyStatusSyncUseCase: GetCryptoCurrencyStatusSyncUseCase, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, @@ -109,31 +111,31 @@ internal class SendViewModel @Inject constructor( private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase, private val shareManager: ShareManager, @DelayedWork private val coroutineScope: CoroutineScope, + private val innerRouter: InnerSendRouter, + private val appRouter: AppRouter, + paramsContainer: ParamsContainer, validateTransactionUseCase: ValidateTransactionUseCase, getCurrencyCheckUseCase: GetCurrencyCheckUseCase, isFeeApproximateUseCase: IsFeeApproximateUseCase, getBalanceNotEnoughForFeeWarningUseCase: GetBalanceNotEnoughForFeeWarningUseCase, - savedStateHandle: SavedStateHandle, -) : ViewModel(), DefaultLifecycleObserver, SendClickIntents { +) : Model(), SendClickIntents { - private val userWalletId: UserWalletId = savedStateHandle.get(AppRoute.Send.USER_WALLET_ID_KEY) - ?.unbundle(UserWalletId.serializer()) - ?: error("This screen can't open without `UserWalletId`") + private val params = paramsContainer.require() - private val cryptoCurrency: CryptoCurrency = savedStateHandle.get(AppRoute.Send.CRYPTO_CURRENCY_KEY) - ?.unbundle(CryptoCurrency.serializer()) - ?: error("This screen can't open without `CryptoCurrency`") - - private val transactionId: String? = savedStateHandle[AppRoute.Send.TRANSACTION_ID_KEY] - private val amount: String? = savedStateHandle[AppRoute.Send.AMOUNT_KEY] - private val destinationAddress: String? = savedStateHandle[AppRoute.Send.DESTINATION_ADDRESS_KEY] - private val memo: String? = savedStateHandle[AppRoute.Send.TAG_KEY] + private val userWalletId: UserWalletId = params.userWalletId + private val cryptoCurrency: CryptoCurrency = params.currency + private val transactionId: String? = params.transactionId + private val amount: String? = params.amount + private val destinationAddress: String? = params.destinationAddress + private val memo: String? = params.tag private val selectedAppCurrencyFlow: StateFlow = createSelectedAppCurrencyFlow() - private var innerRouter: InnerSendRouter by Delegates.notNull() - var stateRouter: StateRouter by Delegates.notNull() - private set + val stateRouter = StateRouter( + appRouter = appRouter, + isEditingDisabled = transactionId != null, + analyticsEventsHandler = analyticsEventHandler, + ) private val stateFactory = SendStateFactory( clickIntents = this, @@ -234,33 +236,26 @@ internal class SendViewModel @Inject constructor( subscribeOnCurrencyStatusUpdates() subscribeOnBalanceHidden() getTapHelpPreviewAvailability() - } - override fun onCreate(owner: LifecycleOwner) { onStateActive() } - override fun onCleared() { - super.onCleared() + override fun onDestroy() { + super.onDestroy() balanceHidingJobHolder.cancel() balanceJobHolder.cancel() stateRouter.clear() } - fun setRouter(router: InnerSendRouter, stateRouter: StateRouter) { - innerRouter = router - this.stateRouter = stateRouter - } - private fun subscribeOnQRScannerResult() { listenToQrScanningUseCase(SourceType.SEND) .getOrElse { emptyFlow() } .onEach(::onQrCodeScanned) - .launchIn(viewModelScope) + .launchIn(modelScope) } private fun subscribeOnCurrencyStatusUpdates() { - viewModelScope.launch { + modelScope.launch { getUserWalletUseCase(userWalletId).fold( ifRight = { wallet -> userWallet = wallet @@ -289,7 +284,7 @@ internal class SendViewModel @Inject constructor( .onEach { uiState.value = stateFactory.getOnHideBalanceState(isBalanceHidden = it.isBalanceHidden) } - .launchIn(viewModelScope) + .launchIn(modelScope) .saveIn(balanceHidingJobHolder) } @@ -310,7 +305,7 @@ internal class SendViewModel @Inject constructor( } private fun getTapHelpPreviewAvailability() { - viewModelScope.launch { + modelScope.launch { isTapHelpPreviewEnabled = isSendTapHelpEnabledUseCase().getOrElse { false } } } @@ -362,7 +357,7 @@ internal class SendViewModel @Inject constructor( maybeAppCurrency.getOrElse { AppCurrency.Default } } .stateIn( - scope = viewModelScope, + scope = modelScope, started = SharingStarted.Eagerly, initialValue = AppCurrency.Default, ) @@ -395,13 +390,13 @@ internal class SendViewModel @Inject constructor( private fun getWalletsAndRecent() { getUserWallets() - viewModelScope.launch { + modelScope.launch { getTxHistory() } } private fun getUserWallets() { - viewModelScope.launch { + modelScope.launch { runCatching { waitForDelay(delay = RECENT_LOAD_DELAY) { getWalletsUseCase.invokeSync() @@ -466,7 +461,7 @@ internal class SendViewModel @Inject constructor( else -> Unit } } - .launchIn(viewModelScope) + .launchIn(modelScope) } private fun updateNotifications() { @@ -475,7 +470,7 @@ internal class SendViewModel @Inject constructor( .distinctUntilChanged() .onEach { uiState.value = stateFactory.getSendNotificationState(notifications = it) } .flowOn(dispatchers.main) - .launchIn(viewModelScope) + .launchIn(modelScope) .saveIn(sendNotificationsJobHolder) } @@ -485,7 +480,7 @@ internal class SendViewModel @Inject constructor( .distinctUntilChanged() .onEach { uiState.value = feeStateFactory.getFeeNotificationState(notifications = it) } .flowOn(dispatchers.main) - .launchIn(viewModelScope) + .launchIn(modelScope) .saveIn(feeNotificationsJobHolder) } @@ -573,7 +568,7 @@ internal class SendViewModel @Inject constructor( val cardInfo = getCardInfoUseCase(userWallet.scanResponse).getOrNull() ?: return - viewModelScope.launch { + modelScope.launch { sendFeedbackEmailUseCase(type = FeedbackEmailType.TransactionSendingProblem(cardInfo = cardInfo)) } } @@ -615,7 +610,7 @@ internal class SendViewModel @Inject constructor( } private fun cancelFeeRequest() { - viewModelScope.launch { + modelScope.launch { feeJobHolder.cancel() } } @@ -660,7 +655,7 @@ internal class SendViewModel @Inject constructor( // region recipient state clicks override fun onRecipientAddressValueChange(value: String, type: EnterAddressSource?) { - viewModelScope.launch { + modelScope.launch { if (!checkIfXrpAddressValue(value)) { uiState.value = recipientStateFactory.onRecipientAddressValueChange(value, isValuePasted = type != null) uiState.value = recipientStateFactory.getOnRecipientAddressValidationStarted() @@ -680,7 +675,7 @@ internal class SendViewModel @Inject constructor( } override fun onRecipientMemoValueChange(value: String, isValuePasted: Boolean) { - viewModelScope.launch { + modelScope.launch { if (!checkIfXrpAddressValue(value)) { uiState.value = recipientStateFactory.getOnRecipientMemoValueChange(value, isValuePasted) uiState.value = recipientStateFactory.getOnRecipientAddressValidationStarted() @@ -758,7 +753,7 @@ internal class SendViewModel @Inject constructor( } private fun loadFee() { - viewModelScope.launch { + modelScope.launch { val isShowStatus = uiState.value.feeState?.fee == null if (isShowStatus) { uiState.value = feeStateFactory.onFeeOnLoadingState() @@ -911,7 +906,7 @@ internal class SendViewModel @Inject constructor( reduceAmountBy = uiState.value.sendState?.reduceAmountBy ?: BigDecimal.ZERO, ) - viewModelScope.launch { + modelScope.launch { createTransactionUseCase( amount = receivingAmount.convertToSdkAmount(cryptoCurrency), fee = fee, @@ -969,7 +964,7 @@ internal class SendViewModel @Inject constructor( val receivingUserWallet = userWallets.firstOrNull { it.address == destinationAddress } ?: return - viewModelScope.launch { + modelScope.launch { addCryptoCurrenciesUseCase( userWalletId = receivingUserWallet.userWalletId, cryptoCurrency = cryptoCurrency, @@ -1031,7 +1026,7 @@ internal class SendViewModel @Inject constructor( val noErrorNotifications = sendState.notifications.none { it is NotificationUM.Error } if (!isSuccess && noErrorNotifications) { - viewModelScope.launch { + modelScope.launch { val feeUpdatedState = callFeeUseCase()?.fold( ifRight = { uiState.value = stateFactory.getSendingStateUpdate(isSending = false) @@ -1065,7 +1060,7 @@ internal class SendViewModel @Inject constructor( } private fun setNeverToShowTapHelp() { - viewModelScope.launch { + modelScope.launch { neverShowTapHelpUseCase() } uiState.value = stateFactory.getHiddenTapHelpState() diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendEventStateFactory.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendEventStateFactory.kt index 1258c831fb..9d95fd1d61 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendEventStateFactory.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendEventStateFactory.kt @@ -8,7 +8,7 @@ import com.tangem.domain.transaction.error.SendTransactionError import com.tangem.features.send.impl.presentation.state.fee.FeeSelectorState import com.tangem.features.send.impl.presentation.state.fee.FeeStateFactory import com.tangem.features.send.impl.presentation.state.fee.FeeType -import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents +import com.tangem.features.send.impl.presentation.model.SendClickIntents import com.tangem.utils.Provider import java.math.BigDecimal diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendStateFactory.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendStateFactory.kt index 030e8e81c7..4502a628ec 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendStateFactory.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendStateFactory.kt @@ -18,7 +18,7 @@ import com.tangem.features.send.impl.presentation.state.fee.FeeSelectorState import com.tangem.features.send.impl.presentation.state.fee.SendFeeStateConverter import com.tangem.features.send.impl.presentation.state.fee.checkFeeCoverage import com.tangem.features.send.impl.presentation.state.recipient.SendRecipientStateConverter -import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents +import com.tangem.features.send.impl.presentation.model.SendClickIntents import com.tangem.utils.Provider import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendUiState.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendUiState.kt index ab01823bca..fd0769ac99 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendUiState.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendUiState.kt @@ -10,7 +10,7 @@ import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.features.send.impl.presentation.domain.SendRecipientListContent import com.tangem.features.send.impl.presentation.state.fee.FeeSelectorState import com.tangem.features.send.impl.presentation.state.fields.SendTextField -import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents +import com.tangem.features.send.impl.presentation.model.SendClickIntents import kotlinx.collections.immutable.ImmutableList import java.math.BigDecimal diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/StateRouter.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/StateRouter.kt index 6335c3b154..809f8ada16 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/StateRouter.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/StateRouter.kt @@ -12,7 +12,7 @@ internal class StateRouter( private val analyticsEventsHandler: AnalyticsEventHandler, private val isEditingDisabled: Boolean, ) { - private var mutableCurrentState: MutableStateFlow = MutableStateFlow(getInitState()) + private val mutableCurrentState: MutableStateFlow = MutableStateFlow(getInitState()) val currentState: StateFlow get() = mutableCurrentState diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/confirm/SendNotificationFactory.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/confirm/SendNotificationFactory.kt index ea3dc027aa..87b25f2824 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/confirm/SendNotificationFactory.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/confirm/SendNotificationFactory.kt @@ -34,7 +34,7 @@ import com.tangem.features.send.impl.presentation.state.SendUiState import com.tangem.features.send.impl.presentation.state.SendUiStateType import com.tangem.features.send.impl.presentation.state.StateRouter import com.tangem.features.send.impl.presentation.state.fee.* -import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents +import com.tangem.features.send.impl.presentation.model.SendClickIntents import com.tangem.lib.crypto.BlockchainUtils import com.tangem.lib.crypto.BlockchainUtils.isTezos import com.tangem.utils.Provider diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeConverter.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeConverter.kt index 4c557fecbb..54424e3b07 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeConverter.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeConverter.kt @@ -9,7 +9,7 @@ import com.tangem.features.send.impl.presentation.state.StateRouter import com.tangem.features.send.impl.presentation.state.fee.custom.BitcoinCustomFeeConverter import com.tangem.features.send.impl.presentation.state.fee.custom.EthereumCustomFeeConverter import com.tangem.features.send.impl.presentation.state.fee.custom.KaspaCustomFeeConverter -import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents +import com.tangem.features.send.impl.presentation.model.SendClickIntents import com.tangem.utils.Provider import com.tangem.utils.converter.Converter diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeNotificationFactory.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeNotificationFactory.kt index 96985ed40d..6eaa94816c 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeNotificationFactory.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeNotificationFactory.kt @@ -4,7 +4,7 @@ import com.tangem.common.ui.notifications.NotificationsFactory.addFeeUnreachable import com.tangem.features.send.impl.presentation.state.SendUiState import com.tangem.features.send.impl.presentation.state.SendUiStateType import com.tangem.features.send.impl.presentation.state.StateRouter -import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents +import com.tangem.features.send.impl.presentation.model.SendClickIntents import com.tangem.utils.Provider import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeStateFactory.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeStateFactory.kt index 83e40651a2..0ff24473ac 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeStateFactory.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeStateFactory.kt @@ -14,7 +14,7 @@ import com.tangem.domain.transaction.usecase.IsFeeApproximateUseCase import com.tangem.features.send.impl.presentation.state.SendStates import com.tangem.features.send.impl.presentation.state.SendUiState import com.tangem.features.send.impl.presentation.state.StateRouter -import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents +import com.tangem.features.send.impl.presentation.model.SendClickIntents import com.tangem.utils.Provider import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/SendFeeCustomFieldConverter.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/SendFeeCustomFieldConverter.kt index 23571ac345..71f672a60a 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/SendFeeCustomFieldConverter.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/SendFeeCustomFieldConverter.kt @@ -9,7 +9,7 @@ import com.tangem.features.send.impl.presentation.state.fee.custom.BitcoinCustom import com.tangem.features.send.impl.presentation.state.fee.custom.EthereumCustomFeeConverter import com.tangem.features.send.impl.presentation.state.fee.custom.KaspaCustomFeeConverter import com.tangem.features.send.impl.presentation.state.fields.SendTextField -import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents +import com.tangem.features.send.impl.presentation.model.SendClickIntents import com.tangem.utils.Provider import com.tangem.utils.converter.Converter import kotlinx.collections.immutable.ImmutableList diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/custom/BitcoinCustomFeeConverter.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/custom/BitcoinCustomFeeConverter.kt index 2b7aa838e5..a88f105554 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/custom/BitcoinCustomFeeConverter.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/custom/BitcoinCustomFeeConverter.kt @@ -15,7 +15,7 @@ import com.tangem.features.send.impl.R import com.tangem.features.send.impl.presentation.state.StateRouter import com.tangem.features.send.impl.presentation.state.fee.checkExceedBalance import com.tangem.features.send.impl.presentation.state.fields.SendTextField -import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents +import com.tangem.features.send.impl.presentation.model.SendClickIntents import com.tangem.lib.crypto.BlockchainUtils.isUseBitcoinFeeConverter import com.tangem.utils.Provider import kotlinx.collections.immutable.ImmutableList diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/custom/EthereumCustomFeeConverter.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/custom/EthereumCustomFeeConverter.kt index b65735aeb2..e8695d1e87 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/custom/EthereumCustomFeeConverter.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/custom/EthereumCustomFeeConverter.kt @@ -14,7 +14,7 @@ import com.tangem.features.send.impl.R import com.tangem.features.send.impl.presentation.state.StateRouter import com.tangem.features.send.impl.presentation.state.fee.checkExceedBalance import com.tangem.features.send.impl.presentation.state.fields.SendTextField -import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents +import com.tangem.features.send.impl.presentation.model.SendClickIntents import com.tangem.utils.Provider import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/custom/EthereumEIPCustomFeeConverter.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/custom/EthereumEIPCustomFeeConverter.kt index 14a249de6c..f436dd3051 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/custom/EthereumEIPCustomFeeConverter.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/custom/EthereumEIPCustomFeeConverter.kt @@ -18,7 +18,7 @@ import com.tangem.features.send.impl.presentation.state.fee.custom.EthereumCusto import com.tangem.features.send.impl.presentation.state.fee.custom.EthereumCustomFeeConverter.Companion.GAS_DECIMALS import com.tangem.features.send.impl.presentation.state.fee.custom.EthereumCustomFeeConverter.Companion.GIGA_DECIMALS import com.tangem.features.send.impl.presentation.state.fields.SendTextField -import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents +import com.tangem.features.send.impl.presentation.model.SendClickIntents import com.tangem.utils.Provider import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/custom/EthereumLegacyCustomFeeConverter.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/custom/EthereumLegacyCustomFeeConverter.kt index b4058dd76d..cf8e3881b7 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/custom/EthereumLegacyCustomFeeConverter.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/custom/EthereumLegacyCustomFeeConverter.kt @@ -18,7 +18,7 @@ import com.tangem.features.send.impl.presentation.state.fee.custom.EthereumCusto import com.tangem.features.send.impl.presentation.state.fee.custom.EthereumCustomFeeConverter.Companion.GAS_DECIMALS import com.tangem.features.send.impl.presentation.state.fee.custom.EthereumCustomFeeConverter.Companion.GIGA_DECIMALS import com.tangem.features.send.impl.presentation.state.fields.SendTextField -import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents +import com.tangem.features.send.impl.presentation.model.SendClickIntents import com.tangem.utils.Provider import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/custom/KaspaCustomFeeConverter.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/custom/KaspaCustomFeeConverter.kt index 769bd3ee75..b361065b43 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/custom/KaspaCustomFeeConverter.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/custom/KaspaCustomFeeConverter.kt @@ -13,7 +13,7 @@ import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.features.send.impl.R import com.tangem.features.send.impl.presentation.state.fields.SendTextField -import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents +import com.tangem.features.send.impl.presentation.model.SendClickIntents import com.tangem.utils.Provider import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/previewdata/SendClickIntentsStub.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/previewdata/SendClickIntentsStub.kt index ca5adcd00a..482afa6bda 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/previewdata/SendClickIntentsStub.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/previewdata/SendClickIntentsStub.kt @@ -4,7 +4,7 @@ import com.tangem.common.ui.notifications.NotificationUM import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.features.send.impl.presentation.analytics.EnterAddressSource import com.tangem.features.send.impl.presentation.state.fee.FeeType -import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents +import com.tangem.features.send.impl.presentation.model.SendClickIntents import java.math.BigDecimal @Suppress("TooManyFunctions") diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/recipient/SendRecipientAddressFieldConverter.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/recipient/SendRecipientAddressFieldConverter.kt index 2365bc31e2..a14a303ab2 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/recipient/SendRecipientAddressFieldConverter.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/recipient/SendRecipientAddressFieldConverter.kt @@ -6,7 +6,7 @@ import androidx.compose.ui.text.input.KeyboardType import com.tangem.core.ui.extensions.resourceReference import com.tangem.features.send.impl.R import com.tangem.features.send.impl.presentation.state.fields.SendTextField -import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents +import com.tangem.features.send.impl.presentation.model.SendClickIntents import com.tangem.utils.converter.Converter internal class SendRecipientAddressFieldConverter( diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/recipient/SendRecipientMemoFieldConverter.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/recipient/SendRecipientMemoFieldConverter.kt index 273b6e0b6f..ad0c05fda2 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/recipient/SendRecipientMemoFieldConverter.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/recipient/SendRecipientMemoFieldConverter.kt @@ -9,7 +9,7 @@ import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.tokens.model.Network import com.tangem.features.send.impl.R import com.tangem.features.send.impl.presentation.state.fields.SendTextField -import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents +import com.tangem.features.send.impl.presentation.model.SendClickIntents import com.tangem.utils.Provider import com.tangem.utils.converter.Converter diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/recipient/SendRecipientStateConverter.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/recipient/SendRecipientStateConverter.kt index 9b3f770fcf..7829d19b85 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/recipient/SendRecipientStateConverter.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/recipient/SendRecipientStateConverter.kt @@ -3,7 +3,7 @@ package com.tangem.features.send.impl.presentation.state.recipient import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.features.send.impl.presentation.state.SendStates import com.tangem.features.send.impl.presentation.state.recipient.utils.* -import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents +import com.tangem.features.send.impl.presentation.model.SendClickIntents import com.tangem.utils.Provider import com.tangem.utils.converter.Converter diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedAndFeeContent.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedAndFeeContent.kt index dedf7fa608..cbb85ab5e8 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedAndFeeContent.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedAndFeeContent.kt @@ -20,7 +20,7 @@ import com.tangem.features.send.impl.presentation.state.fee.FeeType import com.tangem.features.send.impl.presentation.state.previewdata.FeeStatePreviewData import com.tangem.features.send.impl.presentation.state.previewdata.SendClickIntentsStub import com.tangem.features.send.impl.presentation.ui.common.notifications -import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents +import com.tangem.features.send.impl.presentation.model.SendClickIntents private const val FEE_SELECTOR_KEY = "FEE_SELECTOR_KEY" private const val FEE_CUSTOM_KEY = "FEE_CUSTOM_KEY" diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedSelector.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedSelector.kt index 2c83d49d07..1e8293ea4b 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedSelector.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedSelector.kt @@ -25,7 +25,7 @@ import com.tangem.features.send.impl.presentation.state.SendStates import com.tangem.features.send.impl.presentation.state.fee.FeeType import com.tangem.features.send.impl.presentation.state.previewdata.FeeStatePreviewData import com.tangem.features.send.impl.presentation.state.previewdata.SendClickIntentsStub -import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents +import com.tangem.features.send.impl.presentation.model.SendClickIntents @Suppress("LongMethod") @Composable diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/recipient/SendRecipientContent.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/recipient/SendRecipientContent.kt index aaa589bde5..4838a3a3e3 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/recipient/SendRecipientContent.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/recipient/SendRecipientContent.kt @@ -32,7 +32,7 @@ import com.tangem.features.send.impl.presentation.state.SendStates import com.tangem.features.send.impl.presentation.state.fields.SendTextField import com.tangem.features.send.impl.presentation.state.previewdata.RecipientStatePreviewData import com.tangem.features.send.impl.presentation.state.previewdata.SendClickIntentsStub -import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents +import com.tangem.features.send.impl.presentation.model.SendClickIntents import kotlinx.collections.immutable.ImmutableList private const val ADDRESS_FIELD_KEY = "ADDRESS_FIELD_KEY" From ed2eca7e8b2dc8d05316a45dd054a1b445e366b8 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 18 Feb 2025 20:05:09 +0300 Subject: [PATCH 02/33] Updated on 2026-08-14 --- .../tap/features/home/DefaultHomeComponent.kt | 74 ++++++++++++++++++ .../tangem/tap/features/home/HomeFragment.kt | 75 ------------------- .../home/{HomeViewModel.kt => HomeModel.kt} | 17 +++-- .../tap/features/home/api/HomeComponent.kt | 9 +++ .../tap/features/home/di/HomeFeatureModule.kt | 25 +++++++ .../tangem/tap/routing/utils/ChildFactory.kt | 18 ++++- 6 files changed, 133 insertions(+), 85 deletions(-) create mode 100644 app/src/main/java/com/tangem/tap/features/home/DefaultHomeComponent.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/home/HomeFragment.kt rename app/src/main/java/com/tangem/tap/features/home/{HomeViewModel.kt => HomeModel.kt} (93%) create mode 100644 app/src/main/java/com/tangem/tap/features/home/api/HomeComponent.kt create mode 100644 app/src/main/java/com/tangem/tap/features/home/di/HomeFeatureModule.kt diff --git a/app/src/main/java/com/tangem/tap/features/home/DefaultHomeComponent.kt b/app/src/main/java/com/tangem/tap/features/home/DefaultHomeComponent.kt new file mode 100644 index 0000000000..a7a853a86a --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/home/DefaultHomeComponent.kt @@ -0,0 +1,74 @@ +package com.tangem.tap.features.home + +import androidx.activity.compose.BackHandler +import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import com.arkivanov.essenty.lifecycle.subscribe +import com.tangem.core.decompose.context.AppComponentContext +import com.tangem.core.decompose.model.getOrCreateModel +import com.tangem.core.ui.components.SystemBarsIconsDisposable +import com.tangem.core.ui.utils.findActivity +import com.tangem.tap.common.redux.AppState +import com.tangem.tap.features.home.api.HomeComponent +import com.tangem.tap.features.home.compose.StoriesScreen +import com.tangem.tap.features.home.redux.HomeAction +import com.tangem.tap.features.home.redux.HomeState +import com.tangem.tap.store +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import org.rekotlin.StoreSubscriber + +@Suppress("UnusedPrivateMember") +internal class DefaultHomeComponent @AssistedInject constructor( + @Assisted appComponentContext: AppComponentContext, + @Assisted params: Unit, +) : HomeComponent, AppComponentContext by appComponentContext, StoreSubscriber { + + private val model: HomeModel = getOrCreateModel() + + private var homeState: MutableState = mutableStateOf(store.state.homeState) + + init { + lifecycle.subscribe( + onCreate = { + store.dispatch(HomeAction.OnCreate) + }, + onStart = { + store.subscribe(subscriber = this) { state -> + state + .skipRepeats { oldState, newState -> oldState.homeState == newState.homeState } + .select(AppState::homeState) + } + }, + onStop = { + store.unsubscribe(this) + }, + ) + } + + @Composable + override fun Content(modifier: Modifier) { + val activity = LocalContext.current.findActivity() + BackHandler(onBack = activity::finish) + SystemBarsIconsDisposable(darkIcons = false) + StoriesScreen( + homeState = homeState, + onScanButtonClick = model::onScanClick, + onShopButtonClick = model::onShopClick, + onSearchTokensClick = model::onSearchClick, + ) + } + + override fun newState(state: HomeState) { + homeState.value = state + } + + @AssistedFactory + interface Factory : HomeComponent.Factory { + override fun create(context: AppComponentContext, params: Unit): DefaultHomeComponent + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/home/HomeFragment.kt b/app/src/main/java/com/tangem/tap/features/home/HomeFragment.kt deleted file mode 100644 index 2379b399a9..0000000000 --- a/app/src/main/java/com/tangem/tap/features/home/HomeFragment.kt +++ /dev/null @@ -1,75 +0,0 @@ -package com.tangem.tap.features.home - -import android.os.Bundle -import androidx.activity.compose.BackHandler -import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.mutableStateOf -import androidx.compose.ui.Modifier -import androidx.fragment.app.viewModels -import com.tangem.core.ui.UiDependencies -import com.tangem.core.ui.components.SystemBarsIconsDisposable -import com.tangem.core.ui.screen.ComposeFragment -import com.tangem.tap.common.redux.AppState -import com.tangem.tap.features.home.compose.StoriesScreen -import com.tangem.tap.features.home.redux.HomeAction -import com.tangem.tap.features.home.redux.HomeState -import com.tangem.tap.store -import dagger.hilt.android.AndroidEntryPoint -import org.rekotlin.StoreSubscriber -import javax.inject.Inject - -@AndroidEntryPoint -internal class HomeFragment : ComposeFragment(), StoreSubscriber { - - @Inject - override lateinit var uiDependencies: UiDependencies - - private var homeState: MutableState = mutableStateOf(store.state.homeState) - - private val viewModel by viewModels() - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - store.dispatch(HomeAction.OnCreate) - } - - @Composable - override fun ScreenContent(modifier: Modifier) { - BackHandler(onBack = requireActivity()::finish) - SystemBarsIconsDisposable(darkIcons = false) - ScreenContent() - } - - override fun onStart() { - super.onStart() - - store.subscribe(subscriber = this) { state -> - state - .skipRepeats { oldState, newState -> oldState.homeState == newState.homeState } - .select(AppState::homeState) - } - } - - override fun onStop() { - super.onStop() - store.unsubscribe(this) - } - - override fun newState(state: HomeState) { - if (activity == null || view == null) return - - homeState.value = state - } - - @Suppress("TopLevelComposableFunctions") - @Composable - private fun ScreenContent() { - StoriesScreen( - homeState = homeState, - onScanButtonClick = viewModel::onScanClick, - onShopButtonClick = viewModel::onShopClick, - onSearchTokensClick = viewModel::onSearchClick, - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/home/HomeViewModel.kt b/app/src/main/java/com/tangem/tap/features/home/HomeModel.kt similarity index 93% rename from app/src/main/java/com/tangem/tap/features/home/HomeViewModel.kt rename to app/src/main/java/com/tangem/tap/features/home/HomeModel.kt index f0b0d760e6..91a72ef7ed 100644 --- a/app/src/main/java/com/tangem/tap/features/home/HomeViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/home/HomeModel.kt @@ -1,7 +1,6 @@ package com.tangem.tap.features.home -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope +import androidx.compose.runtime.Stable import com.google.firebase.analytics.ktx.analytics import com.google.firebase.ktx.Firebase import com.tangem.common.routing.AppRoute @@ -10,6 +9,8 @@ import com.tangem.core.analytics.Analytics import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.models.AnalyticsParam import com.tangem.core.analytics.models.Basic +import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.model.Model import com.tangem.core.navigation.url.UrlOpener import com.tangem.domain.card.ScanCardProcessor import com.tangem.domain.card.repository.CardSdkConfigRepository @@ -30,7 +31,7 @@ import com.tangem.tap.features.home.redux.HIDE_PROGRESS_DELAY import com.tangem.tap.features.home.redux.HomeAction import com.tangem.tap.features.home.redux.HomeMiddleware.NEW_BUY_WALLET_URL import com.tangem.tap.store -import dagger.hilt.android.lifecycle.HiltViewModel +import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.launch @@ -38,8 +39,10 @@ import timber.log.Timber import javax.inject.Inject @Suppress("LongParameterList") -@HiltViewModel -internal class HomeViewModel @Inject constructor( +@Stable +@ComponentScoped +internal class HomeModel @Inject constructor( + override val dispatchers: CoroutineDispatcherProvider, private val scanCardProcessor: ScanCardProcessor, private val generateWalletNameUseCase: GenerateWalletNameUseCase, private val saveWalletUseCase: SaveWalletUseCase, @@ -47,7 +50,7 @@ internal class HomeViewModel @Inject constructor( private val settingsRepository: SettingsRepository, private val urlOpener: UrlOpener, private val analyticsEventHandler: AnalyticsEventHandler, -) : ViewModel() { +) : Model() { private val tangemErrorHandler = TangemTangemErrorsHandler(store) @@ -73,7 +76,7 @@ internal class HomeViewModel @Inject constructor( } private fun scanCard() { - viewModelScope.launch { + modelScope.launch { cardSdkConfigRepository.isBiometricsRequestPolicy = settingsRepository.shouldSaveAccessCodes() scanCardProcessor.scan( diff --git a/app/src/main/java/com/tangem/tap/features/home/api/HomeComponent.kt b/app/src/main/java/com/tangem/tap/features/home/api/HomeComponent.kt new file mode 100644 index 0000000000..0c63e10a1c --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/home/api/HomeComponent.kt @@ -0,0 +1,9 @@ +package com.tangem.tap.features.home.api + +import com.tangem.core.decompose.factory.ComponentFactory +import com.tangem.core.ui.decompose.ComposableContentComponent + +interface HomeComponent : ComposableContentComponent { + + interface Factory : ComponentFactory +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/home/di/HomeFeatureModule.kt b/app/src/main/java/com/tangem/tap/features/home/di/HomeFeatureModule.kt new file mode 100644 index 0000000000..9f92cc5583 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/home/di/HomeFeatureModule.kt @@ -0,0 +1,25 @@ +package com.tangem.tap.features.home.di + +import com.tangem.core.decompose.model.Model +import com.tangem.tap.features.home.DefaultHomeComponent +import com.tangem.tap.features.home.HomeModel +import com.tangem.tap.features.home.api.HomeComponent +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import dagger.multibindings.ClassKey +import dagger.multibindings.IntoMap + +@Module +@InstallIn(SingletonComponent::class) +internal interface HomeFeatureModule { + + @Binds + fun bindFactory(impl: DefaultHomeComponent.Factory): HomeComponent.Factory + + @Binds + @IntoMap + @ClassKey(HomeModel::class) + fun bindModel(model: HomeModel): Model +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt index 10fc7890b2..d8483ca2db 100644 --- a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt +++ b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt @@ -27,7 +27,7 @@ import com.tangem.tap.features.details.ui.cardsettings.coderecovery.AccessCodeRe import com.tangem.tap.features.details.ui.resetcard.ResetCardFragment import com.tangem.tap.features.details.ui.securitymode.SecurityModeFragment import com.tangem.tap.features.details.ui.walletconnect.WalletConnectFragment -import com.tangem.tap.features.home.HomeFragment +import com.tangem.tap.features.home.api.HomeComponent import com.tangem.tap.features.onboarding.products.note.OnboardingNoteFragment import com.tangem.tap.features.onboarding.products.otherCards.OnboardingOtherCardsFragment import com.tangem.tap.features.onboarding.products.twins.ui.OnboardingTwinsFragment @@ -61,6 +61,7 @@ internal class ChildFactory @Inject constructor( private val sendComponentFactory: SendComponent.Factory, private val stakingComponentFactory: StakingComponent.Factory, private val swapComponentFactory: SwapComponent.Factory, + private val homeComponentFactory: HomeComponent.Factory, private val tokenDetailsRouter: TokenDetailsRouter, private val walletRouter: WalletRouter, private val qrScanningRouter: QrScanningRouter, @@ -249,13 +250,20 @@ internal class ChildFactory @Inject constructor( componentFactory = sendComponentFactory, ) } + is AppRoute.Home -> { + createComponentChild( + contextProvider = contextProvider(route, contextFactory), + params = Unit, + componentFactory = homeComponentFactory, + ) + } is AppRoute.AccessCodeRecovery, is AppRoute.AppCurrencySelector, is AppRoute.SaveWallet, is AppRoute.AppSettings, is AppRoute.CardSettings, is AppRoute.DetailsSecurity, - is AppRoute.Home, + is AppRoute.OnboardingNote, is AppRoute.OnboardingOther, is AppRoute.OnboardingTwins, @@ -328,7 +336,11 @@ internal class ChildFactory @Inject constructor( ) } is AppRoute.Home -> { - route.asFragmentChild(Provider { HomeFragment() }) + route.asComponentChild( + contextProvider = contextProvider(route, contextFactory), + params = Unit, + componentFactory = homeComponentFactory, + ) } is AppRoute.ManageTokens -> { val source = when (route.source) { From 89184e29e09cd261550f67cad4e6b26f2a9ede10 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 18 Feb 2025 19:02:14 +0200 Subject: [PATCH 03/33] Updated on 2026-08-14 --- app/build.gradle.kts | 6 +++--- common/ui-charts/build.gradle.kts | 6 +++--- common/ui/build.gradle.kts | 4 ++-- core/datasource/build.gradle.kts | 4 ++-- data/card/build.gradle.kts | 6 +++--- data/common/build.gradle.kts | 4 ++-- data/feedback/build.gradle.kts | 4 ++-- data/manage-tokens/build.gradle.kts | 4 ++-- data/markets/build.gradle.kts | 2 +- data/onramp/build.gradle.kts | 4 ++-- data/qr-scanning/build.gradle.kts | 2 +- data/staking/build.gradle.kts | 4 ++-- data/tokens/build.gradle.kts | 4 ++-- data/transaction/build.gradle.kts | 4 ++-- data/txhistory/build.gradle.kts | 2 +- data/visa/build.gradle.kts | 4 ++-- data/wallets/build.gradle.kts | 2 +- domain/card/build.gradle.kts | 4 ++-- domain/demo/build.gradle.kts | 4 ++-- domain/legacy/build.gradle.kts | 6 +++--- domain/models/build.gradle.kts | 2 +- domain/staking/build.gradle.kts | 2 +- domain/tokens/build.gradle.kts | 2 +- domain/transaction/build.gradle.kts | 6 +++--- domain/wallets/build.gradle.kts | 4 ++-- domain/wallets/models/build.gradle.kts | 2 +- features/details/impl/build.gradle.kts | 4 ++-- features/onboarding-v2/impl/build.gradle.kts | 4 ++-- features/onboarding/build.gradle.kts | 6 +++--- features/qr-scanning/impl/build.gradle.kts | 2 +- features/referral/data/build.gradle.kts | 2 +- features/referral/domain/build.gradle.kts | 2 +- features/send/impl/build.gradle.kts | 4 ++-- features/staking/impl/build.gradle.kts | 4 ++-- features/swap/data/build.gradle.kts | 2 +- features/swap/domain/build.gradle.kts | 4 ++-- features/tester/impl/build.gradle.kts | 2 +- features/tokendetails/impl/build.gradle.kts | 4 ++-- features/wallet/impl/build.gradle.kts | 4 ++-- gradle/dependencies.toml | 19 ------------------- gradle/tangem_dependencies.toml | 18 ++++++++++++++++++ libs/blockchain-sdk/build.gradle.kts | 4 ++-- libs/crypto/build.gradle.kts | 2 +- libs/tangem-sdk-api/build.gradle.kts | 4 ++-- plugins/configuration/settings.gradle.kts | 3 +++ settings.gradle.kts | 4 ++++ 46 files changed, 101 insertions(+), 95 deletions(-) create mode 100644 gradle/tangem_dependencies.toml diff --git a/app/build.gradle.kts b/app/build.gradle.kts index cce042451f..f3177619a4 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -222,11 +222,11 @@ dependencies { exclude(group = "com.google.protobuf", module = "protobuf-javalite") } /** Tangem libraries */ - implementation(deps.tangem.blockchain) { + implementation(tangemDeps.blockchain) { exclude(module = "joda-time") } - implementation(deps.tangem.card.core) - implementation(deps.tangem.card.android) { + implementation(tangemDeps.card.core) + implementation(tangemDeps.card.android) { exclude(module = "joda-time") } diff --git a/common/ui-charts/build.gradle.kts b/common/ui-charts/build.gradle.kts index 58bf27c3a5..0520d97bb3 100644 --- a/common/ui-charts/build.gradle.kts +++ b/common/ui-charts/build.gradle.kts @@ -13,9 +13,9 @@ dependencies { implementation(projects.core.ui) /** Compose */ - implementation(deps.tangem.vico.core) - implementation(deps.tangem.vico.compose) - implementation(deps.tangem.vico.compose.m3) + implementation(tangemDeps.vico.core) + implementation(tangemDeps.vico.compose) + implementation(tangemDeps.vico.compose.m3) implementation(deps.lifecycle.compose) implementation(deps.compose.foundation) diff --git a/common/ui/build.gradle.kts b/common/ui/build.gradle.kts index 709c410a9f..6a6f96f728 100644 --- a/common/ui/build.gradle.kts +++ b/common/ui/build.gradle.kts @@ -38,8 +38,8 @@ dependencies { implementation(projects.domain.onramp.models) implementation(projects.domain.promo.models) - implementation(deps.tangem.card.core) - implementation(deps.tangem.blockchain) { + implementation(tangemDeps.card.core) + implementation(tangemDeps.blockchain) { exclude(module = "joda-time") } } \ No newline at end of file diff --git a/core/datasource/build.gradle.kts b/core/datasource/build.gradle.kts index 3c417c187c..2e43145350 100644 --- a/core/datasource/build.gradle.kts +++ b/core/datasource/build.gradle.kts @@ -34,8 +34,8 @@ dependencies { implementation(projects.domain.models) /** Tangem libraries */ - implementation(deps.tangem.blockchain) - implementation(deps.tangem.card.core) + implementation(tangemDeps.blockchain) + implementation(tangemDeps.card.core) /** DI */ implementation(deps.hilt.android) diff --git a/data/card/build.gradle.kts b/data/card/build.gradle.kts index eb80b3d8cf..6d546bc04d 100644 --- a/data/card/build.gradle.kts +++ b/data/card/build.gradle.kts @@ -13,15 +13,15 @@ android { dependencies { implementation(deps.androidx.datastore) - implementation(deps.tangem.blockchain) { + implementation(tangemDeps.blockchain) { exclude(module = "joda-time") } implementation(deps.hilt.android) kapt(deps.hilt.kapt) - implementation(deps.tangem.card.android) - implementation(deps.tangem.card.core) + implementation(tangemDeps.card.android) + implementation(tangemDeps.card.core) implementation(projects.core.datasource) implementation(projects.core.utils) diff --git a/data/common/build.gradle.kts b/data/common/build.gradle.kts index 5a5b6c1d85..96dc4861ca 100644 --- a/data/common/build.gradle.kts +++ b/data/common/build.gradle.kts @@ -19,8 +19,8 @@ dependencies { implementation(projects.domain.tokens.models) /* Libs - SDK */ - implementation(deps.tangem.blockchain) - implementation(deps.tangem.card.core) + implementation(tangemDeps.blockchain) + implementation(tangemDeps.card.core) implementation(projects.libs.blockchainSdk) /* DI */ diff --git a/data/feedback/build.gradle.kts b/data/feedback/build.gradle.kts index 5f75809008..42c689a596 100644 --- a/data/feedback/build.gradle.kts +++ b/data/feedback/build.gradle.kts @@ -21,8 +21,8 @@ dependencies { // endregion // region Tangem libraries - implementation(deps.tangem.blockchain) - implementation(deps.tangem.card.core) + implementation(tangemDeps.blockchain) + implementation(tangemDeps.card.core) // endregion // Other libraries diff --git a/data/manage-tokens/build.gradle.kts b/data/manage-tokens/build.gradle.kts index a8373e38ff..d303cffc3f 100644 --- a/data/manage-tokens/build.gradle.kts +++ b/data/manage-tokens/build.gradle.kts @@ -33,8 +33,8 @@ dependencies { implementation(projects.libs.blockchainSdk) /** Tangem SDKs */ - implementation(deps.tangem.blockchain) - implementation(deps.tangem.card.core) + implementation(tangemDeps.blockchain) + implementation(tangemDeps.card.core) /** AndroidX */ implementation(deps.androidx.datastore) diff --git a/data/markets/build.gradle.kts b/data/markets/build.gradle.kts index 9e8f4d07a7..9f3c3fc995 100644 --- a/data/markets/build.gradle.kts +++ b/data/markets/build.gradle.kts @@ -41,7 +41,7 @@ dependencies { implementation(deps.moshi) implementation(deps.moshi.kotlin) implementation(deps.timber) - implementation(deps.tangem.blockchain) + implementation(tangemDeps.blockchain) kaptForObfuscatingVariants(deps.moshi.kotlin.codegen) kaptForObfuscatingVariants(deps.retrofit.response.type.keeper) // endregion diff --git a/data/onramp/build.gradle.kts b/data/onramp/build.gradle.kts index dd8b614228..fc4b8695b8 100644 --- a/data/onramp/build.gradle.kts +++ b/data/onramp/build.gradle.kts @@ -52,8 +52,8 @@ dependencies { implementation(projects.libs.blockchainSdk) implementation(projects.libs.crypto) - implementation(deps.tangem.card.core) - implementation(deps.tangem.blockchain) { + implementation(tangemDeps.card.core) + implementation(tangemDeps.blockchain) { exclude(module = "joda-time") } diff --git a/data/qr-scanning/build.gradle.kts b/data/qr-scanning/build.gradle.kts index 1c801589b7..a422fdbd4a 100644 --- a/data/qr-scanning/build.gradle.kts +++ b/data/qr-scanning/build.gradle.kts @@ -20,7 +20,7 @@ dependencies { implementation(projects.core.ui) /** SdK */ - implementation(deps.tangem.blockchain) + implementation(tangemDeps.blockchain) /** DI */ implementation(deps.hilt.android) diff --git a/data/staking/build.gradle.kts b/data/staking/build.gradle.kts index 511b6f79b0..ee2849d585 100644 --- a/data/staking/build.gradle.kts +++ b/data/staking/build.gradle.kts @@ -54,8 +54,8 @@ dependencies { implementation(projects.libs.blockchainSdk) implementation(projects.libs.crypto) - implementation(deps.tangem.card.core) - implementation(deps.tangem.blockchain) { + implementation(tangemDeps.card.core) + implementation(tangemDeps.blockchain) { exclude(module = "joda-time") } diff --git a/data/tokens/build.gradle.kts b/data/tokens/build.gradle.kts index b268688860..003cc83849 100644 --- a/data/tokens/build.gradle.kts +++ b/data/tokens/build.gradle.kts @@ -33,8 +33,8 @@ dependencies { implementation(projects.libs.blockchainSdk) /** Tangem SDKs */ - implementation(deps.tangem.blockchain) - implementation(deps.tangem.card.core) + implementation(tangemDeps.blockchain) + implementation(tangemDeps.card.core) /** AndroidX */ implementation(deps.androidx.datastore) diff --git a/data/transaction/build.gradle.kts b/data/transaction/build.gradle.kts index 709f743912..0426e68bbc 100644 --- a/data/transaction/build.gradle.kts +++ b/data/transaction/build.gradle.kts @@ -13,8 +13,8 @@ android { dependencies { /** Tangem SDKs */ - implementation(deps.tangem.blockchain) - implementation(deps.tangem.card.core) + implementation(tangemDeps.blockchain) + implementation(tangemDeps.card.core) /** Core */ implementation(projects.core.datasource) diff --git a/data/txhistory/build.gradle.kts b/data/txhistory/build.gradle.kts index 3a8e769a69..23bb1bd73d 100644 --- a/data/txhistory/build.gradle.kts +++ b/data/txhistory/build.gradle.kts @@ -25,7 +25,7 @@ dependencies { implementation(deps.androidx.paging.runtime) implementation(deps.timber) implementation(deps.jodatime) - implementation(deps.tangem.blockchain) + implementation(tangemDeps.blockchain) implementation(deps.hilt.core) kapt(deps.hilt.kapt) diff --git a/data/visa/build.gradle.kts b/data/visa/build.gradle.kts index 5a74bcefe0..b2f273b514 100644 --- a/data/visa/build.gradle.kts +++ b/data/visa/build.gradle.kts @@ -43,8 +43,8 @@ dependencies { kaptForObfuscatingVariants(deps.retrofit.response.type.keeper) /** Libs - Tangem */ - implementation(deps.tangem.blockchain) - implementation(deps.tangem.card.core) + implementation(tangemDeps.blockchain) + implementation(tangemDeps.card.core) /** DI */ implementation(deps.hilt.core) diff --git a/data/wallets/build.gradle.kts b/data/wallets/build.gradle.kts index 2f37436631..46c3ad34e3 100644 --- a/data/wallets/build.gradle.kts +++ b/data/wallets/build.gradle.kts @@ -13,7 +13,7 @@ android { dependencies { /** Tangem libraries */ - implementation(deps.tangem.blockchain) // android-library + implementation(tangemDeps.blockchain) // android-library /** Core */ implementation(projects.core.datasource) diff --git a/domain/card/build.gradle.kts b/domain/card/build.gradle.kts index d317bafbf5..a5aa3d005f 100644 --- a/domain/card/build.gradle.kts +++ b/domain/card/build.gradle.kts @@ -20,8 +20,8 @@ dependencies { implementation(projects.domain.tokens.models) implementation(projects.domain.wallets.models) - implementation(deps.tangem.card.core) - implementation(deps.tangem.blockchain) { + implementation(tangemDeps.card.core) + implementation(tangemDeps.blockchain) { exclude(module = "joda-time") } diff --git a/domain/demo/build.gradle.kts b/domain/demo/build.gradle.kts index a9e6de5249..83c77bfc66 100644 --- a/domain/demo/build.gradle.kts +++ b/domain/demo/build.gradle.kts @@ -9,6 +9,6 @@ android { } dependencies { - implementation(deps.tangem.blockchain) - implementation(deps.tangem.card.core) + implementation(tangemDeps.blockchain) + implementation(tangemDeps.card.core) } \ No newline at end of file diff --git a/domain/legacy/build.gradle.kts b/domain/legacy/build.gradle.kts index f87e9728c8..8a3a831cbe 100644 --- a/domain/legacy/build.gradle.kts +++ b/domain/legacy/build.gradle.kts @@ -25,11 +25,11 @@ dependencies { implementation(projects.domain.txhistory.models) implementation(projects.domain.wallets.models) /** Tangem libraries */ - implementation(deps.tangem.blockchain) { + implementation(tangemDeps.blockchain) { exclude(module = "joda-time") } - implementation(deps.tangem.card.core) - implementation(deps.tangem.card.android) { + implementation(tangemDeps.card.core) + implementation(tangemDeps.card.android) { exclude(module = "joda-time") } diff --git a/domain/models/build.gradle.kts b/domain/models/build.gradle.kts index fec72be756..aeafc373d1 100644 --- a/domain/models/build.gradle.kts +++ b/domain/models/build.gradle.kts @@ -10,7 +10,7 @@ plugins { dependencies { api(projects.domain.visa.models) - implementation(deps.tangem.card.core) + implementation(tangemDeps.card.core) implementation(deps.moshi.kotlin) implementation(deps.moshi.adapters) implementation(deps.kotlin.serialization) diff --git a/domain/staking/build.gradle.kts b/domain/staking/build.gradle.kts index a0caf393f8..917cd0ad5f 100644 --- a/domain/staking/build.gradle.kts +++ b/domain/staking/build.gradle.kts @@ -23,7 +23,7 @@ dependencies { implementation(projects.features.staking.api) - implementation(deps.tangem.blockchain) { + implementation(tangemDeps.blockchain) { exclude(module = "joda-time") } } \ No newline at end of file diff --git a/domain/tokens/build.gradle.kts b/domain/tokens/build.gradle.kts index 3e8fc1ea6a..9382289ad6 100644 --- a/domain/tokens/build.gradle.kts +++ b/domain/tokens/build.gradle.kts @@ -50,7 +50,7 @@ dependencies { /** Tests */ testImplementation(deps.test.junit) testImplementation(deps.test.coroutine) - testImplementation(deps.tangem.blockchain) { + testImplementation(tangemDeps.blockchain) { exclude(module = "joda-time") } } \ No newline at end of file diff --git a/domain/transaction/build.gradle.kts b/domain/transaction/build.gradle.kts index b54aeca082..f798f98dc8 100644 --- a/domain/transaction/build.gradle.kts +++ b/domain/transaction/build.gradle.kts @@ -16,11 +16,11 @@ dependencies { implementation(projects.core.ui) /** Tangem SDKs */ - implementation(deps.tangem.card.core) - implementation(deps.tangem.card.android) { + implementation(tangemDeps.card.core) + implementation(tangemDeps.card.android) { exclude(module = "joda-time") } - implementation(deps.tangem.blockchain) + implementation(tangemDeps.blockchain) implementation(projects.domain.models) implementation(projects.domain.legacy) diff --git a/domain/wallets/build.gradle.kts b/domain/wallets/build.gradle.kts index 9972fdc9c7..616cbdcc21 100644 --- a/domain/wallets/build.gradle.kts +++ b/domain/wallets/build.gradle.kts @@ -26,7 +26,7 @@ dependencies { // endregion // region Tangem libraries - implementation(deps.tangem.blockchain) // android-library - implementation(deps.tangem.card.core) + implementation(tangemDeps.blockchain) // android-library + implementation(tangemDeps.card.core) // endregion } \ No newline at end of file diff --git a/domain/wallets/models/build.gradle.kts b/domain/wallets/models/build.gradle.kts index 9c259ee6b6..03afdb3da9 100644 --- a/domain/wallets/models/build.gradle.kts +++ b/domain/wallets/models/build.gradle.kts @@ -7,7 +7,7 @@ plugins { dependencies { // region Tangem libraries - implementation(deps.tangem.card.core) + implementation(tangemDeps.card.core) // endregion // region Domain modules diff --git a/features/details/impl/build.gradle.kts b/features/details/impl/build.gradle.kts index b3981ae397..2ffdab4b0e 100644 --- a/features/details/impl/build.gradle.kts +++ b/features/details/impl/build.gradle.kts @@ -45,9 +45,9 @@ dependencies { /* SDK */ // TODO: For TangemError model, should be removed after card domain scanning refactoring - implementation(deps.tangem.card.core) + implementation(tangemDeps.card.core) // For image resolving - implementation(deps.tangem.blockchain) + implementation(tangemDeps.blockchain) /* AndroidX */ implementation(deps.androidx.activity.compose) diff --git a/features/onboarding-v2/impl/build.gradle.kts b/features/onboarding-v2/impl/build.gradle.kts index 3f1c7150fc..636d71237b 100644 --- a/features/onboarding-v2/impl/build.gradle.kts +++ b/features/onboarding-v2/impl/build.gradle.kts @@ -45,8 +45,8 @@ dependencies { /** Tangem libraries */ implementation(projects.libs.tangemSdkApi) - implementation(deps.tangem.card.core) - implementation(deps.tangem.card.android) { + implementation(tangemDeps.card.core) + implementation(tangemDeps.card.android) { exclude(module = "joda-time") } diff --git a/features/onboarding/build.gradle.kts b/features/onboarding/build.gradle.kts index fb353a3220..6d048e8c4d 100644 --- a/features/onboarding/build.gradle.kts +++ b/features/onboarding/build.gradle.kts @@ -25,8 +25,8 @@ dependencies { implementation(project(":data:common")) /** Tangem libraries */ - implementation(deps.tangem.card.core) - implementation(deps.tangem.card.android) { + implementation(tangemDeps.card.core) + implementation(tangemDeps.card.android) { exclude(module = "joda-time") } @@ -50,7 +50,7 @@ dependencies { implementation(deps.compose.coil) implementation(deps.compose.shimmer) - implementation(deps.tangem.card.core) + implementation(tangemDeps.card.core) /** Other libraries */ implementation(deps.compose.shimmer) diff --git a/features/qr-scanning/impl/build.gradle.kts b/features/qr-scanning/impl/build.gradle.kts index 87bb1cc68e..f8bb506a61 100644 --- a/features/qr-scanning/impl/build.gradle.kts +++ b/features/qr-scanning/impl/build.gradle.kts @@ -60,5 +60,5 @@ dependencies { /** Other dependencies */ implementation(deps.arrow.core) implementation(deps.timber) - implementation(deps.tangem.card.core) + implementation(tangemDeps.card.core) } \ No newline at end of file diff --git a/features/referral/data/build.gradle.kts b/features/referral/data/build.gradle.kts index 954bac9c2e..bbe186db0f 100644 --- a/features/referral/data/build.gradle.kts +++ b/features/referral/data/build.gradle.kts @@ -38,5 +38,5 @@ dependencies { kapt(deps.hilt.kapt) /** Tangem deps */ - implementation(deps.tangem.blockchain) + implementation(tangemDeps.blockchain) } \ No newline at end of file diff --git a/features/referral/domain/build.gradle.kts b/features/referral/domain/build.gradle.kts index 4206513db7..a77d439bbb 100644 --- a/features/referral/domain/build.gradle.kts +++ b/features/referral/domain/build.gradle.kts @@ -32,7 +32,7 @@ dependencies { implementation(deps.arrow.core) implementation(deps.jodatime) implementation(deps.timber) - implementation(deps.tangem.card.core) + implementation(tangemDeps.card.core) /** DI */ implementation(deps.hilt.android) diff --git a/features/send/impl/build.gradle.kts b/features/send/impl/build.gradle.kts index 2126c0ac09..7df0d26ab3 100644 --- a/features/send/impl/build.gradle.kts +++ b/features/send/impl/build.gradle.kts @@ -39,8 +39,8 @@ dependencies { implementation(deps.compose.constraintLayout) /** Tangem SDKs */ - implementation(deps.tangem.card.core) - implementation(deps.tangem.blockchain) + implementation(tangemDeps.card.core) + implementation(tangemDeps.blockchain) /** Core modules */ implementation(projects.core.configToggles) diff --git a/features/staking/impl/build.gradle.kts b/features/staking/impl/build.gradle.kts index be3dbdd1e2..bbfa41e6e2 100644 --- a/features/staking/impl/build.gradle.kts +++ b/features/staking/impl/build.gradle.kts @@ -36,8 +36,8 @@ dependencies { implementation(deps.compose.constraintLayout) /** Tangem SDKs */ - implementation(deps.tangem.card.core) - implementation(deps.tangem.blockchain) + implementation(tangemDeps.card.core) + implementation(tangemDeps.blockchain) /** Core modules */ implementation(projects.core.configToggles) diff --git a/features/swap/data/build.gradle.kts b/features/swap/data/build.gradle.kts index 805cd27a59..f9af5bb02d 100644 --- a/features/swap/data/build.gradle.kts +++ b/features/swap/data/build.gradle.kts @@ -44,7 +44,7 @@ dependencies { implementation(projects.data.common) /** Tangem SDKs */ - implementation(deps.tangem.blockchain) + implementation(tangemDeps.blockchain) /** Others */ implementation(deps.timber) diff --git a/features/swap/domain/build.gradle.kts b/features/swap/domain/build.gradle.kts index ed5fe567e7..46a1c51668 100644 --- a/features/swap/domain/build.gradle.kts +++ b/features/swap/domain/build.gradle.kts @@ -51,8 +51,8 @@ dependencies { implementation(deps.kotlin.coroutines) implementation(deps.arrow.core) implementation(deps.timber) - implementation(deps.tangem.blockchain) - implementation(deps.tangem.card.core) + implementation(tangemDeps.blockchain) + implementation(tangemDeps.card.core) implementation(deps.moshi) kaptForObfuscatingVariants(deps.moshi.kotlin.codegen) } \ No newline at end of file diff --git a/features/tester/impl/build.gradle.kts b/features/tester/impl/build.gradle.kts index 5c994aba93..5f26b9b233 100644 --- a/features/tester/impl/build.gradle.kts +++ b/features/tester/impl/build.gradle.kts @@ -50,7 +50,7 @@ dependencies { implementation(projects.features.tester.api) /* SDK */ - implementation(deps.tangem.blockchain) + implementation(tangemDeps.blockchain) /** Other modules */ implementation(projects.common.routing) diff --git a/features/tokendetails/impl/build.gradle.kts b/features/tokendetails/impl/build.gradle.kts index 4a38dc8f9b..1457affebd 100644 --- a/features/tokendetails/impl/build.gradle.kts +++ b/features/tokendetails/impl/build.gradle.kts @@ -35,8 +35,8 @@ dependencies { implementation(deps.jodatime) implementation(deps.kotlin.immutable.collections) implementation(deps.reKotlin) - implementation(deps.tangem.blockchain) - implementation(deps.tangem.card.core) + implementation(tangemDeps.blockchain) + implementation(tangemDeps.card.core) implementation(deps.timber) implementation(deps.lifecycle.compose) implementation(deps.kotlin.serialization) diff --git a/features/wallet/impl/build.gradle.kts b/features/wallet/impl/build.gradle.kts index 3d27a12451..99809111b3 100644 --- a/features/wallet/impl/build.gradle.kts +++ b/features/wallet/impl/build.gradle.kts @@ -39,8 +39,8 @@ dependencies { implementation(deps.jodatime) implementation(deps.kotlin.immutable.collections) implementation(deps.reKotlin) - implementation(deps.tangem.card.core) - implementation(deps.tangem.blockchain) + implementation(tangemDeps.card.core) + implementation(tangemDeps.blockchain) implementation(deps.timber) implementation(deps.firebase.perf) { exclude(group = "com.google.firebase", module = "protolite-well-known-types") diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index 535afc2fe4..060b0ba823 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -88,15 +88,6 @@ markdown = "0.7.2" markdownComposeView = "0.5.4" # endregion Other libraries -# region Tangem -tangemBlockchainSdk = "develop-952" -#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds -tangemCardSdk = "develop-434" -#tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ -tangemVico = "2.0.0-alpha.25-tangem-developments8" -#tangemVico = "0.0.1" # Keep it! - used for local builds ^ -# endregion Tangem - # region Tools detektComposeRules = "1.3.0" detekt = "1.22.0" @@ -188,16 +179,6 @@ firebase-messaging = { module = "com.google.firebase:firebase-messaging-ktx" } firebase-perf = { module = "com.google.firebase:firebase-perf" } # endregion Firebase -# region Tangem -tangem-blockchain = { module = "com.tangem:blockchain", version.ref = "tangemBlockchainSdk" } -tangem-card-android = { module = "com.tangem.tangem-sdk-kotlin:android", version.ref = "tangemCardSdk" } -tangem-card-core = { module = "com.tangem.tangem-sdk-kotlin:core", version.ref = "tangemCardSdk" } - -tangem-vico-compose = { group = "com.tangem.vico", name = "compose", version.ref = "tangemVico" } -tangem-vico-compose-m3 = { group = "com.tangem.vico", name = "compose-m3", version.ref = "tangemVico" } -tangem-vico-core = { group = "com.tangem.vico", name = "core", version.ref = "tangemVico" } -# endregion Tangem - # region Detekt detekt-compose = { module = "ru.kode:detekt-rules-compose", version.ref = "detektComposeRules" } detekt-formatting = { module = "io.gitlab.arturbosch.detekt:detekt-formatting", version.ref = "detekt" } diff --git a/gradle/tangem_dependencies.toml b/gradle/tangem_dependencies.toml new file mode 100644 index 0000000000..f9edc59dd5 --- /dev/null +++ b/gradle/tangem_dependencies.toml @@ -0,0 +1,18 @@ +[versions] +tangemBlockchainSdk = "develop-952" +#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds +tangemCardSdk = "develop-434" +#tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ +tangemVico = "2.0.0-alpha.25-tangem-developments8" +#tangemVico = "0.0.1" # Keep it! - used for local builds ^ + + + +[libraries] +blockchain = { module = "com.tangem:blockchain", version.ref = "tangemBlockchainSdk" } +card-android = { module = "com.tangem.tangem-sdk-kotlin:android", version.ref = "tangemCardSdk" } +card-core = { module = "com.tangem.tangem-sdk-kotlin:core", version.ref = "tangemCardSdk" } + +vico-compose = { group = "com.tangem.vico", name = "compose", version.ref = "tangemVico" } +vico-compose-m3 = { group = "com.tangem.vico", name = "compose-m3", version.ref = "tangemVico" } +vico-core = { group = "com.tangem.vico", name = "core", version.ref = "tangemVico" } \ No newline at end of file diff --git a/libs/blockchain-sdk/build.gradle.kts b/libs/blockchain-sdk/build.gradle.kts index 12234d749f..31e9b0408e 100644 --- a/libs/blockchain-sdk/build.gradle.kts +++ b/libs/blockchain-sdk/build.gradle.kts @@ -45,8 +45,8 @@ dependencies { // endregion // region Tangem libraries - implementation(deps.tangem.blockchain) { exclude(module = "joda-time") } - implementation(deps.tangem.card.core) + implementation(tangemDeps.blockchain) { exclude(module = "joda-time") } + implementation(tangemDeps.card.core) // endregion testImplementation(deps.test.coroutine) diff --git a/libs/crypto/build.gradle.kts b/libs/crypto/build.gradle.kts index 1e443985c3..0278a0501c 100644 --- a/libs/crypto/build.gradle.kts +++ b/libs/crypto/build.gradle.kts @@ -16,7 +16,7 @@ dependencies { implementation(deps.kotlin.coroutines) /** SDK */ - implementation(deps.tangem.blockchain) + implementation(tangemDeps.blockchain) /** Core */ implementation(projects.core.utils) diff --git a/libs/tangem-sdk-api/build.gradle.kts b/libs/tangem-sdk-api/build.gradle.kts index 514702adfa..577365a357 100644 --- a/libs/tangem-sdk-api/build.gradle.kts +++ b/libs/tangem-sdk-api/build.gradle.kts @@ -22,8 +22,8 @@ dependencies { implementation(projects.core.res) /** Tangem libraries */ - implementation(deps.tangem.card.core) - implementation(deps.tangem.card.android) { + implementation(tangemDeps.card.core) + implementation(tangemDeps.card.android) { exclude(module = "joda-time") } diff --git a/plugins/configuration/settings.gradle.kts b/plugins/configuration/settings.gradle.kts index 0ed5a2e04b..13c8987dd9 100644 --- a/plugins/configuration/settings.gradle.kts +++ b/plugins/configuration/settings.gradle.kts @@ -3,5 +3,8 @@ dependencyResolutionManagement { create("deps") { from(files("../../gradle/dependencies.toml")) } + create("tangemDeps") { + from(files("../../gradle/tangem_dependencies.toml")) + } } } \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 7d45b0e97e..1ad6153ba0 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -113,7 +113,11 @@ dependencyResolutionManagement { create("deps") { from(files("gradle/dependencies.toml")) } + create("tangemDeps") { + from(files("gradle/tangem_dependencies.toml")) + } } + } enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") From 5899f9ea8d6118246d6058582a9444152df86fe0 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 19 Feb 2025 12:25:53 +0300 Subject: [PATCH 04/33] Updated on 2026-08-14 --- .../main/java/com/tangem/tap/MainActivity.kt | 4 - .../tangem/tap/routing/utils/ChildFactory.kt | 25 ++- core/deep-links/build.gradle.kts | 2 + .../tangem/core/deeplink/DeepLinksRegistry.kt | 19 --- .../deeplink/impl/DefaultDeepLinksRegistry.kt | 16 -- .../utils/AppComponentContextExtensions.kt | 21 +++ .../utils/DeepLinksLifecycleObserver.kt | 20 --- features/tokendetails/api/build.gradle.kts | 9 +- .../tokendetails/TokenDetailsComponent.kt | 16 ++ .../navigation/TokenDetailsRouter.kt | 8 - .../DefaultTokenDetailsComponent.kt | 78 +++++++++ .../tokendetails/di/TokenDetailsModule.kt | 38 +++++ .../di/TokenDetailsRouterModule.kt | 27 ---- .../presentation/TokenDetailsFragment.kt | 105 ------------ .../router/DefaultTokenDetailsRouter.kt | 9 +- .../router/InnerTokenDetailsRouter.kt | 3 +- .../TokenDetailsClickIntents.kt | 2 +- .../TokenDetailsModel.kt} | 150 ++++++++---------- .../TokenDetailsActionButtonsConverter.kt | 2 +- .../TokenDetailsLoadedBalanceConverter.kt | 2 +- .../TokenDetailsNotificationConverter.kt | 2 +- ...nDetailsOnrampTransactionStateConverter.kt | 2 +- .../TokenDetailsSkeletonStateConverter.kt | 2 +- .../state/factory/TokenDetailsStateFactory.kt | 2 +- ...enDetailsSwapTransactionsStateConverter.kt | 2 +- .../factory/express/ExchangeStatusFactory.kt | 2 +- .../factory/express/ExpressStatusFactory.kt | 2 +- .../factory/express/OnrampStatusFactory.kt | 2 +- .../TokenDetailsLoadedTxHistoryConverter.kt | 2 +- .../TokenDetailsLoadingTxHistoryConverter.kt | 2 +- .../TokenDetailsTxHistoryItemFlowConverter.kt | 2 +- ...tailsTxHistoryTransactionStateConverter.kt | 2 +- 32 files changed, 265 insertions(+), 315 deletions(-) create mode 100644 core/deep-links/src/main/kotlin/com/tangem/core/deeplink/utils/AppComponentContextExtensions.kt delete mode 100644 core/deep-links/src/main/kotlin/com/tangem/core/deeplink/utils/DeepLinksLifecycleObserver.kt create mode 100644 features/tokendetails/api/src/main/kotlin/com/tangem/features/tokendetails/TokenDetailsComponent.kt delete mode 100644 features/tokendetails/api/src/main/kotlin/com/tangem/features/tokendetails/navigation/TokenDetailsRouter.kt create mode 100644 features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/DefaultTokenDetailsComponent.kt create mode 100644 features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/di/TokenDetailsModule.kt delete mode 100644 features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/di/TokenDetailsRouterModule.kt delete mode 100644 features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/TokenDetailsFragment.kt rename features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/{viewmodels => model}/TokenDetailsClickIntents.kt (99%) rename features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/{viewmodels/TokenDetailsViewModel.kt => model/TokenDetailsModel.kt} (91%) diff --git a/app/src/main/java/com/tangem/tap/MainActivity.kt b/app/src/main/java/com/tangem/tap/MainActivity.kt index c96a550db8..72b9f67d82 100644 --- a/app/src/main/java/com/tangem/tap/MainActivity.kt +++ b/app/src/main/java/com/tangem/tap/MainActivity.kt @@ -64,7 +64,6 @@ import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnaly import com.tangem.features.onboarding.v2.OnboardingV2FeatureToggles import com.tangem.features.pushnotifications.api.navigation.PushNotificationsRouter import com.tangem.features.pushnotifications.api.utils.PUSH_PERMISSION -import com.tangem.features.tokendetails.navigation.TokenDetailsRouter import com.tangem.features.wallet.navigation.WalletRouter import com.tangem.google.GoogleServicesHelper import com.tangem.operations.backup.BackupService @@ -140,9 +139,6 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac @Inject lateinit var walletRouter: WalletRouter - @Inject - lateinit var tokenDetailsRouter: TokenDetailsRouter - @Inject lateinit var walletConnectInteractor: WalletConnectInteractor diff --git a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt index d8483ca2db..09e825ea06 100644 --- a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt +++ b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt @@ -18,7 +18,7 @@ import com.tangem.features.send.api.SendComponent import com.tangem.features.swap.SwapComponent import com.tangem.features.staking.api.StakingComponent import com.tangem.features.tester.api.TesterRouter -import com.tangem.features.tokendetails.navigation.TokenDetailsRouter +import com.tangem.features.tokendetails.TokenDetailsComponent import com.tangem.features.wallet.navigation.WalletRouter import com.tangem.tap.features.details.ui.appcurrency.AppCurrencySelectorFragment import com.tangem.tap.features.details.ui.appsettings.AppSettingsFragment @@ -62,7 +62,7 @@ internal class ChildFactory @Inject constructor( private val stakingComponentFactory: StakingComponent.Factory, private val swapComponentFactory: SwapComponent.Factory, private val homeComponentFactory: HomeComponent.Factory, - private val tokenDetailsRouter: TokenDetailsRouter, + private val tokenDetailsComponentFactory: TokenDetailsComponent.Factory, private val walletRouter: WalletRouter, private val qrScanningRouter: QrScanningRouter, private val testerRouter: TesterRouter, @@ -213,6 +213,16 @@ internal class ChildFactory @Inject constructor( componentFactory = storiesComponentFactory, ) } + is AppRoute.CurrencyDetails -> { + createComponentChild( + contextProvider = contextProvider(route, contextFactory), + params = TokenDetailsComponent.Params( + userWalletId = route.userWalletId, + currency = route.currency, + ), + componentFactory = tokenDetailsComponentFactory, + ) + } is AppRoute.Staking -> { createComponentChild( contextProvider = contextProvider(route, contextFactory), @@ -263,7 +273,6 @@ internal class ChildFactory @Inject constructor( is AppRoute.AppSettings, is AppRoute.CardSettings, is AppRoute.DetailsSecurity, - is AppRoute.OnboardingNote, is AppRoute.OnboardingOther, is AppRoute.OnboardingTwins, @@ -273,7 +282,6 @@ internal class ChildFactory @Inject constructor( is AppRoute.ResetToFactory, is AppRoute.Wallet, is AppRoute.WalletConnectSessions, - is AppRoute.CurrencyDetails, is AppRoute.PushNotification, -> error("Unsupported route: $route") } @@ -395,7 +403,14 @@ internal class ChildFactory @Inject constructor( route.asFragmentChild(Provider { WalletConnectFragment() }) } is AppRoute.CurrencyDetails -> { - route.asFragmentChild(Provider { tokenDetailsRouter.getEntryFragment() }) + route.asComponentChild( + contextProvider = contextProvider(route, contextFactory), + params = TokenDetailsComponent.Params( + userWalletId = route.userWalletId, + currency = route.currency, + ), + componentFactory = tokenDetailsComponentFactory, + ) } is AppRoute.Welcome -> { route.asFragmentChild(Provider { WelcomeFragment() }) diff --git a/core/deep-links/build.gradle.kts b/core/deep-links/build.gradle.kts index 9d43ab04df..c086d8f8d6 100644 --- a/core/deep-links/build.gradle.kts +++ b/core/deep-links/build.gradle.kts @@ -10,6 +10,8 @@ android { } dependencies { + /* Core */ + implementation(projects.core.decompose) /* Libs - AndroidX */ implementation(deps.lifecycle.runtime.ktx) diff --git a/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/DeepLinksRegistry.kt b/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/DeepLinksRegistry.kt index 105ddbc940..fc56ae10a0 100644 --- a/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/DeepLinksRegistry.kt +++ b/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/DeepLinksRegistry.kt @@ -1,8 +1,6 @@ package com.tangem.core.deeplink import android.content.Intent -import androidx.lifecycle.LifecycleOwner -import androidx.lifecycle.ViewModel // TODO: Add tests /** @@ -21,17 +19,11 @@ interface DeepLinksRegistry { /** * Registers the given [deepLink]. - * - * @see registerWithLifecycle - * @see registerWithViewModel */ fun register(deepLink: DeepLink) /** * Registers the given [deepLinks]. - * - * @see registerWithLifecycle - * @see registerWithViewModel */ fun register(deepLinks: Collection) @@ -50,17 +42,6 @@ interface DeepLinksRegistry { * */ fun unregisterByIds(ids: Collection) - /** - * Registers the [deepLinks] when the [owner] is resumed and ensures that they are unregistered when the [owner] is - * stopped. - */ - fun registerWithLifecycle(owner: LifecycleOwner, deepLinks: Collection) - - /** - * Registers the [deepLinks] and ensures that they are unregistered when the [ViewModel] is closed. - */ - fun registerWithViewModel(viewModel: ViewModel, deepLinks: Collection) - /** * Triggers run last launched [Intent] with deeplink handlers that can handle delayed deeplink * after handle [Intent] clear that and second time no intent will be handled diff --git a/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/impl/DefaultDeepLinksRegistry.kt b/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/impl/DefaultDeepLinksRegistry.kt index e51f6b8b37..63f6f60d78 100644 --- a/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/impl/DefaultDeepLinksRegistry.kt +++ b/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/impl/DefaultDeepLinksRegistry.kt @@ -3,11 +3,8 @@ package com.tangem.core.deeplink.impl import android.content.Intent import android.net.Uri import androidx.core.net.toUri -import androidx.lifecycle.LifecycleOwner -import androidx.lifecycle.ViewModel import com.tangem.core.deeplink.DeepLink import com.tangem.core.deeplink.DeepLinksRegistry -import com.tangem.core.deeplink.utils.DeepLinksLifecycleObserver import timber.log.Timber internal class DefaultDeepLinksRegistry : DeepLinksRegistry { @@ -103,19 +100,6 @@ internal class DefaultDeepLinksRegistry : DeepLinksRegistry { ) } - override fun registerWithLifecycle(owner: LifecycleOwner, deepLinks: Collection) { - val observer = DeepLinksLifecycleObserver(deepLinksRegistry = this, deepLinks) - owner.lifecycle.addObserver(observer) - } - - override fun registerWithViewModel(viewModel: ViewModel, deepLinks: Collection) { - viewModel.addCloseable { - unregister(deepLinks) - } - - register(deepLinks) - } - override fun triggerDelayedDeeplink() { if (lastIntent != null) { val intent = lastIntent diff --git a/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/utils/AppComponentContextExtensions.kt b/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/utils/AppComponentContextExtensions.kt new file mode 100644 index 0000000000..594b8305ca --- /dev/null +++ b/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/utils/AppComponentContextExtensions.kt @@ -0,0 +1,21 @@ +package com.tangem.core.deeplink.utils + +import com.arkivanov.essenty.lifecycle.subscribe +import com.tangem.core.decompose.context.AppComponentContext +import com.tangem.core.deeplink.DeepLink +import com.tangem.core.deeplink.DeepLinksRegistry + +fun AppComponentContext.registerDeepLinks(registry: DeepLinksRegistry, vararg deepLinks: DeepLink) { + registerDeepLinks(registry, deepLinks.toList()) +} + +fun AppComponentContext.registerDeepLinks(registry: DeepLinksRegistry, deepLinks: Collection) { + lifecycle.subscribe( + onCreate = { + registry.register(deepLinks) + }, + onDestroy = { + registry.unregister(deepLinks) + }, + ) +} \ No newline at end of file diff --git a/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/utils/DeepLinksLifecycleObserver.kt b/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/utils/DeepLinksLifecycleObserver.kt deleted file mode 100644 index ae1580e17e..0000000000 --- a/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/utils/DeepLinksLifecycleObserver.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.tangem.core.deeplink.utils - -import androidx.lifecycle.DefaultLifecycleObserver -import androidx.lifecycle.LifecycleOwner -import com.tangem.core.deeplink.DeepLink -import com.tangem.core.deeplink.DeepLinksRegistry - -internal class DeepLinksLifecycleObserver( - private val deepLinksRegistry: DeepLinksRegistry, - private val deepLinks: Collection, -) : DefaultLifecycleObserver { - - override fun onResume(owner: LifecycleOwner) { - deepLinksRegistry.register(deepLinks) - } - - override fun onPause(owner: LifecycleOwner) { - deepLinksRegistry.unregister(deepLinks) - } -} \ No newline at end of file diff --git a/features/tokendetails/api/build.gradle.kts b/features/tokendetails/api/build.gradle.kts index 26d2527cd2..dc22e4ffbb 100644 --- a/features/tokendetails/api/build.gradle.kts +++ b/features/tokendetails/api/build.gradle.kts @@ -10,8 +10,11 @@ android { } dependencies { - implementation(projects.domain.tokens.models) + /** Core */ + implementation(projects.core.decompose) + implementation(projects.core.ui) - /** AndroidX */ - implementation(deps.androidx.fragment.ktx) + /** Domain models */ + implementation(projects.domain.tokens.models) + implementation(projects.domain.wallets.models) } \ No newline at end of file diff --git a/features/tokendetails/api/src/main/kotlin/com/tangem/features/tokendetails/TokenDetailsComponent.kt b/features/tokendetails/api/src/main/kotlin/com/tangem/features/tokendetails/TokenDetailsComponent.kt new file mode 100644 index 0000000000..a057fcb984 --- /dev/null +++ b/features/tokendetails/api/src/main/kotlin/com/tangem/features/tokendetails/TokenDetailsComponent.kt @@ -0,0 +1,16 @@ +package com.tangem.features.tokendetails + +import com.tangem.core.decompose.factory.ComponentFactory +import com.tangem.core.ui.decompose.ComposableContentComponent +import com.tangem.domain.tokens.model.CryptoCurrency +import com.tangem.domain.wallets.models.UserWalletId + +interface TokenDetailsComponent : ComposableContentComponent { + + data class Params( + val userWalletId: UserWalletId, + val currency: CryptoCurrency, + ) + + interface Factory : ComponentFactory +} \ No newline at end of file diff --git a/features/tokendetails/api/src/main/kotlin/com/tangem/features/tokendetails/navigation/TokenDetailsRouter.kt b/features/tokendetails/api/src/main/kotlin/com/tangem/features/tokendetails/navigation/TokenDetailsRouter.kt deleted file mode 100644 index a361d75438..0000000000 --- a/features/tokendetails/api/src/main/kotlin/com/tangem/features/tokendetails/navigation/TokenDetailsRouter.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.tangem.features.tokendetails.navigation - -import androidx.fragment.app.Fragment - -interface TokenDetailsRouter { - - fun getEntryFragment(): Fragment -} \ No newline at end of file diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/DefaultTokenDetailsComponent.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/DefaultTokenDetailsComponent.kt new file mode 100644 index 0000000000..5d4274694f --- /dev/null +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/DefaultTokenDetailsComponent.kt @@ -0,0 +1,78 @@ +package com.tangem.feature.tokendetails + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.arkivanov.essenty.lifecycle.subscribe +import com.tangem.core.decompose.context.AppComponentContext +import com.tangem.core.decompose.context.child +import com.tangem.core.decompose.model.getOrCreateModel +import com.tangem.core.deeplink.DeepLinksRegistry +import com.tangem.core.deeplink.global.BuyCurrencyDeepLink +import com.tangem.core.deeplink.utils.registerDeepLinks +import com.tangem.core.ui.components.NavigationBar3ButtonsScrim +import com.tangem.domain.tokens.model.CryptoCurrency +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsModel +import com.tangem.feature.tokendetails.presentation.tokendetails.ui.TokenDetailsScreen +import com.tangem.features.markets.token.block.TokenMarketBlockComponent +import com.tangem.features.tokendetails.TokenDetailsComponent +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject + +internal class DefaultTokenDetailsComponent @AssistedInject constructor( + @Assisted appComponentContext: AppComponentContext, + @Assisted params: TokenDetailsComponent.Params, + tokenMarketBlockComponentFactory: TokenMarketBlockComponent.Factory, + deepLinksRegistry: DeepLinksRegistry, +) : TokenDetailsComponent, AppComponentContext by appComponentContext { + + private val model: TokenDetailsModel = getOrCreateModel(params) + + init { + lifecycle.subscribe( + onPause = model::onPause, + onResume = model::onResume, + ) + + registerDeepLinks( + registry = deepLinksRegistry, + BuyCurrencyDeepLink( + onReceive = model::onBuyCurrencyDeepLink, + ), + ) + } + + private val tokenMarketBlockComponent = params.currency.toTokenMarketParam()?.let { tokenMarketParams -> + tokenMarketBlockComponentFactory.create( + appComponentContext = child("tokenMarketBlockComponent"), + params = tokenMarketParams, + ) + } + + @Composable + override fun Content(modifier: Modifier) { + val state by model.uiState.collectAsStateWithLifecycle() + + NavigationBar3ButtonsScrim() + TokenDetailsScreen( + state = state, + tokenMarketBlockComponent = tokenMarketBlockComponent, + ) + } + + private fun CryptoCurrency.toTokenMarketParam(): TokenMarketBlockComponent.Params? { + id.rawCurrencyId ?: return null // token price is not available + + return TokenMarketBlockComponent.Params(cryptoCurrency = this) + } + + @AssistedFactory + interface Factory : TokenDetailsComponent.Factory { + override fun create( + context: AppComponentContext, + params: TokenDetailsComponent.Params, + ): DefaultTokenDetailsComponent + } +} \ No newline at end of file diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/di/TokenDetailsModule.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/di/TokenDetailsModule.kt new file mode 100644 index 0000000000..a7ad3dd026 --- /dev/null +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/di/TokenDetailsModule.kt @@ -0,0 +1,38 @@ +package com.tangem.feature.tokendetails.di + +import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.model.Model +import com.tangem.feature.tokendetails.DefaultTokenDetailsComponent +import com.tangem.feature.tokendetails.presentation.router.DefaultTokenDetailsRouter +import com.tangem.feature.tokendetails.presentation.router.InnerTokenDetailsRouter +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsModel +import com.tangem.features.tokendetails.TokenDetailsComponent +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import dagger.multibindings.ClassKey +import dagger.multibindings.IntoMap + +@Module +@InstallIn(SingletonComponent::class) +internal interface TokenDetailsModule { + + @Binds + fun bindComponentFactory(factory: DefaultTokenDetailsComponent.Factory): TokenDetailsComponent.Factory + + @Binds + @IntoMap + @ClassKey(TokenDetailsModel::class) + fun bindModel(model: TokenDetailsModel): Model +} + +@Module +@InstallIn(DecomposeComponent::class) +internal interface StakingComponentModule { + + @Binds + @ComponentScoped + fun bindRouter(impl: DefaultTokenDetailsRouter): InnerTokenDetailsRouter +} \ No newline at end of file diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/di/TokenDetailsRouterModule.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/di/TokenDetailsRouterModule.kt deleted file mode 100644 index 94147e5592..0000000000 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/di/TokenDetailsRouterModule.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.tangem.feature.tokendetails.di - -import com.tangem.common.routing.AppRouter -import com.tangem.core.navigation.share.ShareManager -import com.tangem.core.navigation.url.UrlOpener -import com.tangem.feature.tokendetails.presentation.router.DefaultTokenDetailsRouter -import com.tangem.features.tokendetails.navigation.TokenDetailsRouter -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.android.components.ActivityComponent -import dagger.hilt.android.scopes.ActivityScoped - -@Module -@InstallIn(ActivityComponent::class) -internal object TokenDetailsRouterModule { - - @Provides - @ActivityScoped - fun provideTokenDetailsRouter( - appRouter: AppRouter, - urlOpener: UrlOpener, - shareManager: ShareManager, - ): TokenDetailsRouter { - return DefaultTokenDetailsRouter(appRouter, urlOpener, shareManager) - } -} \ No newline at end of file diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/TokenDetailsFragment.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/TokenDetailsFragment.kt deleted file mode 100644 index 2c787270d1..0000000000 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/TokenDetailsFragment.kt +++ /dev/null @@ -1,105 +0,0 @@ -package com.tangem.feature.tokendetails.presentation - -import android.os.Bundle -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.fragment.app.viewModels -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.arkivanov.decompose.defaultComponentContext -import com.tangem.common.routing.AppRoute -import com.tangem.common.routing.AppRouter -import com.tangem.common.routing.bundle.unbundle -import com.tangem.common.routing.utils.asRouter -import com.tangem.core.decompose.context.DefaultAppComponentContext -import com.tangem.core.decompose.di.DecomposeComponent -import com.tangem.core.decompose.di.GlobalUiMessageSender -import com.tangem.core.decompose.ui.UiMessageSender -import com.tangem.core.ui.UiDependencies -import com.tangem.core.ui.components.NavigationBar3ButtonsScrim -import com.tangem.core.ui.screen.ComposeFragment -import com.tangem.domain.tokens.model.CryptoCurrency -import com.tangem.feature.tokendetails.presentation.router.InnerTokenDetailsRouter -import com.tangem.feature.tokendetails.presentation.tokendetails.ui.TokenDetailsScreen -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsViewModel -import com.tangem.features.markets.token.block.TokenMarketBlockComponent -import com.tangem.features.tokendetails.navigation.TokenDetailsRouter -import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import dagger.hilt.android.AndroidEntryPoint -import javax.inject.Inject - -@AndroidEntryPoint -internal class TokenDetailsFragment : ComposeFragment() { - - @Inject - override lateinit var uiDependencies: UiDependencies - - @Inject - @GlobalUiMessageSender - internal lateinit var messageSender: UiMessageSender - - @Inject - internal lateinit var tokenDetailsRouter: TokenDetailsRouter - - @Inject - internal lateinit var coroutineDispatcherProvider: CoroutineDispatcherProvider - - @Inject - internal lateinit var componentBuilder: DecomposeComponent.Builder - - @Inject - internal lateinit var tokenMarketBlockComponentFactory: TokenMarketBlockComponent.Factory - - @Inject - internal lateinit var appRouter: AppRouter - - private val viewModel by viewModels() - - private var tokenMarketBlockComponent: TokenMarketBlockComponent? = null - - private val internalTokenDetailsRouter: InnerTokenDetailsRouter - get() = requireNotNull(tokenDetailsRouter as? InnerTokenDetailsRouter) { - "internalTokenDetailsRouter should be instance of InnerTokenDetailsRouter" - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - viewModel.router = internalTokenDetailsRouter - lifecycle.addObserver(viewModel) - - val cryptoCurrency: CryptoCurrency = arguments - ?.getBundle(AppRoute.CurrencyDetails.CRYPTO_CURRENCY_KEY) - ?.unbundle(CryptoCurrency.serializer()) - ?: error("Token Details screen can't be opened without `CryptoCurrency`") - - val param = cryptoCurrency.toParam() ?: return - - val appContext = DefaultAppComponentContext( - componentContext = defaultComponentContext(requireActivity().onBackPressedDispatcher), - messageSender = messageSender, - dispatchers = coroutineDispatcherProvider, - hiltComponentBuilder = componentBuilder, - replaceRouter = appRouter.asRouter(), - ) - - tokenMarketBlockComponent = tokenMarketBlockComponentFactory.create( - appComponentContext = appContext, - params = param, - ) - } - - private fun CryptoCurrency.toParam(): TokenMarketBlockComponent.Params? { - id.rawCurrencyId ?: return null // token price is not available - - return TokenMarketBlockComponent.Params(cryptoCurrency = this) - } - - @Composable - override fun ScreenContent(modifier: Modifier) { - NavigationBar3ButtonsScrim() - TokenDetailsScreen( - state = viewModel.uiState.collectAsStateWithLifecycle().value, - tokenMarketBlockComponent = tokenMarketBlockComponent, - ) - } -} \ No newline at end of file diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/router/DefaultTokenDetailsRouter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/router/DefaultTokenDetailsRouter.kt index d8a3eb4733..4ffdf4c587 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/router/DefaultTokenDetailsRouter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/router/DefaultTokenDetailsRouter.kt @@ -1,23 +1,22 @@ package com.tangem.feature.tokendetails.presentation.router -import androidx.fragment.app.Fragment import com.tangem.common.routing.AppRoute import com.tangem.common.routing.AppRouter +import com.tangem.core.decompose.di.ComponentScoped import com.tangem.core.navigation.share.ShareManager import com.tangem.core.navigation.url.UrlOpener import com.tangem.domain.staking.model.stakekit.Yield import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.wallets.models.UserWalletId -import com.tangem.feature.tokendetails.presentation.TokenDetailsFragment +import javax.inject.Inject -internal class DefaultTokenDetailsRouter( +@ComponentScoped +internal class DefaultTokenDetailsRouter @Inject constructor( private val router: AppRouter, private val urlOpener: UrlOpener, private val shareManager: ShareManager, ) : InnerTokenDetailsRouter { - override fun getEntryFragment(): Fragment = TokenDetailsFragment() - override fun popBackStack() { router.pop() } diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/router/InnerTokenDetailsRouter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/router/InnerTokenDetailsRouter.kt index e4a143ccd1..156a7c60c1 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/router/InnerTokenDetailsRouter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/router/InnerTokenDetailsRouter.kt @@ -3,9 +3,8 @@ package com.tangem.feature.tokendetails.presentation.router import com.tangem.domain.staking.model.stakekit.Yield import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.wallets.models.UserWalletId -import com.tangem.features.tokendetails.navigation.TokenDetailsRouter -internal interface InnerTokenDetailsRouter : TokenDetailsRouter { +internal interface InnerTokenDetailsRouter { /** Pop back stack */ fun popBackStack() diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsClickIntents.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsClickIntents.kt similarity index 99% rename from features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsClickIntents.kt rename to features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsClickIntents.kt index 8806affc45..c716c21445 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsClickIntents.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsClickIntents.kt @@ -1,4 +1,4 @@ -package com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels +package com.tangem.feature.tokendetails.presentation.tokendetails.model import com.tangem.core.ui.components.bottomsheets.tokenreceive.AddressModel import com.tangem.core.ui.extensions.TextReference diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt similarity index 91% rename from features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt rename to features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt index 744218305e..2f6219c24e 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt @@ -1,21 +1,20 @@ -package com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels +package com.tangem.feature.tokendetails.presentation.tokendetails.model -import android.os.Bundle -import androidx.lifecycle.* +import androidx.compose.runtime.Stable import androidx.paging.cachedIn import arrow.core.getOrElse import com.tangem.blockchain.common.address.AddressType import com.tangem.common.routing.AppRoute import com.tangem.common.routing.AppRouter -import com.tangem.common.routing.bundle.unbundle import com.tangem.common.ui.expressStatus.ExpressStatusBottomSheetConfig import com.tangem.common.ui.expressStatus.state.ExpressTransactionStateUM import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.models.AnalyticsParam +import com.tangem.core.decompose.di.ComponentScoped import com.tangem.core.decompose.di.GlobalUiMessageSender +import com.tangem.core.decompose.model.Model +import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.ui.UiMessageSender -import com.tangem.core.deeplink.DeepLinksRegistry -import com.tangem.core.deeplink.global.BuyCurrencyDeepLink import com.tangem.core.navigation.share.ShareManager import com.tangem.core.ui.clipboard.ClipboardManager import com.tangem.core.ui.components.bottomsheets.tokenreceive.AddressModel @@ -36,6 +35,7 @@ import com.tangem.domain.card.NetworkHasDerivationUseCase import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.demo.IsDemoCardUseCase import com.tangem.domain.onramp.model.OnrampSource +import com.tangem.domain.promo.ShouldShowSwapPromoTokenUseCase import com.tangem.domain.redux.ReduxStateHolder import com.tangem.domain.staking.GetStakingAvailabilityUseCase import com.tangem.domain.staking.GetStakingEntryInfoUseCase @@ -73,12 +73,11 @@ import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenBala import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.TokenDetailsStateFactory import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.express.ExpressStatusFactory -import com.tangem.domain.promo.ShouldShowSwapPromoTokenUseCase import com.tangem.features.onramp.OnrampFeatureToggles +import com.tangem.features.tokendetails.TokenDetailsComponent import com.tangem.features.tokendetails.impl.R import com.tangem.utils.Provider import com.tangem.utils.coroutines.* -import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.async @@ -89,9 +88,10 @@ import timber.log.Timber import javax.inject.Inject @Suppress("LongParameterList", "LargeClass", "TooManyFunctions") -@HiltViewModel -internal class TokenDetailsViewModel @Inject constructor( - private val dispatchers: CoroutineDispatcherProvider, +@Stable +@ComponentScoped +internal class TokenDetailsModel @Inject constructor( + override val dispatchers: CoroutineDispatcherProvider, private val getCurrencyStatusUpdatesUseCase: GetCurrencyStatusUpdatesUseCase, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, private val fetchCurrencyStatusUseCase: FetchCurrencyStatusUseCase, @@ -122,26 +122,19 @@ internal class TokenDetailsViewModel @Inject constructor( private val onrampFeatureToggles: OnrampFeatureToggles, private val shareManager: ShareManager, @GlobalUiMessageSender private val uiMessageSender: UiMessageSender, + paramsContainer: ParamsContainer, expressStatusFactory: ExpressStatusFactory.Factory, getUserWalletUseCase: GetUserWalletUseCase, getStakingIntegrationIdUseCase: GetStakingIntegrationIdUseCase, - deepLinksRegistry: DeepLinksRegistry, - savedStateHandle: SavedStateHandle, private val appRouter: AppRouter, -) : ViewModel(), DefaultLifecycleObserver, TokenDetailsClickIntents { + private val router: InnerTokenDetailsRouter, +) : Model(), TokenDetailsClickIntents { - private val userWalletId: UserWalletId = savedStateHandle.get(AppRoute.CurrencyDetails.USER_WALLET_ID_KEY) - ?.unbundle(UserWalletId.serializer()) - ?: error("This screen can't be opened without `UserWalletId`") + private val params = paramsContainer.require() + private val userWalletId: UserWalletId = params.userWalletId + private val cryptoCurrency: CryptoCurrency = params.currency - private val cryptoCurrency: CryptoCurrency = - savedStateHandle.get(AppRoute.CurrencyDetails.CRYPTO_CURRENCY_KEY) - ?.unbundle(CryptoCurrency.serializer()) - ?: error("This screen can't be opened without `CryptoCurrency`") - - private val userWallet: UserWallet - - lateinit var router: InnerTokenDetailsRouter + private val userWallet: UserWallet = getUserWalletUseCase(userWalletId).getOrNull() ?: error("UserWallet not found") private val marketPriceJobHolder = JobHolder() private val refreshStateJobHolder = JobHolder() @@ -195,18 +188,16 @@ internal class TokenDetailsViewModel @Inject constructor( val uiState: StateFlow = internalUiState init { - deepLinksRegistry.registerWithViewModel( - viewModel = this, - deepLinks = listOf( - BuyCurrencyDeepLink( - onReceive = ::onBuyCurrencyDeepLink, - ), - ), + analyticsEventsHandler.send( + event = TokenScreenAnalyticsEvent.DetailsScreenOpened(token = cryptoCurrency.symbol), ) - userWallet = getUserWalletUseCase(userWalletId).getOrNull() ?: error("UserWallet not found") + updateTopBarMenu() + initButtons() + updateContent() + handleBalanceHiding() } - private fun onBuyCurrencyDeepLink(externalTxId: String) { + fun onBuyCurrencyDeepLink(externalTxId: String) { if (onrampFeatureToggles.isFeatureEnabled) { router.openOnrampSuccess(externalTxId) } else { @@ -215,36 +206,24 @@ internal class TokenDetailsViewModel @Inject constructor( } } - override fun onCreate(owner: LifecycleOwner) { - analyticsEventsHandler.send( - event = TokenScreenAnalyticsEvent.DetailsScreenOpened(token = cryptoCurrency.symbol), - ) - updateTopBarMenu() - initButtons() - updateContent() - handleBalanceHiding(owner) - } - - override fun onPause(owner: LifecycleOwner) { + fun onPause() { expressTxStatusTaskScheduler.cancelTask() expressTxJobHolder.cancel() - super.onPause(owner) } - override fun onResume(owner: LifecycleOwner) { + fun onResume() { subscribeOnExpressTransactionsUpdates() - super.onResume(owner) } - override fun onCleared() { + override fun onDestroy() { expressTxStatusTaskScheduler.cancelTask() expressTxJobHolder.cancel() - super.onCleared() + super.onDestroy() } private fun initButtons() { // we need also init buttons before start all loading to avoid buttons blocking - viewModelScope.launch { + modelScope.launch { val currentCryptoCurrencyStatus = getCryptoCurrencySyncUseCase.invoke( userWalletId = userWalletId, cryptoCurrencyId = cryptoCurrency.id, @@ -266,15 +245,14 @@ internal class TokenDetailsViewModel @Inject constructor( updateStakingInfo() } - private fun handleBalanceHiding(owner: LifecycleOwner) { + private fun handleBalanceHiding() { getBalanceHidingSettingsUseCase() - .flowWithLifecycle(owner.lifecycle) .onEach { internalUiState.value = stateFactory.getStateWithUpdatedHidden( isBalanceHidden = it.isBalanceHidden, ) } - .launchIn(viewModelScope) + .launchIn(modelScope) } private suspend fun updateButtons(currencyStatus: CryptoCurrencyStatus) { @@ -288,11 +266,11 @@ internal class TokenDetailsViewModel @Inject constructor( internalUiState.value = stateFactory.getManageButtonsState(actions = it.states) } .flowOn(dispatchers.main) - .launchIn(viewModelScope) + .launchIn(modelScope) } private fun updateWarnings(cryptoCurrencyStatus: CryptoCurrencyStatus) { - viewModelScope.launch(dispatchers.main) { + modelScope.launch(dispatchers.main) { getCurrencyWarningsUseCase.invoke( userWalletId = userWalletId, currencyStatus = cryptoCurrencyStatus, @@ -305,13 +283,13 @@ internal class TokenDetailsViewModel @Inject constructor( notificationsAnalyticsSender.send(internalUiState.value, updatedState.notifications) internalUiState.value = updatedState } - .launchIn(viewModelScope) + .launchIn(modelScope) .saveIn(warningsJobHolder) } } private fun subscribeOnCurrencyStatusUpdates() { - viewModelScope.launch(dispatchers.main) { + modelScope.launch(dispatchers.main) { getCurrencyStatusUpdatesUseCase( userWalletId = userWalletId, currencyId = cryptoCurrency.id, @@ -328,13 +306,13 @@ internal class TokenDetailsViewModel @Inject constructor( currencyStatusAnalyticsSender.send(maybeCurrencyStatus) } .flowOn(dispatchers.main) - .launchIn(viewModelScope) + .launchIn(modelScope) .saveIn(marketPriceJobHolder) } } private fun subscribeOnExpressTransactionsUpdates() { - viewModelScope.launch(dispatchers.main) { + modelScope.launch(dispatchers.main) { expressTxStatusTaskScheduler.cancelTask() expressStatusFactory .getExpressStatuses() @@ -345,7 +323,7 @@ internal class TokenDetailsViewModel @Inject constructor( ::updateNetworkToSwapBalance, ) expressTxStatusTaskScheduler.scheduleTask( - viewModelScope, + modelScope, PeriodicTask( isDelayFirst = false, delay = EXPRESS_STATUS_UPDATE_DELAY, @@ -365,13 +343,13 @@ internal class TokenDetailsViewModel @Inject constructor( ) } .flowOn(dispatchers.main) - .launchIn(viewModelScope) + .launchIn(modelScope) .saveIn(expressTxJobHolder) } } private fun updateNetworkToSwapBalance(toCryptoCurrency: CryptoCurrency) { - viewModelScope.launch { + modelScope.launch { updateDelayedCurrencyStatusUseCase( userWalletId = userWalletId, network = toCryptoCurrency.network, @@ -385,7 +363,7 @@ internal class TokenDetailsViewModel @Inject constructor( * @param showItemsLoading - show loading items placeholder. */ private fun updateTxHistory(refresh: Boolean, showItemsLoading: Boolean) { - viewModelScope.launch(dispatchers.main) { + modelScope.launch(dispatchers.main) { val txHistoryItemsCountEither = txHistoryItemsCountUseCase( userWalletId = userWalletId, currency = cryptoCurrency, @@ -404,7 +382,7 @@ internal class TokenDetailsViewModel @Inject constructor( userWalletId = userWalletId, currency = cryptoCurrency, refresh = refresh, - ).map { it.cachedIn(viewModelScope) } + ).map { it.cachedIn(modelScope) } internalUiState.value = stateFactory.getLoadedTxHistoryState(maybeTxHistory) } @@ -412,7 +390,7 @@ internal class TokenDetailsViewModel @Inject constructor( } private fun updateStakingInfo() { - viewModelScope.launch { + modelScope.launch { val availability = getStakingAvailabilityUseCase( userWalletId = userWalletId, cryptoCurrency = cryptoCurrency, @@ -432,7 +410,7 @@ internal class TokenDetailsViewModel @Inject constructor( } private fun updateTopBarMenu() { - viewModelScope.launch(dispatchers.main) { + modelScope.launch(dispatchers.main) { val hasDerivations = networkHasDerivationUseCase(userWallet.scanResponse, cryptoCurrency.network).getOrElse { false } @@ -452,7 +430,7 @@ internal class TokenDetailsViewModel @Inject constructor( maybeAppCurrency.getOrElse { AppCurrency.Default } } .stateIn( - scope = viewModelScope, + scope = modelScope, started = SharingStarted.Eagerly, initialValue = AppCurrency.Default, ) @@ -476,7 +454,7 @@ internal class TokenDetailsViewModel @Inject constructor( val status = cryptoCurrencyStatus ?: return if (onrampFeatureToggles.isFeatureEnabled) { - viewModelScope.launch(dispatchers.main) { + modelScope.launch(dispatchers.main) { reduxStateHolder.dispatch( TradeCryptoAction.Buy( userWallet = userWallet, @@ -488,7 +466,7 @@ internal class TokenDetailsViewModel @Inject constructor( } } else { showErrorIfDemoModeOrElse { - viewModelScope.launch(dispatchers.main) { + modelScope.launch(dispatchers.main) { reduxStateHolder.dispatch( TradeCryptoAction.Buy( userWallet = userWallet, @@ -554,7 +532,7 @@ internal class TokenDetailsViewModel @Inject constructor( return } - viewModelScope.launch(dispatchers.main) { + modelScope.launch(dispatchers.main) { analyticsEventsHandler.send(TokenScreenAnalyticsEvent.ButtonReceive(cryptoCurrency.symbol)) analyticsEventsHandler.send(TokenReceiveAnalyticsEvent.ReceiveScreenOpened(cryptoCurrency.symbol)) @@ -587,7 +565,7 @@ internal class TokenDetailsViewModel @Inject constructor( } override fun onGenerateExtendedKey() { - viewModelScope.launch(dispatchers.main) { + modelScope.launch(dispatchers.main) { val extendedKey = getExtendedPublicKeyForCurrencyUseCase( userWalletId, cryptoCurrency.network, @@ -655,7 +633,7 @@ internal class TokenDetailsViewModel @Inject constructor( override fun onHideClick() { analyticsEventsHandler.send(TokenScreenAnalyticsEvent.ButtonRemoveToken(cryptoCurrency.symbol)) - viewModelScope.launch { + modelScope.launch { val hasLinkedTokens = removeCurrencyUseCase.hasLinkedTokens(userWalletId, cryptoCurrency) internalUiState.value = if (hasLinkedTokens) { stateFactory.getStateWithLinkedTokensDialog(cryptoCurrency) @@ -666,7 +644,7 @@ internal class TokenDetailsViewModel @Inject constructor( } override fun onHideConfirmed() { - viewModelScope.launch { + modelScope.launch { removeCurrencyUseCase.invoke(userWalletId, cryptoCurrency) .onLeft { Timber.e(it) } .onRight { router.popBackStack() } @@ -681,7 +659,7 @@ internal class TokenDetailsViewModel @Inject constructor( private fun openExplorer() { val currencyStatus = cryptoCurrencyStatus ?: return - viewModelScope.launch(dispatchers.main) { + modelScope.launch(dispatchers.main) { when (val addresses = currencyStatus.value.networkAddress) { is NetworkAddress.Selectable -> { internalUiState.value = stateFactory.getStateWithChooseAddressBottomSheet(cryptoCurrency, addresses) @@ -713,7 +691,7 @@ internal class TokenDetailsViewModel @Inject constructor( } override fun onAddressTypeSelected(addressModel: AddressModel) { - viewModelScope.launch { + modelScope.launch { router.openUrl( url = getExploreUrlUseCase( userWalletId = userWalletId, @@ -738,7 +716,7 @@ internal class TokenDetailsViewModel @Inject constructor( override fun onRefreshSwipe(isRefreshing: Boolean) { internalUiState.value = stateFactory.getRefreshingState() - viewModelScope.launch(dispatchers.main) { + modelScope.launch(dispatchers.main) { listOf( async { fetchCurrencyStatusUseCase( @@ -762,7 +740,7 @@ internal class TokenDetailsViewModel @Inject constructor( override fun onDismissBottomSheet() { when (val bsContent = internalUiState.value.bottomSheetConfig?.content) { is ExpressStatusBottomSheetConfig -> { - viewModelScope.launch(dispatchers.main) { + modelScope.launch(dispatchers.main) { expressStatusFactory.removeTransactionOnBottomSheetClosed(bsContent.value) } } @@ -792,7 +770,7 @@ internal class TokenDetailsViewModel @Inject constructor( } override fun onSwapPromoDismiss() { - viewModelScope.launch(dispatchers.main) { + modelScope.launch(dispatchers.main) { shouldShowSwapPromoTokenUseCase.neverToShow() analyticsEventsHandler.send( TokenSwapPromoAnalyticsEvent.PromotionBannerClicked( @@ -805,7 +783,7 @@ internal class TokenDetailsViewModel @Inject constructor( } override fun onSwapPromoClick() { - viewModelScope.launch(dispatchers.main) { + modelScope.launch(dispatchers.main) { shouldShowSwapPromoTokenUseCase.neverToShow() analyticsEventsHandler.send( TokenSwapPromoAnalyticsEvent.PromotionBannerClicked( @@ -836,7 +814,7 @@ internal class TokenDetailsViewModel @Inject constructor( blockchain = cryptoCurrency.network.name, ), ) - viewModelScope.launch { + modelScope.launch { retryIncompleteTransactionUseCase( userWalletId = userWalletId, currency = cryptoCurrency, @@ -877,13 +855,13 @@ internal class TokenDetailsViewModel @Inject constructor( blockchain = cryptoCurrency.network.name, ), ) - viewModelScope.launch { + modelScope.launch { internalUiState.value = stateFactory.getStateWithDismissIncompleteTransactionConfirmDialog() } } override fun onConfirmDismissIncompleteTransactionClick() { - viewModelScope.launch { + modelScope.launch { dismissIncompleteTransactionUseCase( userWalletId = userWalletId, currency = cryptoCurrency, @@ -908,7 +886,7 @@ internal class TokenDetailsViewModel @Inject constructor( blockchain = cryptoCurrency.network.name, ), ) - viewModelScope.launch(dispatchers.io) { + modelScope.launch(dispatchers.io) { associateAssetUseCase( userWalletId = userWalletId, currency = cryptoCurrency, @@ -947,7 +925,7 @@ internal class TokenDetailsViewModel @Inject constructor( override fun onDisposeExpressStatus() { val bottomSheetState = internalUiState.value.bottomSheetConfig?.content if (bottomSheetState is ExpressStatusBottomSheetConfig) { - viewModelScope.launch { + modelScope.launch { expressStatusFactory.removeTransactionOnBottomSheetClosed( expressState = bottomSheetState.value, isForceDispose = true, @@ -979,7 +957,7 @@ internal class TokenDetailsViewModel @Inject constructor( } private fun openStaking() { - viewModelScope.launch { + modelScope.launch { val yield = getYieldUseCase.invoke( cryptoCurrencyId = cryptoCurrency.id, symbol = cryptoCurrency.symbol, diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsActionButtonsConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsActionButtonsConverter.kt index c68c1e3be2..50052f3557 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsActionButtonsConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsActionButtonsConverter.kt @@ -4,7 +4,7 @@ import com.tangem.domain.tokens.model.ScenarioUnavailabilityReason import com.tangem.domain.tokens.model.TokenActionsState import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsActionButton -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.utils.Provider import com.tangem.utils.converter.Converter import kotlinx.collections.immutable.ImmutableList diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt index 91ac3d6a00..75bb0ebc77 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt @@ -22,7 +22,7 @@ import com.tangem.feature.tokendetails.presentation.tokendetails.state.* import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsNotification import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.txhistory.TokenDetailsTxHistoryTransactionStateConverter import com.tangem.feature.tokendetails.presentation.tokendetails.state.utils.getBalance -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.features.tokendetails.impl.R import com.tangem.lib.crypto.BlockchainUtils.isBSC import com.tangem.lib.crypto.BlockchainUtils.isSolana diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsNotificationConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsNotificationConverter.kt index 1c0e9869ad..f8d51e82c0 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsNotificationConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsNotificationConverter.kt @@ -13,7 +13,7 @@ import com.tangem.domain.tokens.model.warnings.KaspaWarnings import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsNotification import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsNotification.* -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.features.tokendetails.impl.R import com.tangem.utils.converter.Converter import com.tangem.utils.extensions.removeBy diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsOnrampTransactionStateConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsOnrampTransactionStateConverter.kt index ec6b983685..c585e6e3cd 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsOnrampTransactionStateConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsOnrampTransactionStateConverter.kt @@ -26,7 +26,7 @@ import com.tangem.domain.tokens.model.analytics.TokenOnrampAnalyticsEvent import com.tangem.common.ui.expressStatus.state.ExpressTransactionStateIconUM import com.tangem.common.ui.expressStatus.state.ExpressTransactionStateInfoUM import com.tangem.common.ui.expressStatus.state.ExpressTransactionStateUM -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.features.tokendetails.impl.R import com.tangem.utils.Provider import com.tangem.utils.converter.Converter diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSkeletonStateConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSkeletonStateConverter.kt index 44798192e1..d4f23daa2d 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSkeletonStateConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSkeletonStateConverter.kt @@ -16,7 +16,7 @@ import com.tangem.domain.wallets.models.UserWalletId import com.tangem.domain.wallets.usecase.GetUserWalletUseCase import com.tangem.feature.tokendetails.presentation.tokendetails.state.* import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsActionButton -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.features.tokendetails.impl.R import com.tangem.lib.crypto.BlockchainUtils.isBitcoin import com.tangem.utils.converter.Converter diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt index e88c1cc061..a76e681373 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt @@ -33,7 +33,7 @@ import com.tangem.feature.tokendetails.presentation.tokendetails.state.component import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.txhistory.TokenDetailsLoadedTxHistoryConverter import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.txhistory.TokenDetailsLoadingTxHistoryConverter import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.txhistory.TokenDetailsLoadingTxHistoryConverter.TokenDetailsLoadingTxHistoryModel -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.features.tokendetails.impl.R import com.tangem.utils.Provider import kotlinx.collections.immutable.toImmutableList diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSwapTransactionsStateConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSwapTransactionsStateConverter.kt index e8e7415770..d13c0cab28 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSwapTransactionsStateConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSwapTransactionsStateConverter.kt @@ -27,7 +27,7 @@ import com.tangem.feature.swap.domain.models.domain.SavedSwapTransactionModel import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.ExchangeStatusNotifications import com.tangem.feature.tokendetails.presentation.tokendetails.state.express.ExchangeStatusState import com.tangem.feature.tokendetails.presentation.tokendetails.state.express.ExchangeUM -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.features.tokendetails.impl.R import com.tangem.utils.Provider import com.tangem.utils.converter.Converter diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExchangeStatusFactory.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExchangeStatusFactory.kt index 3bf62b35de..8596a83abd 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExchangeStatusFactory.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExchangeStatusFactory.kt @@ -18,7 +18,7 @@ import com.tangem.feature.swap.domain.models.domain.* import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState import com.tangem.feature.tokendetails.presentation.tokendetails.state.express.ExchangeUM import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.TokenDetailsSwapTransactionsStateConverter -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.utils.Provider import dagger.assisted.Assisted import dagger.assisted.AssistedFactory diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExpressStatusFactory.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExpressStatusFactory.kt index 5f1c18949f..289cfffede 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExpressStatusFactory.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExpressStatusFactory.kt @@ -13,7 +13,7 @@ import com.tangem.domain.wallets.models.UserWalletId import com.tangem.feature.swap.domain.models.domain.ExchangeStatus import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState import com.tangem.feature.tokendetails.presentation.tokendetails.state.express.ExchangeUM -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.utils.Provider import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.assisted.Assisted diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/OnrampStatusFactory.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/OnrampStatusFactory.kt index 79328454af..e25e788d52 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/OnrampStatusFactory.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/OnrampStatusFactory.kt @@ -17,7 +17,7 @@ import com.tangem.domain.tokens.model.analytics.TokenOnrampAnalyticsEvent import com.tangem.domain.wallets.models.UserWalletId import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.TokenDetailsOnrampTransactionStateConverter -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.utils.Provider import dagger.assisted.Assisted import dagger.assisted.AssistedFactory diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsLoadedTxHistoryConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsLoadedTxHistoryConverter.kt index efcc958a22..cb5e434ccf 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsLoadedTxHistoryConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsLoadedTxHistoryConverter.kt @@ -6,7 +6,7 @@ import com.tangem.core.ui.components.transactions.state.TxHistoryState import com.tangem.domain.txhistory.models.TxHistoryItem import com.tangem.domain.txhistory.models.TxHistoryListError import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.utils.Provider import com.tangem.utils.converter.Converter import kotlinx.coroutines.flow.Flow diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsLoadingTxHistoryConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsLoadingTxHistoryConverter.kt index e7c0cd2e1b..479a510db6 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsLoadingTxHistoryConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsLoadingTxHistoryConverter.kt @@ -7,7 +7,7 @@ import com.tangem.core.ui.components.transactions.state.TxHistoryState import com.tangem.domain.txhistory.models.TxHistoryStateError import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.txhistory.TokenDetailsLoadingTxHistoryConverter.TokenDetailsLoadingTxHistoryModel -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.utils.Provider import com.tangem.utils.converter.Converter import kotlinx.collections.immutable.toImmutableList diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryItemFlowConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryItemFlowConverter.kt index 6a8bc163c7..2dc64a9aef 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryItemFlowConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryItemFlowConverter.kt @@ -7,7 +7,7 @@ import com.tangem.core.ui.components.transactions.state.TxHistoryState.TxHistory import com.tangem.core.ui.utils.toDateFormatWithTodayYesterday import com.tangem.domain.txhistory.models.TxHistoryItem import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.utils.Provider import com.tangem.utils.converter.Converter import kotlinx.coroutines.CoroutineScope diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryTransactionStateConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryTransactionStateConverter.kt index 360126d91d..8bc7cf05cd 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryTransactionStateConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryTransactionStateConverter.kt @@ -12,7 +12,7 @@ import com.tangem.core.ui.format.bigdecimal.format import com.tangem.core.ui.utils.toTimeFormat import com.tangem.domain.txhistory.models.TxHistoryItem import com.tangem.domain.txhistory.models.TxHistoryItem.* -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.features.tokendetails.impl.R import com.tangem.utils.StringsSigns.MINUS import com.tangem.utils.StringsSigns.PLUS From 0658cf67cbd976b5236eb1ccb0aa95a4f0975110 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 19 Feb 2025 15:55:27 +0500 Subject: [PATCH 05/33] Updated on 2026-08-14 --- .../presentation/common/WalletPreviewData.kt | 10 +-- .../common/preview/WalletScreenPreviewData.kt | 6 +- .../implementors/MultiWalletContentLoader.kt | 8 ++ .../MultiWalletContentLoaderFactory.kt | 3 + .../implementors/SingleWalletContentLoader.kt | 7 ++ .../SingleWalletContentLoaderFactory.kt | 3 + .../SingleWalletWithTokenContentLoader.kt | 9 +++ ...ngleWalletWithTokenContentLoaderFactory.kt | 3 + .../wallet/state/model/WalletCardState.kt | 45 +++++------ .../wallet/state/model/WalletDropDownItems.kt | 10 +++ .../InitializeWalletsTransformer.kt | 3 +- .../SetBalancesAndLimitsTransformer.kt | 6 +- .../SetTokenListErrorTransformer.kt | 3 +- .../SetWalletCardDropDownItemsTransformer.kt | 78 +++++++++++++++++++ .../MultiWalletCardStateConverter.kt | 9 +-- .../SingleWalletCardStateConverter.kt | 9 +-- .../state/utils/WalletLoadingStateFactory.kt | 3 +- .../WalletDropDownItemsSubscriber.kt | 30 +++++++ .../wallet/ui/components/common/WalletCard.kt | 53 +++++-------- .../wallet/viewmodels/WalletViewModel.kt | 12 +-- 20 files changed, 213 insertions(+), 97 deletions(-) create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletDropDownItems.kt create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetWalletCardDropDownItemsTransformer.kt create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/WalletDropDownItemsSubscriber.kt diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt index f77bbed840..7fd53126fb 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt @@ -13,6 +13,7 @@ import com.tangem.feature.wallet.presentation.organizetokens.model.DraggableItem import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensListState import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensState import com.tangem.feature.wallet.presentation.wallet.state.model.* +import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toPersistentList import java.util.UUID @@ -32,8 +33,7 @@ internal object WalletPreviewData { content = TextReference.Str("3 cards • Seed phrase3 cards • Seed phrasephrasephrasephrase"), ), imageResId = R.drawable.ill_wallet2_cards3_120_106, - onRenameClick = { _ -> }, - onDeleteClick = {}, + dropDownItems = persistentListOf(), cardCount = 1, isZeroBalance = false, isBalanceFlickering = false, @@ -45,8 +45,7 @@ internal object WalletPreviewData { id = UserWalletId("321"), title = "Wallet 1", imageResId = R.drawable.ill_wallet2_cards3_120_106, - onRenameClick = { _ -> }, - onDeleteClick = {}, + dropDownItems = persistentListOf(), ) } @@ -55,8 +54,7 @@ internal object WalletPreviewData { id = UserWalletId("24"), title = "Wallet 1", imageResId = R.drawable.ill_wallet2_cards3_120_106, - onRenameClick = { _ -> }, - onDeleteClick = {}, + dropDownItems = persistentListOf(), ) } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/preview/WalletScreenPreviewData.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/preview/WalletScreenPreviewData.kt index 6bb90675a5..da8b495a9a 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/preview/WalletScreenPreviewData.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/preview/WalletScreenPreviewData.kt @@ -87,8 +87,7 @@ internal object WalletScreenPreviewData { content = TextReference.Str("Locked"), ), imageResId = R.drawable.ill_note_btc_120_106, - onRenameClick = { _ -> }, - onDeleteClick = {}, + dropDownItems = persistentListOf(), ) } private val miltiUnreachableCard by lazy { @@ -102,8 +101,7 @@ internal object WalletScreenPreviewData { imageResId = R.drawable.ill_wallet2_cards3_120_106, cardCount = 3, balance = DASH_SIGN, - onRenameClick = { _ -> }, - onDeleteClick = {}, + dropDownItems = persistentListOf(), isZeroBalance = false, isBalanceFlickering = false, ) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoader.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoader.kt index b5c157f8b4..a80ea9429f 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoader.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoader.kt @@ -6,6 +6,7 @@ import com.tangem.domain.promo.GetStoryContentUseCase import com.tangem.domain.tokens.ApplyTokenListSortingUseCase import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase import com.tangem.domain.wallets.models.UserWallet +import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase import com.tangem.feature.wallet.presentation.wallet.analytics.utils.TokenListAnalyticsSender import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsSingleEventSender @@ -13,6 +14,7 @@ import com.tangem.feature.wallet.presentation.wallet.domain.GetMultiWalletWarnin import com.tangem.feature.wallet.presentation.wallet.domain.MultiWalletTokenListStore import com.tangem.feature.wallet.presentation.wallet.domain.WalletWithFundsChecker import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController +import com.tangem.feature.wallet.presentation.wallet.subscribers.* import com.tangem.feature.wallet.presentation.wallet.subscribers.MultiWalletActionButtonsSubscriber import com.tangem.feature.wallet.presentation.wallet.subscribers.MultiWalletTokenListSubscriber import com.tangem.feature.wallet.presentation.wallet.subscribers.MultiWalletWarningsSubscriber @@ -34,6 +36,7 @@ internal class MultiWalletContentLoader( private val applyTokenListSortingUseCase: ApplyTokenListSortingUseCase, private val getMultiWalletWarningsFactory: GetMultiWalletWarningsFactory, private val runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase, + private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase, private val getStoryContentUseCase: GetStoryContentUseCase, private val swapFeatureToggles: SwapFeatureToggles, private val deepLinksRegistry: DeepLinksRegistry, @@ -68,6 +71,11 @@ internal class MultiWalletContentLoader( getStoryContentUseCase = getStoryContentUseCase, ).let(::add) } + WalletDropDownItemsSubscriber( + stateHolder = stateHolder, + shouldSaveUserWalletsUseCase = shouldSaveUserWalletsUseCase, + clickIntents = clickIntents, + ).let(::add) } } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoaderFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoaderFactory.kt index 0196a960d0..03ffae14b8 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoaderFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoaderFactory.kt @@ -6,6 +6,7 @@ import com.tangem.domain.promo.GetStoryContentUseCase import com.tangem.domain.tokens.ApplyTokenListSortingUseCase import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase import com.tangem.domain.wallets.models.UserWallet +import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase import com.tangem.feature.wallet.presentation.wallet.analytics.utils.TokenListAnalyticsSender import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsSingleEventSender @@ -31,6 +32,7 @@ internal class MultiWalletContentLoaderFactory @Inject constructor( private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender, private val walletWarningsSingleEventSender: WalletWarningsSingleEventSender, private val runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase, + private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase, private val getStoryContentUseCase: GetStoryContentUseCase, private val swapFeatureToggles: SwapFeatureToggles, private val deepLinksRegistry: DeepLinksRegistry, @@ -51,6 +53,7 @@ internal class MultiWalletContentLoaderFactory @Inject constructor( applyTokenListSortingUseCase = applyTokenListSortingUseCase, runPolkadotAccountHealthCheckUseCase = runPolkadotAccountHealthCheckUseCase, getStoryContentUseCase = getStoryContentUseCase, + shouldSaveUserWalletsUseCase = shouldSaveUserWalletsUseCase, swapFeatureToggles = swapFeatureToggles, deepLinksRegistry = deepLinksRegistry, ) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletContentLoader.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletContentLoader.kt index 0d96fb7855..5ebe780476 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletContentLoader.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletContentLoader.kt @@ -10,6 +10,7 @@ import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase import com.tangem.domain.wallets.models.UserWallet +import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender import com.tangem.feature.wallet.presentation.wallet.domain.GetSingleWalletWarningsFactory import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController @@ -31,6 +32,7 @@ internal class SingleWalletContentLoader( private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, private val getOnrampTransactionsUseCase: GetOnrampTransactionsUseCase, private val onrampRemoveTransactionUseCase: OnrampRemoveTransactionUseCase, + private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase, private val analyticsEventHandler: AnalyticsEventHandler, private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender, ) : WalletContentLoader(id = userWallet.walletId) { @@ -59,6 +61,11 @@ internal class SingleWalletContentLoader( getSingleWalletWarningsFactory = getSingleWalletWarningsFactory, walletWarningsAnalyticsSender = walletWarningsAnalyticsSender, ), + WalletDropDownItemsSubscriber( + stateHolder = stateHolder, + shouldSaveUserWalletsUseCase = shouldSaveUserWalletsUseCase, + clickIntents = clickIntents, + ), SingleWalletExpressStatusesSubscriber( userWallet = userWallet, stateHolder = stateHolder, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletContentLoaderFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletContentLoaderFactory.kt index aa40c79e7f..d6a6f49dae 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletContentLoaderFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletContentLoaderFactory.kt @@ -10,6 +10,7 @@ import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase import com.tangem.domain.wallets.models.UserWallet +import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender import com.tangem.feature.wallet.presentation.wallet.domain.GetSingleWalletWarningsFactory import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController @@ -30,6 +31,7 @@ internal class SingleWalletContentLoaderFactory @Inject constructor( private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, private val getOnrampTransactionsUseCase: GetOnrampTransactionsUseCase, private val onrampRemoveTransactionUseCase: OnrampRemoveTransactionUseCase, + private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase, private val analyticsEventHandler: AnalyticsEventHandler, private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender, ) { @@ -51,6 +53,7 @@ internal class SingleWalletContentLoaderFactory @Inject constructor( walletWarningsAnalyticsSender = walletWarningsAnalyticsSender, getOnrampTransactionsUseCase = getOnrampTransactionsUseCase, onrampRemoveTransactionUseCase = onrampRemoveTransactionUseCase, + shouldSaveUserWalletsUseCase = shouldSaveUserWalletsUseCase, ) } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoader.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoader.kt index e87a5d2d10..666c0eaacc 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoader.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoader.kt @@ -5,6 +5,7 @@ import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.promo.GetStoryContentUseCase import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase import com.tangem.domain.wallets.models.UserWallet +import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase import com.tangem.feature.wallet.presentation.wallet.analytics.utils.TokenListAnalyticsSender import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsSingleEventSender @@ -12,9 +13,11 @@ import com.tangem.feature.wallet.presentation.wallet.domain.GetMultiWalletWarnin import com.tangem.feature.wallet.presentation.wallet.domain.MultiWalletTokenListStore import com.tangem.feature.wallet.presentation.wallet.domain.WalletWithFundsChecker import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController +import com.tangem.feature.wallet.presentation.wallet.subscribers.* import com.tangem.feature.wallet.presentation.wallet.subscribers.MultiWalletActionButtonsSubscriber import com.tangem.feature.wallet.presentation.wallet.subscribers.MultiWalletWarningsSubscriber import com.tangem.feature.wallet.presentation.wallet.subscribers.SingleWalletWithTokenListSubscriber +import com.tangem.feature.wallet.presentation.wallet.subscribers.WalletDropDownItemsSubscriber import com.tangem.feature.wallet.presentation.wallet.subscribers.WalletSubscriber import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.WalletClickIntents import com.tangem.features.swap.SwapFeatureToggles @@ -32,6 +35,7 @@ internal class SingleWalletWithTokenContentLoader( private val tokenListStore: MultiWalletTokenListStore, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, private val runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase, + private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase, private val getStoryContentUseCase: GetStoryContentUseCase, private val swapFeatureToggles: SwapFeatureToggles, private val deepLinksRegistry: DeepLinksRegistry, @@ -65,6 +69,11 @@ internal class SingleWalletWithTokenContentLoader( getStoryContentUseCase = getStoryContentUseCase, ).let(::add) } + WalletDropDownItemsSubscriber( + stateHolder = stateHolder, + shouldSaveUserWalletsUseCase = shouldSaveUserWalletsUseCase, + clickIntents = clickIntents, + ).let(::add) } } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoaderFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoaderFactory.kt index 002f3fc487..78cd9fa1ca 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoaderFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoaderFactory.kt @@ -5,6 +5,7 @@ import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.promo.GetStoryContentUseCase import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase import com.tangem.domain.wallets.models.UserWallet +import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase import com.tangem.feature.wallet.presentation.wallet.analytics.utils.TokenListAnalyticsSender import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsSingleEventSender @@ -28,6 +29,7 @@ internal class SingleWalletWithTokenContentLoaderFactory @Inject constructor( private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender, private val walletWarningsSingleEventSender: WalletWarningsSingleEventSender, private val runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase, + private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase, private val getStoryContentUseCase: GetStoryContentUseCase, private val swapFeatureToggles: SwapFeatureToggles, private val deepLinksRegistry: DeepLinksRegistry, @@ -47,6 +49,7 @@ internal class SingleWalletWithTokenContentLoaderFactory @Inject constructor( walletWarningsSingleEventSender = walletWarningsSingleEventSender, runPolkadotAccountHealthCheckUseCase = runPolkadotAccountHealthCheckUseCase, getStoryContentUseCase = getStoryContentUseCase, + shouldSaveUserWalletsUseCase = shouldSaveUserWalletsUseCase, swapFeatureToggles = swapFeatureToggles, deepLinksRegistry = deepLinksRegistry, ) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletCardState.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletCardState.kt index c03ee58d88..2be0662c6c 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletCardState.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletCardState.kt @@ -5,6 +5,7 @@ import androidx.compose.runtime.Immutable import com.tangem.core.ui.extensions.TextReference import com.tangem.domain.wallets.models.UserWalletId import com.tangem.utils.StringsSigns.DASH_SIGN +import kotlinx.collections.immutable.ImmutableList /** Wallet card state */ @Immutable @@ -23,11 +24,8 @@ internal sealed interface WalletCardState { @get:DrawableRes val imageResId: Int? - /** Lambda be invoked when Rename button is clicked */ - val onRenameClick: (UserWalletId) -> Unit - - /** Lambda be invoked when Delete button is clicked */ - val onDeleteClick: (UserWalletId) -> Unit + /** Wallet drop down items */ + val dropDownItems: ImmutableList /** * Wallet card content state @@ -35,8 +33,7 @@ internal sealed interface WalletCardState { * @property id wallet id * @property title wallet name * @property imageResId wallet image resource id - * @property onRenameClick lambda be invoked when Rename button is clicked - * @property onDeleteClick lambda be invoked when Delete button is clicked + * @property dropDownItems wallet dropdown items * @property additionalInfo wallet additional info * @property cardCount number of cards in the wallet * @property balance wallet balance @@ -46,8 +43,7 @@ internal sealed interface WalletCardState { override val title: String, override val additionalInfo: WalletAdditionalInfo, override val imageResId: Int?, - override val onRenameClick: (UserWalletId) -> Unit, - override val onDeleteClick: (UserWalletId) -> Unit, + override val dropDownItems: ImmutableList, val isBalanceFlickering: Boolean, val cardCount: Int?, val balance: String, @@ -61,16 +57,14 @@ internal sealed interface WalletCardState { * @property title wallet name * @property additionalInfo wallet additional info * @property imageResId wallet image resource id - * @property onRenameClick lambda be invoked when Rename button is clicked - * @property onDeleteClick lambda be invoked when Delete button is clicked + * @property dropDownItems wallet dropdown items */ data class LockedContent( override val id: UserWalletId, override val title: String, override val additionalInfo: WalletAdditionalInfo, override val imageResId: Int?, - override val onRenameClick: (UserWalletId) -> Unit, - override val onDeleteClick: (UserWalletId) -> Unit, + override val dropDownItems: ImmutableList, ) : WalletCardState /** @@ -79,16 +73,14 @@ internal sealed interface WalletCardState { * @property id wallet id * @property title wallet name * @property imageResId wallet image resource id - * @property onRenameClick lambda be invoked when Rename button is clicked - * @property onDeleteClick lambda be invoked when Delete button is clicked + * @property dropDownItems wallet dropdown items */ data class Error( override val id: UserWalletId, override val title: String, override val additionalInfo: WalletAdditionalInfo? = defaultAdditionalInfo, override val imageResId: Int?, - override val onRenameClick: (UserWalletId) -> Unit, - override val onDeleteClick: (UserWalletId) -> Unit, + override val dropDownItems: ImmutableList, ) : WalletCardState { private companion object { @@ -103,24 +95,25 @@ internal sealed interface WalletCardState { * @property id wallet id * @property title wallet name * @property imageResId wallet image resource id - * @property onRenameClick lambda be invoked when Rename button is clicked - * @property onDeleteClick lambda be invoked when Delete button is clicked + * @property dropDownItems wallet dropdown items */ data class Loading( override val id: UserWalletId, override val title: String, override val additionalInfo: WalletAdditionalInfo? = null, override val imageResId: Int?, - override val onRenameClick: (UserWalletId) -> Unit, - override val onDeleteClick: (UserWalletId) -> Unit, + override val dropDownItems: ImmutableList, ) : WalletCardState - fun copySealed(title: String = this.title): WalletCardState { + fun copySealed( + title: String = this.title, + dropDownItems: ImmutableList = this.dropDownItems, + ): WalletCardState { return when (this) { - is Content -> copy(title = title) - is Error -> copy(title = title) - is Loading -> copy(title = title) - is LockedContent -> copy(title = title) + is Content -> copy(title = title, dropDownItems = dropDownItems) + is Error -> copy(title = title, dropDownItems = dropDownItems) + is Loading -> copy(title = title, dropDownItems = dropDownItems) + is LockedContent -> copy(title = title, dropDownItems = dropDownItems) } } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletDropDownItems.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletDropDownItems.kt new file mode 100644 index 0000000000..6e9166db40 --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletDropDownItems.kt @@ -0,0 +1,10 @@ +package com.tangem.feature.wallet.presentation.wallet.state.model + +import androidx.compose.ui.graphics.vector.ImageVector +import com.tangem.core.ui.extensions.TextReference + +internal data class WalletDropDownItems( + val text: TextReference, + val icon: ImageVector, + val onClick: () -> Unit, +) \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/InitializeWalletsTransformer.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/InitializeWalletsTransformer.kt index bfa6f1caa6..63b2d6c2a6 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/InitializeWalletsTransformer.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/InitializeWalletsTransformer.kt @@ -91,8 +91,7 @@ internal class InitializeWalletsTransformer( title = name, additionalInfo = WalletAdditionalInfoFactory.resolve(wallet = this), imageResId = walletImageResolver.resolve(userWallet = this), - onRenameClick = clickIntents::onRenameBeforeConfirmationClick, - onDeleteClick = clickIntents::onDeleteBeforeConfirmationClick, + dropDownItems = persistentListOf(), ) } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetBalancesAndLimitsTransformer.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetBalancesAndLimitsTransformer.kt index 97bbb348fb..a4d821f725 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetBalancesAndLimitsTransformer.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetBalancesAndLimitsTransformer.kt @@ -58,8 +58,7 @@ internal class SetBalancesAndLimitsTransformer( id = id, title = title, imageResId = imageResId, - onRenameClick = onRenameClick, - onDeleteClick = onDeleteClick, + dropDownItems = dropDownItems, ) } } @@ -71,8 +70,7 @@ internal class SetBalancesAndLimitsTransformer( title = title, additionalInfo = createAdditionalInfo(visaCurrency), imageResId = imageResId, - onRenameClick = onRenameClick, - onDeleteClick = onDeleteClick, + dropDownItems = dropDownItems, balance = visaCurrency.balances.available.format { crypto(visaCurrency.symbol, visaCurrency.decimals) }, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTokenListErrorTransformer.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTokenListErrorTransformer.kt index 3705598bcd..a3522cddca 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTokenListErrorTransformer.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTokenListErrorTransformer.kt @@ -60,8 +60,7 @@ internal class SetTokenListErrorTransformer( title = title, additionalInfo = WalletAdditionalInfoFactory.resolve(wallet = selectedWallet), imageResId = imageResId, - onRenameClick = onRenameClick, - onDeleteClick = onDeleteClick, + dropDownItems = dropDownItems, balance = BigDecimalFormatter.formatFiatAmount( fiatAmount = BigDecimal.ZERO, fiatCurrencyCode = appCurrency.code, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetWalletCardDropDownItemsTransformer.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetWalletCardDropDownItemsTransformer.kt new file mode 100644 index 0000000000..f538e29f90 --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetWalletCardDropDownItemsTransformer.kt @@ -0,0 +1,78 @@ +package com.tangem.feature.wallet.presentation.wallet.state.transformers + +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Delete +import androidx.compose.material.icons.outlined.Edit +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.domain.wallets.models.UserWalletId +import com.tangem.feature.wallet.impl.R +import com.tangem.feature.wallet.presentation.wallet.state.model.WalletDropDownItems +import com.tangem.feature.wallet.presentation.wallet.state.model.WalletScreenState +import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState +import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.WalletCardClickIntents +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toImmutableList + +internal class SetWalletCardDropDownItemsTransformer( + private val dropdownEnabled: Boolean, + private val clickIntents: WalletCardClickIntents, +) : WalletScreenStateTransformer { + override fun transform(prevState: WalletScreenState): WalletScreenState { + return prevState.copy(wallets = prevState.wallets.map(::transformWalletState).toImmutableList()) + } + + private fun transformWalletState(prevState: WalletState): WalletState { + return when (prevState) { + is WalletState.MultiCurrency.Content -> prevState.copy( + walletCardState = prevState.walletCardState.copySealed( + dropDownItems = constructDropDownItems(prevState.walletCardState.id), + ), + ) + is WalletState.SingleCurrency.Content -> prevState.copy( + walletCardState = prevState.walletCardState.copySealed( + dropDownItems = constructDropDownItems(prevState.walletCardState.id), + ), + ) + is WalletState.Visa.Content -> prevState.copy( + walletCardState = prevState.walletCardState.copySealed( + dropDownItems = constructDropDownItems(prevState.walletCardState.id), + ), + ) + is WalletState.MultiCurrency.Locked -> prevState.copy( + walletCardState = prevState.walletCardState.copySealed( + dropDownItems = constructDropDownItems(prevState.walletCardState.id), + ), + ) + is WalletState.SingleCurrency.Locked -> prevState.copy( + walletCardState = prevState.walletCardState.copySealed( + dropDownItems = constructDropDownItems(prevState.walletCardState.id), + ), + ) + is WalletState.Visa.Locked -> prevState.copy( + walletCardState = prevState.walletCardState.copySealed( + dropDownItems = constructDropDownItems(prevState.walletCardState.id), + ), + ) + } + } + + private fun constructDropDownItems(userWalletId: UserWalletId): ImmutableList { + return if (dropdownEnabled) { + persistentListOf( + WalletDropDownItems( + text = resourceReference(id = R.string.common_rename), + icon = Icons.Outlined.Edit, + onClick = { clickIntents.onRenameBeforeConfirmationClick(userWalletId) }, + ), + WalletDropDownItems( + text = resourceReference(id = R.string.common_delete), + icon = Icons.Outlined.Delete, + onClick = { clickIntents.onDeleteBeforeConfirmationClick(userWalletId) }, + ), + ) + } else { + persistentListOf() + } + } +} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/MultiWalletCardStateConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/MultiWalletCardStateConverter.kt index 2fdbb17338..65a68880bb 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/MultiWalletCardStateConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/MultiWalletCardStateConverter.kt @@ -30,8 +30,7 @@ internal class MultiWalletCardStateConverter( title = title, additionalInfo = additionalInfo, imageResId = imageResId, - onRenameClick = onRenameClick, - onDeleteClick = onDeleteClick, + dropDownItems = dropDownItems, ) } @@ -41,8 +40,7 @@ internal class MultiWalletCardStateConverter( title = title, additionalInfo = additionalInfo, imageResId = imageResId, - onDeleteClick = onDeleteClick, - onRenameClick = onRenameClick, + dropDownItems = dropDownItems, ) } @@ -52,8 +50,7 @@ internal class MultiWalletCardStateConverter( title = title, additionalInfo = WalletAdditionalInfoFactory.resolve(wallet = selectedWallet), imageResId = imageResId, - onRenameClick = onRenameClick, - onDeleteClick = onDeleteClick, + dropDownItems = dropDownItems, balance = BigDecimalFormatter.formatFiatAmount( fiatAmount = fiatBalance.amount, fiatCurrencyCode = appCurrency.code, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/SingleWalletCardStateConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/SingleWalletCardStateConverter.kt index 83dd7c2422..f763c222f8 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/SingleWalletCardStateConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/SingleWalletCardStateConverter.kt @@ -36,8 +36,7 @@ internal class SingleWalletCardStateConverter( id = id, title = title, imageResId = imageResId, - onRenameClick = onRenameClick, - onDeleteClick = onDeleteClick, + dropDownItems = dropDownItems, ) } @@ -46,8 +45,7 @@ internal class SingleWalletCardStateConverter( id = id, title = title, imageResId = imageResId, - onRenameClick = onRenameClick, - onDeleteClick = onDeleteClick, + dropDownItems = dropDownItems, ) } @@ -60,8 +58,7 @@ internal class SingleWalletCardStateConverter( currencyAmount = status.amount, ), imageResId = imageResId, - onRenameClick = onRenameClick, - onDeleteClick = onDeleteClick, + dropDownItems = dropDownItems, balance = formatFiatAmount(status = status, appCurrency = appCurrency), cardCount = selectedWallet.getCardsCount(), isZeroBalance = status.fiatAmount?.isZero(), diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/utils/WalletLoadingStateFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/utils/WalletLoadingStateFactory.kt index 601894c802..2ea461b088 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/utils/WalletLoadingStateFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/utils/WalletLoadingStateFactory.kt @@ -90,8 +90,7 @@ internal class WalletLoadingStateFactory( title = name, additionalInfo = if (isMultiCurrency) WalletAdditionalInfoFactory.resolve(wallet = this) else null, imageResId = walletImageResolver.resolve(userWallet = this), - onRenameClick = clickIntents::onRenameBeforeConfirmationClick, - onDeleteClick = clickIntents::onDeleteBeforeConfirmationClick, + dropDownItems = persistentListOf(), ) } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/WalletDropDownItemsSubscriber.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/WalletDropDownItemsSubscriber.kt new file mode 100644 index 0000000000..b58c62f9a1 --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/WalletDropDownItemsSubscriber.kt @@ -0,0 +1,30 @@ +package com.tangem.feature.wallet.presentation.wallet.subscribers + +import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase +import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController +import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetWalletCardDropDownItemsTransformer +import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.WalletClickIntents +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.* + +internal class WalletDropDownItemsSubscriber( + private val stateHolder: WalletStateController, + private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase, + private val clickIntents: WalletClickIntents, +) : WalletSubscriber() { + override fun create(coroutineScope: CoroutineScope): Flow<*> { + return flow { + shouldSaveUserWalletsUseCase.invoke() + .distinctUntilChanged() + .onEach { + stateHolder.update( + SetWalletCardDropDownItemsTransformer( + dropdownEnabled = it, + clickIntents = clickIntents, + ), + ) + } + .launchIn(coroutineScope) + } + } +} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletCard.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletCard.kt index 2539a970d6..dd24826ded 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletCard.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletCard.kt @@ -2,7 +2,6 @@ package com.tangem.feature.wallet.presentation.wallet.ui.components.common import android.content.res.Configuration import androidx.annotation.DrawableRes -import androidx.annotation.StringRes import androidx.compose.animation.* import androidx.compose.animation.core.tween import androidx.compose.foundation.Image @@ -14,9 +13,6 @@ import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.PressInteraction import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.Delete -import androidx.compose.material.icons.outlined.Edit import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable @@ -48,13 +44,14 @@ import com.tangem.core.ui.components.flicker import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.orMaskWithStars import com.tangem.core.ui.extensions.resolveReference -import com.tangem.core.ui.extensions.stringResourceSafe import com.tangem.core.ui.res.TangemDimens import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview -import com.tangem.feature.wallet.impl.R import com.tangem.feature.wallet.presentation.common.WalletPreviewData import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState +import com.tangem.feature.wallet.presentation.wallet.state.model.WalletDropDownItems +import com.tangem.feature.wallet.presentation.wallet.ui.components.fastForEach +import kotlinx.collections.immutable.ImmutableList private const val HALF_OF_ITEM_WIDTH = 0.5 @@ -71,8 +68,7 @@ private const val HALF_OF_ITEM_WIDTH = 0.5 internal fun WalletCard(state: WalletCardState, isBalanceHidden: Boolean, modifier: Modifier = Modifier) { @Suppress("DestructuringDeclarationWithTooManyEntries") CardContainer( - onDeleteClick = { state.onDeleteClick(state.id) }, - onRenameClick = { state.onRenameClick(state.id) }, + dropDownItems = state.dropDownItems, isLockedState = state is WalletCardState.LockedContent, modifier = modifier, ) { itemSize -> @@ -148,8 +144,7 @@ internal fun WalletCard(state: WalletCardState, isBalanceHidden: Boolean, modifi @Composable private fun CardContainer( - onDeleteClick: () -> Unit, - onRenameClick: () -> Unit, + dropDownItems: ImmutableList, isLockedState: Boolean, modifier: Modifier = Modifier, content: @Composable (ConstraintLayoutScope.(IntSize) -> Unit), @@ -167,7 +162,7 @@ private fun CardContainer( .defaultMinSize(minHeight = TangemTheme.dimens.size108) .onSizeChanged { itemSize = it } .then( - if (isLockedState) { + if (isLockedState || dropDownItems.isEmpty()) { Modifier } else { Modifier @@ -210,8 +205,7 @@ private fun CardContainer( pressOffset = pressOffset, itemHeight = itemHeight, onDismissRequest = { isMenuVisible = false }, - onShowRenameWalletDialogClick = onRenameClick, - onDeleteClick = onDeleteClick, + dropDownItems = dropDownItems, ) } @@ -222,8 +216,7 @@ private fun ManageWalletContextMenu( pressOffset: DpOffset, itemHeight: Dp, onDismissRequest: () -> Unit, - onShowRenameWalletDialogClick: () -> Unit, - onDeleteClick: () -> Unit, + dropDownItems: ImmutableList, ) { DropdownMenu( expanded = isMenuVisible, @@ -231,29 +224,23 @@ private fun ManageWalletContextMenu( modifier = Modifier.background(color = TangemTheme.colors.background.secondary), offset = pressOffset.copy(y = pressOffset.y - itemHeight), ) { - MenuItem( - textResId = R.string.common_rename, - imageVector = Icons.Outlined.Edit, - onClick = { - onDismissRequest() - onShowRenameWalletDialogClick() - }, - ) - MenuItem( - textResId = R.string.common_delete, - imageVector = Icons.Outlined.Delete, - onClick = { - onDismissRequest() - onDeleteClick() - }, - ) + dropDownItems.fastForEach { item -> + MenuItem( + text = item.text, + imageVector = item.icon, + onClick = { + onDismissRequest() + item.onClick() + }, + ) + } } } @Composable -private fun MenuItem(@StringRes textResId: Int, imageVector: ImageVector, onClick: () -> Unit) { +private fun MenuItem(text: TextReference, imageVector: ImageVector, onClick: () -> Unit) { DropdownMenuItem( - text = { Text(text = stringResourceSafe(id = textResId), style = TangemTheme.typography.subtitle2) }, + text = { Text(text = text.resolveReference(), style = TangemTheme.typography.subtitle2) }, modifier = Modifier.background(color = TangemTheme.colors.background.secondary), trailingIcon = { Icon(imageVector = imageVector, contentDescription = null) }, onClick = onClick, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt index cff354e8fa..1ddf2fdb9b 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt @@ -299,12 +299,6 @@ internal class WalletViewModel @Inject constructor( } private suspend fun initializeWallets(action: WalletsUpdateActionResolver.Action.InitializeWallets) { - walletScreenContentLoader.load( - userWallet = action.selectedWallet, - clickIntents = clickIntents, - coroutineScope = viewModelScope, - ) - stateHolder.update( transformer = InitializeWalletsTransformer( selectedWalletIndex = action.selectedWalletIndex, @@ -315,6 +309,12 @@ internal class WalletViewModel @Inject constructor( ), ) + walletScreenContentLoader.load( + userWallet = action.selectedWallet, + clickIntents = clickIntents, + coroutineScope = viewModelScope, + ) + if (action.wallets.size > 1 && isWalletsScrollPreviewEnabled()) { withContext(dispatchers.io) { delay(timeMillis = 1_800) } From 84570a8406cef0f2101f1fdd00d29e02d23c5cb8 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 19 Feb 2025 18:06:50 +0300 Subject: [PATCH 06/33] Updated on 2026-08-14 --- app/build.gradle.kts | 7 +- .../data/visa/utils/VisaCurrencyFactory.kt | 1 - .../tangem/domain/visa/model/VisaCurrency.kt | 1 - .../BalancesAndLimitsBottomSheetConfig.kt | 1 - .../BalancesAndLimitsBottomSheetConverter.kt | 1 - .../visa/BalancesAndLimitsBottomSheet.kt | 5 - gradle/dependencies.toml | 2 +- libs/visa/build.gradle.kts | 6 + .../main/java/com/tangem/lib/visa/ERC20.java | 183 +- .../lib/visa/TangemBridgeProcessor.java | 1807 +++++++------ .../tangem/lib/visa/TangemPaymentAccount.java | 2392 ++++++++++------- .../visa/TangemPaymentAccountRegistry.java | 506 ++-- .../visa/DefaultVisaContractInfoProvider.kt | 43 +- .../tangem/lib/visa/model/VisaContractInfo.kt | 1 - settings.gradle.kts | 11 + 15 files changed, 2860 insertions(+), 2107 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index f3177619a4..8fa9c93920 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -22,9 +22,14 @@ android { jniLibs { useLegacyPackaging = true } - resources.excludes.add("META-INF/DEPENDENCIES") resources.excludes.add("META-INF/LICENSE.md") resources.excludes.add("META-INF/NOTICE.md") + resources.excludes.add("META-INF/DISCLAIMER") + resources.excludes.add("META-INF/DEPENDENCIES") + resources.excludes.add("META-INF/FastDoubleParser-NOTICE") + resources.excludes.add("META-INF/FastDoubleParser-LICENSE") + resources.excludes.add("META-INF/io.netty.versions.properties") + resources.excludes.add("META-INF/INDEX.LIST") } androidResources { generateLocaleConfig = true diff --git a/data/visa/src/debug/kotlin/com/tangem/data/visa/utils/VisaCurrencyFactory.kt b/data/visa/src/debug/kotlin/com/tangem/data/visa/utils/VisaCurrencyFactory.kt index 6398dcec84..989a2d504c 100644 --- a/data/visa/src/debug/kotlin/com/tangem/data/visa/utils/VisaCurrencyFactory.kt +++ b/data/visa/src/debug/kotlin/com/tangem/data/visa/utils/VisaCurrencyFactory.kt @@ -32,7 +32,6 @@ internal class VisaCurrencyFactory { available = balances.available.forPayment, blocked = balances.blocked, debt = balances.debt, - pendingRefund = balances.pendingRefund, ) }, limits = VisaCurrency.Limits( diff --git a/domain/visa/src/main/kotlin/com/tangem/domain/visa/model/VisaCurrency.kt b/domain/visa/src/main/kotlin/com/tangem/domain/visa/model/VisaCurrency.kt index 1e6a0c55a1..b21df662c3 100644 --- a/domain/visa/src/main/kotlin/com/tangem/domain/visa/model/VisaCurrency.kt +++ b/domain/visa/src/main/kotlin/com/tangem/domain/visa/model/VisaCurrency.kt @@ -20,7 +20,6 @@ data class VisaCurrency( val available: BigDecimal, val blocked: BigDecimal, val debt: BigDecimal, - val pendingRefund: BigDecimal, ) data class Limits( diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/BalancesAndLimitsBottomSheetConfig.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/BalancesAndLimitsBottomSheetConfig.kt index 1dd961ab14..cedb03bee2 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/BalancesAndLimitsBottomSheetConfig.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/BalancesAndLimitsBottomSheetConfig.kt @@ -12,7 +12,6 @@ internal data class BalancesAndLimitsBottomSheetConfig( val availableBalance: String, val blockedBalance: String, val debit: String, - val pending: String, val amlVerified: String, val onInfoClick: () -> Unit, ) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/BalancesAndLimitsBottomSheetConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/BalancesAndLimitsBottomSheetConverter.kt index dc965b29e2..ffb4722637 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/BalancesAndLimitsBottomSheetConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/BalancesAndLimitsBottomSheetConverter.kt @@ -27,7 +27,6 @@ internal class BalancesAndLimitsBottomSheetConverter( availableBalance = value.balances.available.let(::formatAmount), blockedBalance = value.balances.blocked.let(::formatAmount), debit = value.balances.debt.let(::formatAmount), - pending = value.balances.pendingRefund.let(::formatAmount), amlVerified = value.balances.verified.let(::formatAmount), onInfoClick = this::showBalanceInfo, ), diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/visa/BalancesAndLimitsBottomSheet.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/visa/BalancesAndLimitsBottomSheet.kt index 97dd93b282..d9296dab81 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/visa/BalancesAndLimitsBottomSheet.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/visa/BalancesAndLimitsBottomSheet.kt @@ -78,10 +78,6 @@ private fun BalancesBlock(balances: BalancesAndLimitsBottomSheetConfig.Balance, title = stringReference("Debit"), value = balances.debit, ) - BlockItem( - title = stringReference("Pending refund"), - value = balances.pending, - ) }, description = { InfoButton(onClick = balances.onInfoClick) @@ -180,7 +176,6 @@ private class BalancesAndLimitsBottomSheetParameterProvider : availableBalance = "392.45 USDT", blockedBalance = "36.00 USDT", debit = "00.00 USDT", - pending = "20.99 USDT", amlVerified = "356.45 USDT", onInfoClick = {}, ), diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index 060b0ba823..7f200fada5 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -80,7 +80,7 @@ mlKit-barcodeScanning = "17.2.0" androidXCamera = "1.3.0" listenableFuture = "1.0" swipeRefreshLayout = "1.1.0" -web3j = "4.10.1" +web3j = "4.12.3-SNAPSHOT" leakcanary = "2.13" decompose = "2.2.2" room = "2.6.1" diff --git a/libs/visa/build.gradle.kts b/libs/visa/build.gradle.kts index eb6f922306..d73b1485ff 100644 --- a/libs/visa/build.gradle.kts +++ b/libs/visa/build.gradle.kts @@ -9,6 +9,12 @@ plugins { android { namespace = "com.tangem.libs.visa" + + packaging { + resources { + excludes += "/META-INF/*" + } + } } dependencies { diff --git a/libs/visa/src/main/java/com/tangem/lib/visa/ERC20.java b/libs/visa/src/main/java/com/tangem/lib/visa/ERC20.java index fb6048f082..5ea4655792 100644 --- a/libs/visa/src/main/java/com/tangem/lib/visa/ERC20.java +++ b/libs/visa/src/main/java/com/tangem/lib/visa/ERC20.java @@ -1,8 +1,18 @@ package com.tangem.lib.visa; +import io.reactivex.Flowable; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import org.web3j.abi.EventEncoder; import org.web3j.abi.TypeReference; -import org.web3j.abi.datatypes.*; +import org.web3j.abi.datatypes.Address; +import org.web3j.abi.datatypes.Event; +import org.web3j.abi.datatypes.Function; +import org.web3j.abi.datatypes.Type; +import org.web3j.abi.datatypes.Utf8String; import org.web3j.abi.datatypes.generated.Uint256; import org.web3j.abi.datatypes.generated.Uint8; import org.web3j.crypto.Credentials; @@ -17,25 +27,17 @@ import org.web3j.tx.Contract; import org.web3j.tx.TransactionManager; import org.web3j.tx.gas.ContractGasProvider; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import io.reactivex.Flowable; - /** *

Auto generated code. *

Do not modify! *

Please use the web3j command line tools, - * or the org.web3j.codegen.SolidityFunctionWrapperGenerator in the - * codegen module to update. + * or the org.web3j.codegen.SolidityFunctionWrapperGenerator in the + * codegen module to update. * - *

Generated with web3j version 1.5.2. + *

Generated with web3j version 1.6.1. */ @SuppressWarnings("rawtypes") -class ERC20 extends Contract { +public class ERC20 extends Contract { public static final String BINARY = "Bin file was not provided"; public static final String FUNC_ALLOWANCE = "allowance"; @@ -57,39 +59,40 @@ class ERC20 extends Contract { public static final String FUNC_TRANSFERFROM = "transferFrom"; public static final Event APPROVAL_EVENT = new Event("Approval", - Arrays.asList(new TypeReference

(true) { - }, new TypeReference
(true) { - }, new TypeReference() { - })); + Arrays.>asList(new TypeReference
(true) {}, new TypeReference
(true) {}, new TypeReference() {})); + ; public static final Event TRANSFER_EVENT = new Event("Transfer", - Arrays.asList(new TypeReference
(true) { - }, new TypeReference
(true) { - }, new TypeReference() { - })); + Arrays.>asList(new TypeReference
(true) {}, new TypeReference
(true) {}, new TypeReference() {})); + ; @Deprecated - protected ERC20(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + protected ERC20(String contractAddress, Web3j web3j, Credentials credentials, + BigInteger gasPrice, BigInteger gasLimit) { super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); } - protected ERC20(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { + protected ERC20(String contractAddress, Web3j web3j, Credentials credentials, + ContractGasProvider contractGasProvider) { super(BINARY, contractAddress, web3j, credentials, contractGasProvider); } @Deprecated - protected ERC20(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) { + protected ERC20(String contractAddress, Web3j web3j, TransactionManager transactionManager, + BigInteger gasPrice, BigInteger gasLimit) { super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); } - protected ERC20(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { + protected ERC20(String contractAddress, Web3j web3j, TransactionManager transactionManager, + ContractGasProvider contractGasProvider) { super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); } - public static List getApprovalEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(APPROVAL_EVENT, transactionReceipt); + public static List getApprovalEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(APPROVAL_EVENT, transactionReceipt); ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { + for (Contract.EventValuesWithLog eventValues : valueList) { ApprovalEventResponse typedResponse = new ApprovalEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.owner = (String) eventValues.getIndexedValues().get(0).getValue(); @@ -101,7 +104,7 @@ class ERC20 extends Contract { } public static ApprovalEventResponse getApprovalEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(APPROVAL_EVENT, log); + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(APPROVAL_EVENT, log); ApprovalEventResponse typedResponse = new ApprovalEventResponse(); typedResponse.log = log; typedResponse.owner = (String) eventValues.getIndexedValues().get(0).getValue(); @@ -110,20 +113,22 @@ class ERC20 extends Contract { return typedResponse; } - @Deprecated - public static ERC20 load(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { - return new ERC20(contractAddress, web3j, credentials, gasPrice, gasLimit); + public Flowable approvalEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getApprovalEventFromLog(log)); } - @Deprecated - public static ERC20 load(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) { - return new ERC20(contractAddress, web3j, transactionManager, gasPrice, gasLimit); + public Flowable approvalEventFlowable(DefaultBlockParameter startBlock, + DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(APPROVAL_EVENT)); + return approvalEventFlowable(filter); } - public static List getTransferEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(TRANSFER_EVENT, transactionReceipt); + public static List getTransferEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(TRANSFER_EVENT, transactionReceipt); ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { + for (Contract.EventValuesWithLog eventValues : valueList) { TransferEventResponse typedResponse = new TransferEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.from = (String) eventValues.getIndexedValues().get(0).getValue(); @@ -135,7 +140,7 @@ class ERC20 extends Contract { } public static TransferEventResponse getTransferEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(TRANSFER_EVENT, log); + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(TRANSFER_EVENT, log); TransferEventResponse typedResponse = new TransferEventResponse(); typedResponse.log = log; typedResponse.from = (String) eventValues.getIndexedValues().get(0).getValue(); @@ -148,107 +153,107 @@ class ERC20 extends Contract { return web3j.ethLogFlowable(filter).map(log -> getTransferEventFromLog(log)); } - public Flowable transferEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + public Flowable transferEventFlowable(DefaultBlockParameter startBlock, + DefaultBlockParameter endBlock) { EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); filter.addSingleTopic(EventEncoder.encode(TRANSFER_EVENT)); return transferEventFlowable(filter); } - public static ERC20 load(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { - return new ERC20(contractAddress, web3j, credentials, contractGasProvider); - } - - public static ERC20 load(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { - return new ERC20(contractAddress, web3j, transactionManager, contractGasProvider); - } - - public Flowable approvalEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getApprovalEventFromLog(log)); - } - - public Flowable approvalEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(APPROVAL_EVENT)); - return approvalEventFlowable(filter); - } - public RemoteFunctionCall allowance(String owner, String spender) { final Function function = new Function(FUNC_ALLOWANCE, - Arrays.asList(new Address(160, owner), - new Address(160, spender)), - List.of(new TypeReference() { - })); + Arrays.asList(new org.web3j.abi.datatypes.Address(160, owner), + new org.web3j.abi.datatypes.Address(160, spender)), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, BigInteger.class); } public RemoteFunctionCall approve(String spender, BigInteger value) { final Function function = new Function( FUNC_APPROVE, - Arrays.asList(new Address(160, spender), - new Uint256(value)), - Collections.emptyList()); + Arrays.asList(new org.web3j.abi.datatypes.Address(160, spender), + new org.web3j.abi.datatypes.generated.Uint256(value)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } public RemoteFunctionCall balanceOf(String account) { final Function function = new Function(FUNC_BALANCEOF, - List.of(new Address(160, account)), - List.of(new TypeReference() { - })); + Arrays.asList(new org.web3j.abi.datatypes.Address(160, account)), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, BigInteger.class); } public RemoteFunctionCall decimals() { final Function function = new Function(FUNC_DECIMALS, - List.of(), - List.of(new TypeReference() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, BigInteger.class); } public RemoteFunctionCall name() { final Function function = new Function(FUNC_NAME, - List.of(), - List.of(new TypeReference() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, String.class); } public RemoteFunctionCall symbol() { final Function function = new Function(FUNC_SYMBOL, - List.of(), - List.of(new TypeReference() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, String.class); } public RemoteFunctionCall totalSupply() { final Function function = new Function(FUNC_TOTALSUPPLY, - List.of(), - List.of(new TypeReference() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, BigInteger.class); } public RemoteFunctionCall transfer(String to, BigInteger value) { final Function function = new Function( FUNC_TRANSFER, - Arrays.asList(new Address(160, to), - new Uint256(value)), - Collections.emptyList()); + Arrays.asList(new org.web3j.abi.datatypes.Address(160, to), + new org.web3j.abi.datatypes.generated.Uint256(value)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } - public RemoteFunctionCall transferFrom(String from, String to, BigInteger value) { + public RemoteFunctionCall transferFrom(String from, String to, + BigInteger value) { final Function function = new Function( FUNC_TRANSFERFROM, - Arrays.asList(new Address(160, from), - new Address(160, to), - new Uint256(value)), - Collections.emptyList()); + Arrays.asList(new org.web3j.abi.datatypes.Address(160, from), + new org.web3j.abi.datatypes.Address(160, to), + new org.web3j.abi.datatypes.generated.Uint256(value)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } + @Deprecated + public static ERC20 load(String contractAddress, Web3j web3j, Credentials credentials, + BigInteger gasPrice, BigInteger gasLimit) { + return new ERC20(contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + @Deprecated + public static ERC20 load(String contractAddress, Web3j web3j, + TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) { + return new ERC20(contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + public static ERC20 load(String contractAddress, Web3j web3j, Credentials credentials, + ContractGasProvider contractGasProvider) { + return new ERC20(contractAddress, web3j, credentials, contractGasProvider); + } + + public static ERC20 load(String contractAddress, Web3j web3j, + TransactionManager transactionManager, ContractGasProvider contractGasProvider) { + return new ERC20(contractAddress, web3j, transactionManager, contractGasProvider); + } + public static class ApprovalEventResponse extends BaseEventResponse { public String owner; @@ -264,4 +269,4 @@ class ERC20 extends Contract { public BigInteger value; } -} +} \ No newline at end of file diff --git a/libs/visa/src/main/java/com/tangem/lib/visa/TangemBridgeProcessor.java b/libs/visa/src/main/java/com/tangem/lib/visa/TangemBridgeProcessor.java index b612de84bc..3352f39d85 100644 --- a/libs/visa/src/main/java/com/tangem/lib/visa/TangemBridgeProcessor.java +++ b/libs/visa/src/main/java/com/tangem/lib/visa/TangemBridgeProcessor.java @@ -1,11 +1,23 @@ package com.tangem.lib.visa; +import io.reactivex.Flowable; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import org.web3j.abi.EventEncoder; import org.web3j.abi.FunctionEncoder; import org.web3j.abi.TypeReference; -import org.web3j.abi.datatypes.*; +import org.web3j.abi.datatypes.Address; +import org.web3j.abi.datatypes.Bool; +import org.web3j.abi.datatypes.Event; +import org.web3j.abi.datatypes.Function; +import org.web3j.abi.datatypes.StaticStruct; +import org.web3j.abi.datatypes.Type; +import org.web3j.abi.datatypes.generated.Bytes16; import org.web3j.abi.datatypes.generated.Bytes32; -import org.web3j.abi.datatypes.generated.Bytes4; +import org.web3j.abi.datatypes.generated.Uint16; import org.web3j.abi.datatypes.generated.Uint256; import org.web3j.crypto.Credentials; import org.web3j.protocol.Web3j; @@ -20,40 +32,36 @@ import org.web3j.tx.Contract; import org.web3j.tx.TransactionManager; import org.web3j.tx.gas.ContractGasProvider; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import io.reactivex.Flowable; - /** *

Auto generated code. *

Do not modify! *

Please use the web3j command line tools, - * or the org.web3j.codegen.SolidityFunctionWrapperGenerator in the - * codegen module to update. + * or the org.web3j.codegen.SolidityFunctionWrapperGenerator in the + * codegen module to update. * - *

Generated with web3j version 1.5.2. + *

Generated with web3j version 1.6.1. */ @SuppressWarnings("rawtypes") -class TangemBridgeProcessor extends Contract { - public static final String BINARY = "608060405262278d006008553480156200001857600080fd5b506040516200272f3803806200272f8339810160408190526200003b9162000214565b60028054600580546001600160a01b03199081166001600160a01b038a8116919091179092556006805482168984161790556001600160a81b03199092166101008783160217909255600380549091169184169190911790556009819055620000a6600033620000b2565b5050505050506200027b565b600080620000c18484620000ef565b90508015620000e6576000848152600160205260409020620000e490846200019d565b505b90505b92915050565b6000828152602081815260408083206001600160a01b038516845290915281205460ff1662000194576000838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556200014b3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001620000e9565b506000620000e9565b6000620000e6836001600160a01b03841660008181526001830160205260408120546200019457508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620000e9565b80516001600160a01b03811681146200020f57600080fd5b919050565b600080600080600060a086880312156200022d57600080fd5b6200023886620001f7565b94506200024860208701620001f7565b93506200025860408701620001f7565b92506200026860608701620001f7565b9150608086015190509295509295909350565b6124a4806200028b6000396000f3fe608060405234801561001057600080fd5b506004361061028a5760003560e01c806383af133d1161015c578063c904ea39116100ce578063da90f3a011610087578063da90f3a0146105f1578063e24fd1f114610604578063e452f20d14610617578063e63ab1e91461062a578063e96ede8e14610651578063fe2208aa1461066457600080fd5b8063c904ea3914610589578063ca15c8731461059c578063cb37f3b2146105af578063d47ae89c146105c2578063d547741f146105cb578063d6d32b2a146105de57600080fd5b80639353ce4c116101205780639353ce4c146104f357806396bc563d1461051a578063978975591461052f578063a217fddf14610556578063b77c6d351461055e578063be4d18511461057657600080fd5b806383af133d146104a95780638456cb59146104bc5780639010d07c146104c457806391792d5b146104d757806391d14854146104e057600080fd5b80633f4ba83a11610200578063601c6065116101b9578063601c60651461042357806365ebf99a1461043657806370e4306e1461044957806373d3467c146104705780637f2fadb0146104835780638072a0221461049657600080fd5b80633f4ba83a146103ae5780634413e098146103b65780634b9bb0b4146103c95780634e6d8a73146103f057806356737951146104035780635c975abb1461041857600080fd5b80632f2ff15d116102525780632f2ff15d1461030e5780633013ce291461032157806336568abe1461034c57806337de81061461035f5780633d409a86146103725780633e1dbe1f1461038757600080fd5b806301ffc9a71461028f5780630f1071be146102b757806311dce771146102ce578063248a9ca3146102e35780632cc3264114610306575b600080fd5b6102a261029d366004611f47565b610677565b60405190151581526020015b60405180910390f35b6102c060085481565b6040519081526020016102ae565b6102e16102dc366004611f86565b6106a2565b005b6102c06102f1366004611fa3565b60009081526020819052604090206001015490565b6102e1610710565b6102e161031c366004611fbc565b61078a565b600354610334906001600160a01b031681565b6040516001600160a01b0390911681526020016102ae565b6102e161035a366004611fbc565b6107b5565b6102e161036d366004611fa3565b6107ed565b6102c060008051602061242683398151915281565b6102c07f80578ee961742bd59ed4d7f52c856d4014970acf79709a07f09c8c279d66cbb481565b6102e161084c565b6102e16103c4366004611fec565b610881565b6102c07fc62d23620f0c241b20cdec293f57ff9c0cc09ac7c55352efe3363184cd93032281565b6102e16103fe366004612018565b61094d565b6102c06000805160206123b183398151915281565b60025460ff166102a2565b6102e1610431366004612018565b610a57565b6102e1610444366004611f86565b610c7f565b6102c07f6ac2c8b5322a929d300af17766189693ff6db6939ffe690430ad4720baf47d1c81565b6102e161047e36600461205b565b610ce5565b6102e1610491366004611fec565b610e02565b6102e16104a4366004611fa3565b610ee5565b6102e16104b7366004611fec565b610f70565b6102e161102f565b6103346104d23660046120df565b611061565b6102c060075481565b6102a26104ee366004611fbc565b611080565b6102c07f79af5a85184b45263c1b3721b9c8eb1becd98e55ade5a61da0fed18b90b8325681565b6102c060008051602061230183398151915281565b6102c07f581be84b4822abe392a3bcac0d4d656e4cd57faf2e321a32108215cdd4a8365681565b6102c0600081565b6002546103349061010090046001600160a01b031681565b600654610334906001600160a01b031681565b6102e1610597366004612101565b6110a9565b6102c06105aa366004611fa3565b6111aa565b600554610334906001600160a01b031681565b6102c060095481565b6102e16105d9366004611fbc565b6111c1565b6102e16105ec366004611fa3565b6111e6565b6102e16105ff366004611fec565b611270565b6102e161061236600461214b565b6114ed565b610334610625366004611f86565b61162e565b6102c07f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b6102e161065f366004612018565b61168d565b6102e1610672366004612018565b611782565b60006001600160e01b03198216635a05180f60e01b148061069c575061069c8261185c565b92915050565b6000805160206123018339815191526106ba81611891565b600680546001600160a01b0319166001600160a01b0384169081179091556040519081527f68c7b435e0ad7bfb2140fab0735300efbda206f62906049e0b35763cef67cc5e906020015b60405180910390a15050565b600a54339061071e8261189b565b6000811160405180606001604052806029815260200161244660299139906107625760405162461bcd60e51b8152600401610759919061219d565b60405180910390fd5b506000600a55600654600354610786916001600160a01b0391821691168484611946565b5050565b6000828152602081905260409020600101546107a581611891565b6107af83836119a0565b50505050565b6001600160a01b03811633146107de5760405163334bd91960e11b815260040160405180910390fd5b6107e882826119d5565b505050565b7f80578ee961742bd59ed4d7f52c856d4014970acf79709a07f09c8c279d66cbb461081781611891565b60078290556040518281527fb5aa183eb20407e22587bcd13d5c82a85835a4bd60e2a13d7c7efee3c2e9ed4890602001610704565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a61087681611891565b61087e611a02565b50565b7f581be84b4822abe392a3bcac0d4d656e4cd57faf2e321a32108215cdd4a836566108ab81611891565b60405163b9603bdf60e01b8152600481018390526001600160a01b0384169063b9603bdf90602401600060405180830381600087803b1580156108ed57600080fd5b505af1158015610901573d6000803e3d6000fd5b50505050826001600160a01b03167fc8818db5b3e4e986e2f21e002090b1513e17c05a7a326c3737af624bf6ef78c48360405161094091815260200190565b60405180910390a2505050565b610955611a54565b7f6ac2c8b5322a929d300af17766189693ff6db6939ffe690430ad4720baf47d1c61097f81611891565b600061098a8561162e565b905060006007548461099c91906121e6565b604051630381b4dd60e01b815260048101879052602481018290529091506001600160a01b03831690630381b4dd90604401600060405180830381600087803b1580156109e857600080fd5b505af11580156109fc573d6000803e3d6000fd5b5050505084866001600160a01b03167fa77a4ae2cfa0139350d70cd52434d01ae72e9ec897ae89be03580f1ff00dd3d086600754604051610a47929190918252602082015260400190565b60405180910390a3505050505050565b610a5f611a54565b6000805160206123b1833981519152610a7781611891565b60408051808201909152601b81527f353130307c436f6d6d6f6e3a20616d6f756e74206973207a65726f0000000000602082015282610ac95760405162461bcd60e51b8152600401610759919061219d565b506000610ad58561162e565b6003546006546040516370a0823160e01b81526001600160a01b0391821660048201529293506000929116906370a0823190602401602060405180830381865afa158015610b27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b4b91906121f9565b9050838110156040518060400160405280601f81526020017f353130317c436f6d6d6f6e3a20696e73756666696369656e742066756e64730081525090610ba55760405162461bcd60e51b8152600401610759919061219d565b50600a84905560405163f89db45760e01b8152600481018690526001600160a01b0383169063f89db45790602401600060405180830381600087803b158015610bed57600080fd5b505af1158015610c01573d6000803e3d6000fd5b50505050600a546000146040518060600160405280602e81526020016123d1602e913990610c425760405162461bcd60e51b8152600401610759919061219d565b5084866001600160a01b03167fa5411d116afcb8415f0019792cccf595f94852ba82886dacbf756d9c3ce85f3f86604051610a4791815260200190565b600080516020612301833981519152610c9781611891565b600580546001600160a01b0319166001600160a01b0384169081179091556040519081527fccbdeb71dc680b2f0fd85f93e7ef0f70eda32a12b918c9715be07bb646360e5990602001610704565b610ced611a54565b600080516020612426833981519152610d0581611891565b6000610d108861162e565b9050600060075487610d2291906121e6565b6040516334284dfb60e01b8152600481018a9052602481018290526001600160801b03198816604482015261ffff8716606482015285151560848201529091506001600160a01b038316906334284dfb9060a401600060405180830381600087803b158015610d9057600080fd5b505af1158015610da4573d6000803e3d6000fd5b5050505087896001600160a01b03167f92c1dbadbb7b791052341ce7c185ca37861e432438355dc3e1642b7c1287609a89600754604051610def929190918252602082015260400190565b60405180910390a3505050505050505050565b610e0a611a54565b7f79af5a85184b45263c1b3721b9c8eb1becd98e55ade5a61da0fed18b90b83256610e3481611891565b6000610e3f8461162e565b604051636df6c7d560e11b8152600481018590529091506001600160a01b0382169063dbed8faa90602401600060405180830381600087803b158015610e8457600080fd5b505af1158015610e98573d6000803e3d6000fd5b50505050836001600160a01b03167f466723bb873015d5baf515fce6b0c8df2cb154adfd8badb6bc77a620a6ef676184604051610ed791815260200190565b60405180910390a250505050565b600080516020612301833981519152610efd81611891565b6283d60082106040518060600160405280602a81526020016122d7602a913990610f3a5760405162461bcd60e51b8152600401610759919061219d565b5060088290556040518281527fdc10143650bb79cd7a92cdf792545dcc2c3b0a719bebb3d83a8a21bb8fbfc3d690602001610704565b7f581be84b4822abe392a3bcac0d4d656e4cd57faf2e321a32108215cdd4a83656610f9a81611891565b6040516306b2a38360e41b8152600481018390526001600160a01b03841690636b2a383090602401600060405180830381600087803b158015610fdc57600080fd5b505af1158015610ff0573d6000803e3d6000fd5b50505050826001600160a01b03167fcc1685e553848099cad0e11271e780371c44b5ed92a54552fbedf9f1b6b9f2478360405161094091815260200190565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a61105981611891565b61087e611a7a565b60008281526001602052604081206110799083611ab7565b9392505050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b6110b1611a54565b6000805160206124268339815191526110c981611891565b60006110d48661162e565b90506000600754856110e691906121e6565b6040516320199e7960e21b8152600481018890526024810182905285151560448201529091506001600160a01b0383169063806679e490606401600060405180830381600087803b15801561113a57600080fd5b505af115801561114e573d6000803e3d6000fd5b5050505085876001600160a01b03167f92c1dbadbb7b791052341ce7c185ca37861e432438355dc3e1642b7c1287609a87600754604051611199929190918252602082015260400190565b60405180910390a350505050505050565b600081815260016020526040812061069c90611ac3565b6000828152602081905260409020600101546111dc81611891565b6107af83836119d5565b6000805160206123018339815191526111fe81611891565b610e1082106040518060600160405280602781526020016123ff602791399061123a5760405162461bcd60e51b8152600401610759919061219d565b5060098290556040518281527f7f63f876249f25f7856e620802edd09af38a83c9c6040fcdb37179154030831190602001610704565b611278611a54565b6000805160206123b183398151915261129081611891565b600061129b8461162e565b604051631902cad960e31b8152600481018590529091506000906001600160a01b0383169063c81656c890602401602060405180830381865afa1580156112e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130a91906121f9565b6003546006546040516370a0823160e01b81526001600160a01b0391821660048201529293506000929116906370a0823190602401602060405180830381865afa15801561135c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138091906121f9565b90506000821160405180606001604052806027815260200161238a60279139906113bd5760405162461bcd60e51b8152600401610759919061219d565b5060408051808201909152601f81527f353130317c436f6d6d6f6e3a20696e73756666696369656e742066756e6473006020820152828210156114135760405162461bcd60e51b8152600401610759919061219d565b50600a82905560405163e3dbffd560e01b8152600481018690526001600160a01b0384169063e3dbffd590602401600060405180830381600087803b15801561145b57600080fd5b505af115801561146f573d6000803e3d6000fd5b50505050600a546000146040518060600160405280602e81526020016123d1602e9139906114b05760405162461bcd60e51b8152600401610759919061219d565b5084866001600160a01b03167fdfab01fc691e8b69fca482c65142d1bcfeafeb9eb6e9fd5220867d7196d9476e84604051610a4791815260200190565b7fc62d23620f0c241b20cdec293f57ff9c0cc09ac7c55352efe3363184cd93032261151781611891565b6115208261189b565b306001600160a01b0316826001600160a01b031663ce1b1d436040518163ffffffff1660e01b8152600401602060405180830381865afa158015611568573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061158c9190612212565b6001600160a01b03161460405180606001604052806032815260200161235860329139906115cd5760405162461bcd60e51b8152600401610759919061219d565b506001600160a01b0383811660008181526004602090815260409182902080546001600160a01b0319169487169485179055905192835290917f0c1464e8c817204497a2076f3b466fe64093e83033c83303b0cb44001cd9b6b59101610940565b6001600160a01b03808216600090815260046020908152604080832054815160608101909252602f80835293941692831515926122a890830139906116865760405162461bcd60e51b8152600401610759919061219d565b5092915050565b611695611a54565b6000805160206124268339815191526116ad81611891565b60006116b88561162e565b9050600083156116ca576007546116cd565b60005b905060006116db82866121e6565b60405163e4d7ddb960e01b815260048101889052602481018290529091506001600160a01b0384169063e4d7ddb990604401600060405180830381600087803b15801561172757600080fd5b505af115801561173b573d6000803e3d6000fd5b505060408051888152602081018690528993506001600160a01b038b1692507f8ba3ad1bd4ff5c3d75861d56df66b7942244d700f4d4cb67df693bac78e805a29101611199565b61178a611a54565b6000805160206123b18339815191526117a281611891565b60006117ad8561162e565b60405163456575e560e01b815260048101869052602481018590529091506001600160a01b0382169063456575e590604401600060405180830381600087803b1580156117f957600080fd5b505af115801561180d573d6000803e3d6000fd5b5050505083856001600160a01b03167f6f60b80b8dcecc3741c03485554a9a35ced96ebba66405fd324caf12a16261da8560405161184d91815260200190565b60405180910390a35050505050565b60006001600160e01b03198216637965db0b60e01b148061069c57506301ffc9a760e01b6001600160e01b031983161461069c565b61087e8133611acd565b6002546040516385bb392360e01b81526001600160a01b038381166004830152610100909204909116906385bb392390602401602060405180830381865afa1580156118eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061190f919061222f565b60405180606001604052806037815260200161232160379139906107865760405162461bcd60e51b8152600401610759919061219d565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526107af908590611b06565b6000806119ad8484611b69565b905080156110795760008481526001602052604090206119cd9084611bfb565b509392505050565b6000806119e28484611c10565b905080156110795760008481526001602052604090206119cd9084611c7b565b611a0a611c90565b6002805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60025460ff1615611a785760405163d93c066560e01b815260040160405180910390fd5b565b611a82611a54565b6002805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611a373390565b60006110798383611cb3565b600061069c825490565b611ad78282611080565b6107865760405163e2517d3f60e01b81526001600160a01b038216600482015260248101839052604401610759565b6000611b1b6001600160a01b03841683611cdd565b90508051600014158015611b40575080806020019051810190611b3e919061222f565b155b156107e857604051635274afe760e01b81526001600160a01b0384166004820152602401610759565b6000611b758383611080565b611bf3576000838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055611bab3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161069c565b50600061069c565b6000611079836001600160a01b038416611ceb565b6000611c1c8383611080565b15611bf3576000838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a450600161069c565b6000611079836001600160a01b038416611d32565b60025460ff16611a7857604051638dfc202b60e01b815260040160405180910390fd5b6000826000018281548110611cca57611cca61224c565b9060005260206000200154905092915050565b606061107983836000611e25565b6000818152600183016020526040812054611bf35750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561069c565b60008181526001830160205260408120548015611e1b576000611d56600183612262565b8554909150600090611d6a90600190612262565b9050808214611dcf576000866000018281548110611d8a57611d8a61224c565b9060005260206000200154905080876000018481548110611dad57611dad61224c565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611de057611de0612275565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061069c565b600091505061069c565b606081471015611e4a5760405163cd78605960e01b8152306004820152602401610759565b600080856001600160a01b03168486604051611e66919061228b565b60006040518083038185875af1925050503d8060008114611ea3576040519150601f19603f3d011682016040523d82523d6000602084013e611ea8565b606091505b5091509150611eb8868383611ec2565b9695505050505050565b606082611ed757611ed282611f1e565b611079565b8151158015611eee57506001600160a01b0384163b155b15611f1757604051639996b31560e01b81526001600160a01b0385166004820152602401610759565b5080611079565b805115611f2e5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b600060208284031215611f5957600080fd5b81356001600160e01b03198116811461107957600080fd5b6001600160a01b038116811461087e57600080fd5b600060208284031215611f9857600080fd5b813561107981611f71565b600060208284031215611fb557600080fd5b5035919050565b60008060408385031215611fcf57600080fd5b823591506020830135611fe181611f71565b809150509250929050565b60008060408385031215611fff57600080fd5b823561200a81611f71565b946020939093013593505050565b60008060006060848603121561202d57600080fd5b833561203881611f71565b95602085013595506040909401359392505050565b801515811461087e57600080fd5b60008060008060008060c0878903121561207457600080fd5b863561207f81611f71565b9550602087013594506040870135935060608701356001600160801b0319811681146120aa57600080fd5b9250608087013561ffff811681146120c157600080fd5b915060a08701356120d18161204d565b809150509295509295509295565b600080604083850312156120f257600080fd5b50508035926020909101359150565b6000806000806080858703121561211757600080fd5b843561212281611f71565b9350602085013592506040850135915060608501356121408161204d565b939692955090935050565b6000806040838503121561215e57600080fd5b823561216981611f71565b91506020830135611fe181611f71565b60005b8381101561219457818101518382015260200161217c565b50506000910152565b60208152600082518060208401526121bc816040850160208701612179565b601f01601f19169190910160400192915050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561069c5761069c6121d0565b60006020828403121561220b57600080fd5b5051919050565b60006020828403121561222457600080fd5b815161107981611f71565b60006020828403121561224157600080fd5b81516110798161204d565b634e487b7160e01b600052603260045260246000fd5b8181038181111561069c5761069c6121d0565b634e487b7160e01b600052603160045260246000fd5b6000825161229d818460208701612179565b919091019291505056fe353230327c50726f636573736f723a206e6f207061796d656e74206163636f756e7420666f72207468652063617264353231307c50726f636573736f723a20736574746c656d656e7420706572696f6420746f6f206c6f6e67fa658e47c75a6eb0e27156b2f72e1b295c98b53e8a1d238d7ca6ea6345b34880353230307c50726f636573736f723a207061796d656e74206163636f756e74206e6f74206465706c6f79656420627920666163746f7279353230317c50726f636573736f723a207061796d656e74206163636f756e742070726f636573736f72206d69736d61746368353235307c50726f636573736f723a20726566756e64207265636f7264206e6f7420666f756e64d77cc12a543481a2b3ef8fd055979569715a10db9879cd9e664395eca3a54dff353235327c50726f636573736f723a20726566756e6420746f2070726f63657373207761736e2774207265736574353231317c50726f636573736f723a2073656375726974792064656c617920746f6f206c6f6e67a567244cad934c87b7f7e15b15dd0e75f95a76afd1916f8eab4a391410d6f278353235317c50726f636573736f723a20726566756e6420746f2070726f63657373206973207a65726fa2646970667358221220098c0e97a9ad9d3bb5cd4459c44925a6fb83295823a48d337beb3c254c7b728b64736f6c63430008160033"; +public class TangemBridgeProcessor extends Contract { + public static final String BINARY = "608060405234620000345762000022620000186200012e565b939290926200022c565b604051612dc86200057b8239612dc890f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b90601f01601f191681019081106001600160401b038211176200007157604052565b62000039565b906200008e6200008660405190565b92836200004f565b565b6001600160a01b031690565b90565b6001600160a01b0381165b036200003457565b905051906200008e826200009f565b80620000aa565b905051906200008e82620000c1565b919060a0838203126200003457620000f08184620000b2565b92620001008260208301620000b2565b926200009c620001148460408501620000b2565b936080620001268260608701620000b2565b9401620000c8565b620001516200334380380380620001458162000077565b928339810190620000d7565b9091929394565b906001600160a01b03905b9181191691161790565b6200009c9062000090906001600160a01b031682565b6200009c906200016d565b6200009c9062000183565b90620001ad6200009c620001b5926200018e565b825462000158565b9055565b90610100600160a81b039060081b62000163565b90620001e16200009c620001b5926200018e565b8254620001b9565b906000199062000163565b6200009c6200009c6200009c9290565b90620002186200009c620001b592620001f4565b8254620001e9565b6200009c6000620001f4565b92620002676200026d6200027d946200026762000275956200025f620002859a9962000257620002c3565b600462000199565b600562000199565b6200018e565b6002620001cd565b600362000199565b600662000204565b6200029b6200029362000220565b3390620002e1565b50565b9060ff9062000163565b90620002bb6200009c620001b592151590565b82546200029e565b6200008e60006002620002a8565b905b600052602052604060002090565b620002ed828262000324565b9182620002f957505090565b6200030e6200009c62000314936001620002d1565b620003d2565b5090565b90620002d3906200018e565b6200033862000334838362000419565b1590565b15620003b8576200036460016200035e846000620003578682620002d1565b0162000318565b620002a8565b620003836200037c62000375339390565b936200018e565b916200018e565b917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d620003af60405190565b600090a4600190565b5050600090565b6200009c9081906001600160a01b031681565b906200040c6200040862000402620003fc60006200009c96620003f3600090565b50019462000183565b620003bf565b620001f4565b9190565b620004e4565b5460ff1690565b6200009c916000620003576200043a9362000432600090565b5082620002d1565b62000412565b634e487b7160e01b600052603260045260246000fd5b80548210156200047b5762000472600191600052602060002090565b91020190600090565b62000440565b9160001960089290920291821b911b62000163565b9190620004a86200009c620001b59390565b90835462000481565b9081549168010000000000000000831015620000715782620004dd9160016200008e9501815562000456565b9062000496565b620004f462000334838362000542565b15620003b8576200052991620005239060016200051b84620005178482620004b1565b5490565b9301620002d1565b62000204565b600190565b6200009c9081565b6200009c90546200052e565b620005659160016200055f9262000557600090565b5001620002d1565b62000536565b62000575620004086000620001f4565b14159056fe6080604052600436101561001257600080fd5b60003560e01c806301ffc9a71461030257806311dce771146102fd578063248a9ca3146102f857806328e14f24146102f35780632cc32641146102ee5780632e44b939146102e95780632f2ff15d146102e45780633013ce29146102df57806336568abe146102da5780633c1a5012146102d55780633d409a86146102d05780633f4ba83a146102cb57806341d2ac20146102c65780634413e098146102c157806356737951146102bc5780635c975abb146102b757806365ebf99a146102b257806368b40573146102ad5780636a7554c0146102a857806370e4306e146102a35780637123925e1461029e57806383af133d146102995780638456cb59146102945780639010d07c1461028f57806391d148541461028a5780639353ce4c1461028557806396bc563d14610280578063978975591461027b57806399fef6bb146102765780639e4da86214610271578063a217fddf1461026c578063a9eb7b5a14610267578063aca821f714610262578063b77c6d351461025d578063be4d185114610258578063c0e678f814610253578063c8de6d171461024e578063ca15c87314610249578063cb37f3b214610244578063d47ae89c1461023f578063d547741f1461023a578063d595130814610235578063d6d32b2a14610230578063e0a86ef71461022b578063e63ab1e914610226578063eb465bca146102215763f0cb94980361031a57610d95565b610d76565b610cce565b610caf565b610c04565b610be8565b610bcf565b610bb4565b610b77565b610b50565b610b37565b610b1b565b610a9f565b610a78565b610a50565b610a37565b610a1c565b6109c4565b6109a9565b610970565b610949565b610910565b6108f4565b6108be565b61088a565b610871565b610838565b6107ff565b6107e6565b6107ca565b61077d565b61075e565b610725565b61070c565b6106d7565b61068f565b610668565b610650565b610637565b610610565b61058d565b610548565b61046a565b610431565b6103fa565b6103b6565b610349565b6001600160e01b031981165b0361031a57565b600080fd5b9050359061032c82610307565b565b9060208282031261031a576103429161031f565b90565b9052565b3461031a5761037661036461035f36600461032e565b610dce565b60405191829182901515815260200190565b0390f35b6001600160a01b031690565b6001600160a01b038116610313565b9050359061032c82610386565b9060208282031261031a5761034291610395565b3461031a576103ce6103c93660046103a2565b610e81565b604051005b80610313565b9050359061032c826103d3565b9060208282031261031a57610342916103d9565b3461031a576103766104156104103660046103e6565b610eab565b6040515b9182918290815260200190565b600091031261031a57565b3461031a57610441366004610426565b6103767f350e76a198c654a14c1f5ccac917c5f939f08970b53375e57483f9623a24399c610415565b3461031a5761047a366004610426565b6103ce611072565b908160e091031261031a5790565b909182601f8301121561031a5781359167ffffffffffffffff831161031a57602001926001830284011161031a57565b6101808183031261031a576104d58282610395565b926104e38360208401610395565b926104f18160408501610482565b926105008261012083016103d9565b9261014082013567ffffffffffffffff811161031a5783610522918401610490565b92909361016082013567ffffffffffffffff811161031a576105449201610490565b9091565b3461031a576103ce61055b3660046104c0565b969590959491949392936113fd565b919060408382031261031a5761034290602061058682866103d9565b9401610395565b3461031a576103ce6105a036600461056a565b9061142b565b610342916008021c6001600160a01b031690565b9061034291546105a6565b610342600060036105ba565b6103429061037a906001600160a01b031682565b610342906105d1565b610342906105e5565b610345906105ee565b60208101929161032c91906105f7565b3461031a57610620366004610426565b61037661062b6105c5565b60405191829182610600565b3461031a576103ce61064a36600461056a565b90611435565b3461031a576103ce6106633660046103a2565b611530565b3461031a57610678366004610426565b610376600080516020612d73833981519152610415565b3461031a5761069f366004610426565b6103ce61156d565b909160608284031261031a576103426106c08484610395565b9360406106d08260208701610395565b94016103d9565b3461031a576103ce6106ea3660046106a7565b916116eb565b919060408382031261031a576103429060206106d08286610395565b3461031a576103ce61071f3660046106f0565b906117a3565b3461031a57610735366004610426565b6103767fd77cc12a543481a2b3ef8fd055979569715a10db9879cd9e664395eca3a54dff610415565b3461031a5761076e366004610426565b61037661036460025460ff1690565b3461031a576103ce6107903660046103a2565b6117f8565b60808183031261031a576107a98282610395565b926103426107ba8460208501610395565b9360606106d082604087016103d9565b3461031a576103ce6107dd366004610795565b92919091611a60565b3461031a576103ce6107f93660046106f0565b90611b0f565b3461031a5761080f366004610426565b6103767f6ac2c8b5322a929d300af17766189693ff6db6939ffe690430ad4720baf47d1c610415565b3461031a57610848366004610426565b6103767fca900a2e3cfbbbb78b9095304e53ddb6de902bbef4638bd3c79fe9cf3a441202610415565b3461031a576103ce6108843660046106f0565b90611bbc565b3461031a5761089a366004610426565b6103ce611bfa565b919060408382031261031a576103429060206106d082866103d9565b3461031a576103766108da6108d43660046108a2565b90611c02565b604051918291826001600160a01b03909116815260200190565b3461031a5761037661036461090a36600461056a565b90611c2c565b3461031a57610920366004610426565b6103767f79af5a85184b45263c1b3721b9c8eb1becd98e55ade5a61da0fed18b90b83256610415565b3461031a57610959366004610426565b610376600080516020612d53833981519152610415565b3461031a57610980366004610426565b6103767f581be84b4822abe392a3bcac0d4d656e4cd57faf2e321a32108215cdd4a83656610415565b3461031a576103766103646109bf3660046103a2565b611c55565b3461031a576109d4366004610426565b6103767f863747851594ece3a3681369cf3710069c605efc30fccffb517283afa5efce91610415565b6103426103426103429290565b61034260006109fd565b610342610a0a565b3461031a57610a2c366004610426565b610376610415610a14565b3461031a576103ce610a4a3660046106a7565b91611d3b565b3461031a576103ce610a63366004610795565b92919091611e22565b610342600160026105ba565b3461031a57610a88366004610426565b61037661062b610a6c565b610342600060056105ba565b3461031a57610aaf366004610426565b6103766108da610a93565b801515610313565b9050359061032c82610aba565b919060a08382031261031a57610ae58184610395565b92610af38260208301610395565b92610342610b0484604085016103d9565b936080610b1482606087016103d9565b9401610ac2565b3461031a576103ce610b2e366004610acf565b93929092611f2f565b3461031a576103ce610b4a3660046106a7565b91611ff3565b3461031a57610376610415610b663660046103e6565b611ffe565b610342600060046105ba565b3461031a57610b87366004610426565b6103766108da610b6b565b610342916008021c81565b906103429154610b92565b61034260006006610b9d565b3461031a57610bc4366004610426565b610376610415610ba8565b3461031a576103ce610be236600461056a565b90612030565b3461031a576103ce610bfb366004610795565b929190916120fc565b3461031a576103ce610c173660046103e6565b6121ce565b6001600160801b03198116610313565b9050359061032c82610c1c565b61ffff8116610313565b9050359061032c82610c39565b60e08183031261031a57610c648282610395565b92610c728360208401610395565b92610c8081604085016103d9565b92610c8e82606083016103d9565b92610342610c9f8460808501610c2c565b9360c0610b148260a08701610c43565b3461031a576103ce610cc2366004610c50565b959490949391936122b4565b3461031a57610cde366004610426565b6103767f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a610415565b9060c08282031261031a57610d1c8183610395565b92610d2a8260208501610395565b92610d3883604083016103d9565b92610d4681606084016103d9565b92608083013567ffffffffffffffff811161031a5782610d6d60a094610342938701610490565b94909501610ac2565b3461031a576103ce610d89366004610d07565b95949094939193612397565b3461031a57610da5366004610426565b6103767f7245419aa9f77e6e9f023dc59852153b8258661dd13b3e1a61fe9e8a5977aa74610415565b635a05180f60e01b6001600160e01b0319821614908115610ded575090565b61034291506123a6565b61032c90610e17600080516020612d538339815191526123e0565b6123e0565b610e4c565b906001600160a01b03905b9181191691161790565b90610e41610342610e48926105ee565b8254610e1c565b9055565b610e7c7f68c7b435e0ad7bfb2140fab0735300efbda206f62906049e0b35763cef67cc5e916108da816005610e31565b0390a1565b61032c90610df7565b905b600052602052604060002090565b6103429081565b6103429054610e9a565b6001610ec461034292610ebc600090565b506000610e8a565b01610ea1565b634e487b7160e01b600052604160045260246000fd5b90601f01601f1916810190811067ffffffffffffffff821117610f0257604052565b610eca565b9061032c610f1460405190565b9283610ee0565b67ffffffffffffffff8111610f0257602090601f01601f19160190565b0190565b90610f4e610f4983610f1b565b610f07565b918252565b610f5d6029610f3c565b7f353235317c50726f636573736f723a20726566756e6420746f2070726f63657360208201526873206973207a65726f60b81b604082015290565b610342610f53565b610342610f98565b60005b838110610fbb5750506000910152565b8181015183820152602001610fab565b610fec610ff5602093610f3893610fe0815190565b80835293849260200190565b95869101610fa8565b601f01601f191690565b602080825261034292910190610fcb565b156110185750565b61103a9061102560405190565b62461bcd60e51b815291829160048301610fff565b0390fd5b9060001990610e27565b90611058610342610e48926109fd565b825461103e565b6103429061037a565b610342905461105f565b61032c336110806007610ea1565b9061108a81612475565b6110a761109760006109fd565b83116110a1610fa0565b90611010565b6110bb6110b460006109fd565b6007611048565b6110c56003611068565b6110cf6005611068565b90612537565b9061032c979695949392916110e8612581565b61032c979695949392919061111c7f863747851594ece3a3681369cf3710069c605efc30fccffb517283afa5efce916123e0565b61130e565b6103429060081c61037a565b6103429054611121565b9050519061032c82610386565b9060208282031261031a5761034291611137565b50610342906020810190610ac2565b50610342906020810190610c2c565b50610342906020810190610c43565b9060206111b661032c936111ad61119f6000830183611167565b6001600160801b0319168552565b82810190611176565b61ffff16910152565b506103429060208101906103d9565b90606061122361032c936111ec6111e860008301836111bf565b8552565b6112036111fc60208301836111bf565b6020860152565b61121a61121360408301836111bf565b6040860152565b828101906111bf565b910152565b90606061125e61032c936112486112426000830183611158565b15158552565b611259602082016020860190611185565b820190565b9101906111ce565b90826000939282370152565b9190610ff58161128981610f389560209181520190565b8095611266565b9694906112f3946112dd89956112d36103429c9a966112c36112e59660006101808c019b01906001600160a01b03169052565b6001600160a01b031660208d0152565b60408b0190611228565b610120890152565b868303610140880152611272565b92610160818503910152611272565b6040513d6000823e3d90fd5b9485611354839960209795969960009461133061132b600261112d565b6105ee565b9761133a60405190565b9c8d9a8b998a98632e44b93960e01b8a5260048a01611290565b03925af19081156113f8577f49f84c15b9f052fd24e68e7760c0bc11d05c5a058721d4dfc2c5c02866f84cd6926000926113c3575b50611393906105ee565b926113be6113a060405190565b928392836001600160a01b0391821681529116602082015260400190565b0390a2565b6113939192506113ea9060203d6020116113f1575b6113e28183610ee0565b810190611144565b9190611389565b503d6113d8565b611302565b9061032c979695949392916110d5565b9061032c9161141e610e1282610eab565b906114289161259f565b50565b9061032c9161140d565b9061143f3361037a565b6001600160a01b0382160361145757611428916125ce565b60405163334bd91960e11b8152600490fd5b61032c906114967fca900a2e3cfbbbb78b9095304e53ddb6de902bbef4638bd3c79fe9cf3a4412026123e0565b6114a261132b826105ee565b90813b1561031a5760006114b560405190565b6337a1d41560e01b8152928390600490829084905af19182156113f8576114e192611512575b506105ee565b7feb17a79f3df37ac5b011bba24abb3d48db9d0dd39110551346f1c30bfa0fe70161150b60405190565b80806113be565b61152a9060006115228183610ee0565b810190610426565b386114db565b61032c90611469565b6115627f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a6123e0565b61032c61032c61265f565b61032c611539565b9061032c9291611583612581565b61032c9291906115b27f79af5a85184b45263c1b3721b9c8eb1becd98e55ade5a61da0fed18b90b832566123e0565b6115f9565b9050519061032c826103d3565b9060208282031261031a57610342916115b7565b6001600160a01b03909116815260408101929161032c9160200152565b0152565b602061163360009461160d61132b856105ee565b9061161760405190565b968793849283919063f93184c160e01b835289600484016115d8565b03925af19283156113f85760009361168c575b5061168761167d6116777f8c7f40acbbdddd09014432da06798dda241de8adb409a62f3611f9a0d63d6b5b936105ee565b936105ee565b9361041960405190565b0390a3565b7f8c7f40acbbdddd09014432da06798dda241de8adb409a62f3611f9a0d63d6b5b91935061167d6116776116da6116879360203d6020116116e4575b6116d28183610ee0565b8101906115c4565b9593505050611646565b503d6116c8565b9061032c9291611575565b61032c91906117247f581be84b4822abe392a3bcac0d4d656e4cd57faf2e321a32108215cdd4a836566123e0565b61173061132b826105ee565b803b1561031a57600061174260405190565b63b9603bdf60e01b815260048101859052918290602490829084905af180156113f8577fc8818db5b3e4e986e2f21e002090b1513e17c05a7a326c3737af624bf6ef78c4926113be926117999261151257506105ee565b9261041960405190565b9061032c916116f6565b61032c906117c8600080516020612d538339815191526123e0565b610e7c7fccbdeb71dc680b2f0fd85f93e7ef0f70eda32a12b918c9715be07bb646360e59916108da816004610e31565b61032c906117ad565b9061032c939291611810612581565b61032c939291906118407fd77cc12a543481a2b3ef8fd055979569715a10db9879cd9e664395eca3a54dff6123e0565b6118e2565b61184f601f610f3c565b7f353130317c436f6d6d6f6e3a20696e73756666696369656e742066756e647300602082015290565b610342611845565b610342611878565b611892602e610f3c565b7f353235327c50726f636573736f723a20726566756e6420746f2070726f63657360208201526d1cc81dd85cdb89dd081c995cd95d60921b604082015290565b610342611888565b6103426118d2565b6118eb846126aa565b61193860206118fd61132b6003611068565b6119076005611068565b9061191160405190565b938492839182916370a0823160e01b5b83526001600160a01b031660048301526024820190565b03915afa80156113f85761196491600091611a41575b50859061195a565b9190565b10156110a1611880565b61196f846007611048565b61197b61132b826105ee565b90813b1561031a57600061198e60405190565b92839063bc77d49560e01b82528183816119ac8a8a600484016115d8565b03925af19081156113f857611a16611a10611a1c927f6de2d5fa0b9cac9e48f300a350314e447648d158a5067a56513a46396f1b638a95611a2695611a2b575b5061132b6119fa6007610ea1565b611a0761195660006109fd565b146110a16118da565b946105ee565b946109fd565b9461041960405190565b0390a4565b611a3b9060006115228183610ee0565b386119ec565b611a5a915060203d6020116116e4576116d28183610ee0565b3861194e565b9061032c939291611801565b61032c9190611a9a7f7245419aa9f77e6e9f023dc59852153b8258661dd13b3e1a61fe9e8a5977aa746123e0565b611aa661132b826105ee565b803b1561031a576000611ab860405190565b6377627c0960e11b815260048101859052918290602490829084905af180156113f8577faeb30c8dda75512b9946228f4034031bd3f99d91f2c4ed3806be677f3429cd80926113be926117999261151257506105ee565b9061032c91611a6c565b61032c9190611b477f581be84b4822abe392a3bcac0d4d656e4cd57faf2e321a32108215cdd4a836566123e0565b611b5361132b826105ee565b803b1561031a576000611b6560405190565b6306b2a38360e41b815260048101859052918290602490829084905af180156113f8577fcc1685e553848099cad0e11271e780371c44b5ed92a54552fbedf9f1b6b9f247926113be926117999261151257506105ee565b9061032c91611b19565b611bef7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a6123e0565b61032c61032c612705565b61032c611bc6565b90611c1d61034261034293611c15600090565b506001610e8a565b612723565b90610e8c906105ee565b610342916000611c48611c4e93611c41600090565b5082610e8a565b01611c22565b5460ff1690565b610342907f350e76a198c654a14c1f5ccac917c5f939f08970b53375e57483f9623a24399c611c2c565b9061032c9291611c8d612581565b61032c929190611cbc7f6ac2c8b5322a929d300af17766189693ff6db6939ffe690430ad4720baf47d1c6123e0565b611cc861132b826105ee565b90813b1561031a576000611cdb60405190565b928390633e0fc2ff60e01b8252818381611cf98a8a600484016115d8565b03925af19182156113f8576116776116879261167d927f7ea7d3b21868f19f237e4e91d95cc953f5a73d5b2c1862712635f3ef384887fd9561151257506105ee565b9061032c9291611c7f565b9061032c939291611d55612581565b61032c93929190611d73600080516020612d738339815191526123e0565b611d9f565b6001600160a01b03909116815260608101939261032c9290916040916115f5906020830152565b611dab61132b826105ee565b90813b1561031a576000611dbe60405190565b9283906374b76f4760e11b8252818381611ddd8b8b8b60048501611d78565b03925af19081156113f857611a16611a10611a1c927f0ee23c67813e7ee061931ccc27dd2be79deb9f90738c9649947a27243cd6d81f95611a269561151257506105ee565b9061032c939291611d46565b9061032c94939291611e3e612581565b61032c9493929190611e5d600080516020612d738339815191526123e0565b611ea2565b611e9a61032c94611e93606094989795611e8c608086019a60008701906001600160a01b03169052565b6020850152565b6040830152565b019015159052565b9390919293611eb361132b826105ee565b803b1561031a57611eea600093918492611ecc60405190565b95869384928391906303ad5cef60e31b83528c8c8c60048601611e62565b03925af19081156113f857611a16611a10611a1c927f3cd37480027e3583365f7acfb552d017416b316c9bec58d3c722169ebcfbed8d95611a269561151257506105ee565b9061032c94939291611e2e565b9061032c9291611f4a612581565b61032c929190611f797f79af5a85184b45263c1b3721b9c8eb1becd98e55ade5a61da0fed18b90b832566123e0565b611f8561132b826105ee565b90813b1561031a576000611f9860405190565b636df6c7d560e11b815260048101869052928390602490829084905af19182156113f8576116776116879261167d927f4ec4ca1f307e20478f96cb1c545fe5430572a8db4931456f3828b649f641b1ef9561151257506105ee565b9061032c9291611f3c565b61201061034261034292611c15600090565b612757565b9061032c91612026610e1282610eab565b90611428916125ce565b9061032c91612015565b9061032c939291612049612581565b61032c939291906120797f6ac2c8b5322a929d300af17766189693ff6db6939ffe690430ad4720baf47d1c6123e0565b61208561132b826105ee565b90813b1561031a57600061209860405190565b928390634e6d8a7360e01b82528183816120b78b8b8b60048501611d78565b03925af19081156113f857611a16611a10611a1c927f1dd3b030dd7573079a398f70654588c91f23b82a2434fc5351cef1cbeda903e195611a269561151257506105ee565b9061032c93929161203a565b61032c90612123600080516020612d538339815191526123e0565b612186565b610342610e106109fd565b61213d6027610f3c565b7f353231317c50726f636573736f723a2073656375726974792064656c617920746020820152666f6f206c6f6e6760c81b604082015290565b610342612133565b610342612176565b610e7c7f7f63f876249f25f7856e620802edd09af38a83c9c6040fcdb371791540308311916121c36121b9610342612128565b82106110a161217e565b610415816006611048565b61032c90612108565b9061032c9695949392916121e9612581565b61032c9695949392919061220a600080516020612d738339815191526123e0565b61226c565b9194612261611e9a9298979561225060a09661224961032c9a61224260c08a019e60008b01906001600160a01b03169052565b6020890152565b6040870152565b6001600160801b0319166060850152565b61ffff166080830152565b9194959093929561227f61132b846105ee565b803b1561031a5786600087611eea82968c9661229a60405190565b9a8b9889978896636fb7e9c160e01b88526004880161220f565b9061032c9695949392916121d7565b9061032c9695949392916122d5612581565b61032c969594939291906122f6600080516020612d738339815191526123e0565b61234f565b9695939461032c956123396080956123326123469661232b8d97600060a08a019901906001600160a01b03169052565b60208d0152565b60408b0152565b88830360608a0152611272565b94019015159052565b9194959093929561236261132b846105ee565b803b1561031a5786600087611eea82968c9661237d60405190565b9a8b98899788966311de011760e31b8852600488016122fb565b9061032c9695949392916122c3565b637965db0b60e01b6001600160e01b03198216149081156123c5575090565b61034291506001600160e01b0319166301ffc9a760e01b1490565b61032c90339061276d565b9050519061032c82610aba565b9060208282031261031a57610342916123eb565b6124166037610f3c565b7f353230307c50726f636573736f723a207061796d656e74206163636f756e742060208201527f6e6f74206465706c6f79656420627920666163746f7279000000000000000000604082015290565b61034261240c565b610342612465565b602061249f9161248861132b600261112d565b604051938492839182916385bb392360e01b611921565b03915afa80156113f85761032c916000916124be575b506110a161246d565b6124e0915060203d6020116124e6575b6124d88183610ee0565b8101906123f8565b386124b5565b503d6124ce565b6125066125006103429263ffffffff1690565b60e01b90565b6001600160e01b03191690565b6001600160a01b0391821681529116602082015260608101929161032c9160400152565b9061257c9061256d61032c956004956125536323b872dd6124ed565b9361255d60405190565b9788956020870190815201612513565b60208201810382520383610ee0565b6127a9565b60025460ff1661258d57565b60405163d93c066560e01b8152600490fd5b6125a98282612831565b91826125b457505090565b6125c56103426125ca936001610e8a565b6128be565b5090565b6125d882826128f0565b91826125e357505090565b6125f46103426125ca936001610e8a565b61294c565b61260161296c565b61032c612629565b9060ff90610e27565b90612622610342610e4892151590565b8254612609565b61263560006002612612565b7f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa610e7c336108da565b61032c6125f9565b612671601b610f3c565b7f353130307c436f6d6d6f6e3a20616d6f756e74206973207a65726f0000000000602082015290565b610342612667565b61034261269a565b61032c906126bb61195660006109fd565b116110a16126a2565b6126cc612581565b61032c6126db60016002612612565b7f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610e7c336108da565b61032c6126c4565b610342906109fd565b61037a6103426103429290565b61274d6127486103429361274360006127529561273e600090565b500190565b6129d1565b61270d565b612716565b6105e5565b61276860006103429261273e600090565b6129f0565b9061277f61277b8284611c2c565b1590565b612787575050565b61103a61279360405190565b63e2517d3f60e01b8152928392600484016115d8565b6127b56127bc916105ee565b9182612a04565b80516127cb61195660006109fd565b1415908161280d575b506127dc5750565b61103a906127e960405190565b635274afe760e01b8152918291600483016001600160a01b03909116815260200190565b61282b915080602061282061277b935190565b8183010191016123f8565b386127d4565b61283e61277b8383611c2c565b156128a55761285d6001612858846000611c488682610e8a565b612612565b61287161286b611677339390565b916105ee565b917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d61289c60405190565b600090a4600190565b5050600090565b6103429081906001600160a01b031681565b906128eb6119566128e66128e16000610342966128d9600090565b5001946105e5565b6128ac565b6109fd565b612a71565b6128fa8282611c2c565b156128a55761291360006128588482611c488682610e8a565b61292161286b611677339390565b917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b61289c60405190565b906129676119566128e66128e16000610342966128d9600090565b612b3f565b61297b61277b60025460ff1690565b61298157565b604051638dfc202b60e01b8152600490fd5b634e487b7160e01b600052603260045260246000fd5b80548210156129cc576129c3600191600052602060002090565b91020190600090565b612993565b6103429160006129ea926129e3600090565b50016129a9565b90610b9d565b6000610342916129fe600090565b50015490565b61034291612a1260006109fd565b91612c23565b9160001960089290920291821b911b610e27565b9190612a3b610342610e489390565b908354612a18565b9081549168010000000000000000831015610f025782612a6b91600161032c950181556129a9565b90612a2c565b612a7e61277b8383612c88565b156128a557612aab91612aa6906001612a9f84612a9b8482612a43565b5490565b9301610e8a565b611048565b600190565b634e487b7160e01b600052601160045260246000fd5b91908203918211612ad357565b612ab0565b634e487b7160e01b600052603160045260246000fd5b61032c91600091612a2c565b80548015612b1d576000190190612b1a612b1483836129a9565b90612aee565b55565b612ad8565b9190612a3b610342610e48936109fd565b61032c91600091612b22565b90612b55612b508260018501610e8a565b610ea1565b612b5f60006109fd565b8114612bfc57612bc461034292600092612bb995612bbe6001978893612b8d612b87866109fd565b82612ac6565b88850191612bab612b9c845490565b612ba5896109fd565b90612ac6565b808303612bc9575b50505090565b612afa565b01610e8a565b612b33565b612a6b612bec612bf494612be36129ea612aa695896129a9565b928391886129a9565b888801610e8a565b388080612bb3565b505050600090565b3d15612c1e57612c133d610f3c565b903d6000602084013e565b606090565b91612c2d306105ee565b81813110612c57575060008281926020610342969551920190855af1612c51612c04565b91612cb3565b61103a90612c6460405190565b63cd78605960e01b8152918291600483016001600160a01b03909116815260200190565b612ca1916001612b5092612c9a600090565b5001610e8a565b612cae61195660006109fd565b141590565b90612cbe5750612d23565b8151612ccd61195660006109fd565b1480612d0d575b612cdc575090565b61103a90612ce960405190565b639996b31560e01b8152918291600483016001600160a01b03909116815260200190565b50803b612d1d61195660006109fd565b14612cd4565b8051612d3261195660006109fd565b1115612d4057805190602001fd5b604051630a12f52160e11b8152600490fdfefa658e47c75a6eb0e27156b2f72e1b295c98b53e8a1d238d7ca6ea6345b34880a567244cad934c87b7f7e15b15dd0e75f95a76afd1916f8eab4a391410d6f278a26469706673582212202e2530549c24438ec28dea3d0ac5bc4a94ae7752c7cb46a83d147d6cd4df5ffd64736f6c63430008160033"; + + private static String librariesLinkedBinary; public static final String FUNC_AUTHORIZATION_PROCESSOR_ROLE = "AUTHORIZATION_PROCESSOR_ROLE"; public static final String FUNC_BALANCE_VERIFIER_ROLE = "BALANCE_VERIFIER_ROLE"; + public static final String FUNC_CARD_CONFIRMER_ROLE = "CARD_CONFIRMER_ROLE"; + public static final String FUNC_DEBT_PROCESSOR_ROLE = "DEBT_PROCESSOR_ROLE"; public static final String FUNC_DEFAULT_ADMIN_ROLE = "DEFAULT_ADMIN_ROLE"; - public static final String FUNC_FIXED_FEE_SETTER_ROLE = "FIXED_FEE_SETTER_ROLE"; - public static final String FUNC_PAUSER_ROLE = "PAUSER_ROLE"; - public static final String FUNC_PAYMENT_ACCOUNT_SETTER_ROLE = "PAYMENT_ACCOUNT_SETTER_ROLE"; + public static final String FUNC_PAYMENT_ACCOUNT_DEPLOYER_ROLE = "PAYMENT_ACCOUNT_DEPLOYER_ROLE"; + + public static final String FUNC_PAYMENT_ACCOUNT_PROPERTY_SETTER_ROLE = "PAYMENT_ACCOUNT_PROPERTY_SETTER_ROLE"; public static final String FUNC_PROPERTY_SETTER_ROLE = "PROPERTY_SETTER_ROLE"; @@ -61,9 +69,9 @@ class TangemBridgeProcessor extends Contract { public static final String FUNC_SETTLEMENT_PROCESSOR_ROLE = "SETTLEMENT_PROCESSOR_ROLE"; - public static final String FUNC_FIXEDFEE = "fixedFee"; + public static final String FUNC_WITHDRAWAL_PROCESSOR_ROLE = "WITHDRAWAL_PROCESSOR_ROLE"; - public static final String FUNC_GETPAYMENTACCOUNT = "getPaymentAccount"; + public static final String FUNC_DEPLOYPAYMENTACCOUNT = "deployPaymentAccount"; public static final String FUNC_GETROLEADMIN = "getRoleAdmin"; @@ -77,6 +85,8 @@ class TangemBridgeProcessor extends Contract { public static final String FUNC_INCREASEVERIFIEDBALANCEFOR = "increaseVerifiedBalanceFor"; + public static final String FUNC_ISCARDCONFIRMER = "isCardConfirmer"; + public static final String FUNC_PAUSE = "pause"; public static final String FUNC_PAUSED = "paused"; @@ -87,13 +97,13 @@ class TangemBridgeProcessor extends Contract { public static final String FUNC_PAYMENTTOKEN = "paymentToken"; - public static final String FUNC_PROCESSAUTHORIZATION = "processAuthorization"; - public static final String FUNC_PROCESSAUTHORIZATIONCHANGE = "processAuthorizationChange"; - public static final String FUNC_PROCESSAUTHORIZATIONNOOTP = "processAuthorizationNoOtp"; + public static final String FUNC_PROCESSDEBT = "processDebt"; - public static final String FUNC_PROCESSPENDINGREFUND = "processPendingRefund"; + public static final String FUNC_PROCESSNOCONFIRMATIONAUTHORIZATION = "processNoConfirmationAuthorization"; + + public static final String FUNC_PROCESSOTPAUTHORIZATION = "processOtpAuthorization"; public static final String FUNC_PROCESSREFUND = "processRefund"; @@ -101,19 +111,21 @@ class TangemBridgeProcessor extends Contract { public static final String FUNC_PROCESSSETTLEMENT = "processSettlement"; + public static final String FUNC_PROCESSSIGNATUREAUTHORIZATION = "processSignatureAuthorization"; + + public static final String FUNC_PROCESSUNSETTLEDTRANSACTION = "processUnsettledTransaction"; + + public static final String FUNC_PROCESSWITHDRAWAL = "processWithdrawal"; + public static final String FUNC_REFUNDACCOUNT = "refundAccount"; public static final String FUNC_RENOUNCEROLE = "renounceRole"; public static final String FUNC_REVOKEROLE = "revokeRole"; - public static final String FUNC_SAVEPENDINGREFUND = "savePendingRefund"; - public static final String FUNC_SECURITYDELAY = "securityDelay"; - public static final String FUNC_SETFIXEDFEE = "setFixedFee"; - - public static final String FUNC_SETPAYMENTACCOUNT = "setPaymentAccount"; + public static final String FUNC_SETAUTHLIMITMARGINFOR = "setAuthLimitMarginFor"; public static final String FUNC_SETPAYMENTRECEIVER = "setPaymentReceiver"; @@ -121,214 +133,312 @@ class TangemBridgeProcessor extends Contract { public static final String FUNC_SETSECURITYDELAY = "setSecurityDelay"; - public static final String FUNC_SETSETTLEMENTPERIOD = "setSettlementPeriod"; - public static final String FUNC_SETVERIFIEDBALANCEFOR = "setVerifiedBalanceFor"; - public static final String FUNC_SETTLEMENTPERIOD = "settlementPeriod"; - public static final String FUNC_SUPPORTSINTERFACE = "supportsInterface"; public static final String FUNC_UNPAUSE = "unpause"; public static final String FUNC_WRITEOFFDEBT = "writeOffDebt"; + public static final Event AUTHLIMITMARGINSETFOR_EVENT = new Event("AuthLimitMarginSetFor", + Arrays.>asList(new TypeReference

(true) {}, new TypeReference() {})); + ; + public static final Event AUTHORIZATIONCHANGEPROCESSED_EVENT = new Event("AuthorizationChangeProcessed", - Arrays.asList(new TypeReference
(true) { - }, new TypeReference(true) { - }, new TypeReference() { - }, new TypeReference() { - })); + Arrays.>asList(new TypeReference
(true) {}, new TypeReference
(true) {}, new TypeReference(true) {}, new TypeReference() {})); + ; public static final Event AUTHORIZATIONPROCESSED_EVENT = new Event("AuthorizationProcessed", - Arrays.asList(new TypeReference
(true) { - }, new TypeReference(true) { - }, new TypeReference() { - }, new TypeReference() { - })); + Arrays.>asList(new TypeReference
(true) {}, new TypeReference
(true) {}, new TypeReference(true) {}, new TypeReference() {})); + ; + + public static final Event DEBTPROCESSED_EVENT = new Event("DebtProcessed", + Arrays.>asList(new TypeReference
(true) {}, new TypeReference
(true) {}, new TypeReference() {})); + ; public static final Event DEBTWRITEOFFPROCESSED_EVENT = new Event("DebtWriteOffProcessed", - Arrays.asList(new TypeReference
(true) { - }, new TypeReference() { - })); - - public static final Event FIXEDFEESET_EVENT = new Event("FixedFeeSet", - List.of(new TypeReference() { - })); + Arrays.>asList(new TypeReference
(true) {}, new TypeReference
(true) {}, new TypeReference() {})); + ; public static final Event PAUSED_EVENT = new Event("Paused", - List.of(new TypeReference
() { - })); + Arrays.>asList(new TypeReference
() {})); + ; - public static final Event PAYMENTACCOUNTSET_EVENT = new Event("PaymentAccountSet", - Arrays.asList(new TypeReference
(true) { - }, new TypeReference
() { - })); + public static final Event PAYMENTACCOUNTDEPLOYED_EVENT = new Event("PaymentAccountDeployed", + Arrays.>asList(new TypeReference
(true) {}, new TypeReference
() {}, new TypeReference
() {})); + ; public static final Event PAYMENTRECEIVERSET_EVENT = new Event("PaymentReceiverSet", - List.of(new TypeReference
() { - })); - - public static final Event PENDINGREFUNDPROCESSED_EVENT = new Event("PendingRefundProcessed", - Arrays.asList(new TypeReference
(true) { - }, new TypeReference(true) { - }, new TypeReference() { - })); + Arrays.>asList(new TypeReference
() {})); + ; public static final Event REFUNDACCOUNTSET_EVENT = new Event("RefundAccountSet", - List.of(new TypeReference
() { - })); + Arrays.>asList(new TypeReference
() {})); + ; public static final Event REFUNDPROCESSED_EVENT = new Event("RefundProcessed", - Arrays.asList(new TypeReference
(true) { - }, new TypeReference(true) { - }, new TypeReference() { - })); + Arrays.>asList(new TypeReference
(true) {}, new TypeReference
(true) {}, new TypeReference(true) {}, new TypeReference() {})); + ; public static final Event ROLEADMINCHANGED_EVENT = new Event("RoleAdminChanged", - Arrays.asList(new TypeReference(true) { - }, new TypeReference(true) { - }, new TypeReference(true) { - })); + Arrays.>asList(new TypeReference(true) {}, new TypeReference(true) {}, new TypeReference(true) {})); + ; public static final Event ROLEGRANTED_EVENT = new Event("RoleGranted", - Arrays.asList(new TypeReference(true) { - }, new TypeReference
(true) { - }, new TypeReference
(true) { - })); + Arrays.>asList(new TypeReference(true) {}, new TypeReference
(true) {}, new TypeReference
(true) {})); + ; public static final Event ROLEREVOKED_EVENT = new Event("RoleRevoked", - Arrays.asList(new TypeReference(true) { - }, new TypeReference
(true) { - }, new TypeReference
(true) { - })); - - public static final Event SAVEREFUNDPROCESSED_EVENT = new Event("SaveRefundProcessed", - Arrays.asList(new TypeReference
(true) { - }, new TypeReference(true) { - }, new TypeReference() { - })); + Arrays.>asList(new TypeReference(true) {}, new TypeReference
(true) {}, new TypeReference
(true) {})); + ; public static final Event SECURITYDELAYSET_EVENT = new Event("SecurityDelaySet", - List.of(new TypeReference() { - })); + Arrays.>asList(new TypeReference() {})); + ; public static final Event SETTLEMENTPERIODSET_EVENT = new Event("SettlementPeriodSet", - List.of(new TypeReference() { - })); + Arrays.>asList(new TypeReference() {})); + ; public static final Event SETTLEMENTPROCESSED_EVENT = new Event("SettlementProcessed", - Arrays.asList(new TypeReference
(true) { - }, new TypeReference(true) { - }, new TypeReference() { - }, new TypeReference() { - })); + Arrays.>asList(new TypeReference
(true) {}, new TypeReference
(true) {}, new TypeReference(true) {}, new TypeReference() {})); + ; public static final Event UNPAUSED_EVENT = new Event("Unpaused", - List.of(new TypeReference
() { - })); + Arrays.>asList(new TypeReference
() {})); + ; + + public static final Event UNSETTLEDTRANSACTIONPROCESSED_EVENT = new Event("UnsettledTransactionProcessed", + Arrays.>asList(new TypeReference
(true) {}, new TypeReference
(true) {}, new TypeReference() {})); + ; public static final Event VERIFIEDBALANCEINCREASEDFOR_EVENT = new Event("VerifiedBalanceIncreasedFor", - Arrays.asList(new TypeReference
(true) { - }, new TypeReference() { - })); + Arrays.>asList(new TypeReference
(true) {}, new TypeReference() {})); + ; public static final Event VERIFIEDBALANCESETFOR_EVENT = new Event("VerifiedBalanceSetFor", - Arrays.asList(new TypeReference
(true) { - }, new TypeReference() { - })); + Arrays.>asList(new TypeReference
(true) {}, new TypeReference() {})); + ; + + public static final Event WITHDRAWALPROCESSED_EVENT = new Event("WithdrawalProcessed", + Arrays.>asList(new TypeReference
(true) {})); + ; @Deprecated - protected TangemBridgeProcessor(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + protected TangemBridgeProcessor(String contractAddress, Web3j web3j, Credentials credentials, + BigInteger gasPrice, BigInteger gasLimit) { super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); } - protected TangemBridgeProcessor(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { + protected TangemBridgeProcessor(String contractAddress, Web3j web3j, Credentials credentials, + ContractGasProvider contractGasProvider) { super(BINARY, contractAddress, web3j, credentials, contractGasProvider); } @Deprecated - protected TangemBridgeProcessor(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) { + protected TangemBridgeProcessor(String contractAddress, Web3j web3j, + TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) { super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); } - protected TangemBridgeProcessor(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { + protected TangemBridgeProcessor(String contractAddress, Web3j web3j, + TransactionManager transactionManager, ContractGasProvider contractGasProvider) { super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); } - public static List getAuthorizationChangeProcessedEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(AUTHORIZATIONCHANGEPROCESSED_EVENT, transactionReceipt); - ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { - AuthorizationChangeProcessedEventResponse typedResponse = new AuthorizationChangeProcessedEventResponse(); + public static List getAuthLimitMarginSetForEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(AUTHLIMITMARGINSETFOR_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + AuthLimitMarginSetForEventResponse typedResponse = new AuthLimitMarginSetForEventResponse(); typedResponse.log = eventValues.getLog(); - typedResponse.card = (String) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(1).getValue(); - typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - typedResponse.fee = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); + typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.authLimitMargin = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); responses.add(typedResponse); } return responses; } - public static AuthorizationChangeProcessedEventResponse getAuthorizationChangeProcessedEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(AUTHORIZATIONCHANGEPROCESSED_EVENT, log); - AuthorizationChangeProcessedEventResponse typedResponse = new AuthorizationChangeProcessedEventResponse(); + public static AuthLimitMarginSetForEventResponse getAuthLimitMarginSetForEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(AUTHLIMITMARGINSETFOR_EVENT, log); + AuthLimitMarginSetForEventResponse typedResponse = new AuthLimitMarginSetForEventResponse(); typedResponse.log = log; - typedResponse.card = (String) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(1).getValue(); - typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - typedResponse.fee = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); + typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.authLimitMargin = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); return typedResponse; } - public static AuthorizationProcessedEventResponse getAuthorizationProcessedEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(AUTHORIZATIONPROCESSED_EVENT, log); + public Flowable authLimitMarginSetForEventFlowable( + EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getAuthLimitMarginSetForEventFromLog(log)); + } + + public Flowable authLimitMarginSetForEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(AUTHLIMITMARGINSETFOR_EVENT)); + return authLimitMarginSetForEventFlowable(filter); + } + + public static List getAuthorizationChangeProcessedEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(AUTHORIZATIONCHANGEPROCESSED_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + AuthorizationChangeProcessedEventResponse typedResponse = new AuthorizationChangeProcessedEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(2).getValue(); + typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public static AuthorizationChangeProcessedEventResponse getAuthorizationChangeProcessedEventFromLog( + Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(AUTHORIZATIONCHANGEPROCESSED_EVENT, log); + AuthorizationChangeProcessedEventResponse typedResponse = new AuthorizationChangeProcessedEventResponse(); + typedResponse.log = log; + typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(2).getValue(); + typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + + public Flowable authorizationChangeProcessedEventFlowable( + EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getAuthorizationChangeProcessedEventFromLog(log)); + } + + public Flowable authorizationChangeProcessedEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(AUTHORIZATIONCHANGEPROCESSED_EVENT)); + return authorizationChangeProcessedEventFlowable(filter); + } + + public static List getAuthorizationProcessedEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(AUTHORIZATIONPROCESSED_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + AuthorizationProcessedEventResponse typedResponse = new AuthorizationProcessedEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(2).getValue(); + typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public static AuthorizationProcessedEventResponse getAuthorizationProcessedEventFromLog( + Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(AUTHORIZATIONPROCESSED_EVENT, log); AuthorizationProcessedEventResponse typedResponse = new AuthorizationProcessedEventResponse(); typedResponse.log = log; - typedResponse.card = (String) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(2).getValue(); typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - typedResponse.fee = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); return typedResponse; } + public Flowable authorizationProcessedEventFlowable( + EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getAuthorizationProcessedEventFromLog(log)); + } + + public Flowable authorizationProcessedEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(AUTHORIZATIONPROCESSED_EVENT)); + return authorizationProcessedEventFlowable(filter); + } + + public static List getDebtProcessedEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(DEBTPROCESSED_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + DebtProcessedEventResponse typedResponse = new DebtProcessedEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public static DebtProcessedEventResponse getDebtProcessedEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(DEBTPROCESSED_EVENT, log); + DebtProcessedEventResponse typedResponse = new DebtProcessedEventResponse(); + typedResponse.log = log; + typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + + public Flowable debtProcessedEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getDebtProcessedEventFromLog(log)); + } + + public Flowable debtProcessedEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(DEBTPROCESSED_EVENT)); + return debtProcessedEventFlowable(filter); + } + + public static List getDebtWriteOffProcessedEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(DEBTWRITEOFFPROCESSED_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + DebtWriteOffProcessedEventResponse typedResponse = new DebtWriteOffProcessedEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + responses.add(typedResponse); + } + return responses; + } + public static DebtWriteOffProcessedEventResponse getDebtWriteOffProcessedEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(DEBTWRITEOFFPROCESSED_EVENT, log); + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(DEBTWRITEOFFPROCESSED_EVENT, log); DebtWriteOffProcessedEventResponse typedResponse = new DebtWriteOffProcessedEventResponse(); typedResponse.log = log; - typedResponse.card = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); return typedResponse; } - public static List getAuthorizationProcessedEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(AUTHORIZATIONPROCESSED_EVENT, transactionReceipt); - ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { - AuthorizationProcessedEventResponse typedResponse = new AuthorizationProcessedEventResponse(); - typedResponse.log = eventValues.getLog(); - typedResponse.card = (String) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(1).getValue(); - typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - typedResponse.fee = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); - responses.add(typedResponse); - } - return responses; + public Flowable debtWriteOffProcessedEventFlowable( + EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getDebtWriteOffProcessedEventFromLog(log)); } - public static FixedFeeSetEventResponse getFixedFeeSetEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(FIXEDFEESET_EVENT, log); - FixedFeeSetEventResponse typedResponse = new FixedFeeSetEventResponse(); - typedResponse.log = log; - typedResponse.fixedFee = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; + public Flowable debtWriteOffProcessedEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(DEBTWRITEOFFPROCESSED_EVENT)); + return debtWriteOffProcessedEventFlowable(filter); } public static List getPausedEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(PAUSED_EVENT, transactionReceipt); + List valueList = staticExtractEventParametersWithLog(PAUSED_EVENT, transactionReceipt); ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { + for (Contract.EventValuesWithLog eventValues : valueList) { PausedEventResponse typedResponse = new PausedEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.account = (String) eventValues.getNonIndexedValues().get(0).getValue(); @@ -338,177 +448,67 @@ class TangemBridgeProcessor extends Contract { } public static PausedEventResponse getPausedEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(PAUSED_EVENT, log); + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(PAUSED_EVENT, log); PausedEventResponse typedResponse = new PausedEventResponse(); typedResponse.log = log; typedResponse.account = (String) eventValues.getNonIndexedValues().get(0).getValue(); return typedResponse; } - public static List getDebtWriteOffProcessedEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(DEBTWRITEOFFPROCESSED_EVENT, transactionReceipt); - ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { - DebtWriteOffProcessedEventResponse typedResponse = new DebtWriteOffProcessedEventResponse(); + public Flowable pausedEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getPausedEventFromLog(log)); + } + + public Flowable pausedEventFlowable(DefaultBlockParameter startBlock, + DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(PAUSED_EVENT)); + return pausedEventFlowable(filter); + } + + public static List getPaymentAccountDeployedEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(PAYMENTACCOUNTDEPLOYED_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + PaymentAccountDeployedEventResponse typedResponse = new PaymentAccountDeployedEventResponse(); typedResponse.log = eventValues.getLog(); - typedResponse.card = (String) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + typedResponse.owner = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.cardAddress = (String) eventValues.getNonIndexedValues().get(0).getValue(); + typedResponse.paymentAccount = (String) eventValues.getNonIndexedValues().get(1).getValue(); responses.add(typedResponse); } return responses; } - public static PaymentAccountSetEventResponse getPaymentAccountSetEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(PAYMENTACCOUNTSET_EVENT, log); - PaymentAccountSetEventResponse typedResponse = new PaymentAccountSetEventResponse(); + public static PaymentAccountDeployedEventResponse getPaymentAccountDeployedEventFromLog( + Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(PAYMENTACCOUNTDEPLOYED_EVENT, log); + PaymentAccountDeployedEventResponse typedResponse = new PaymentAccountDeployedEventResponse(); typedResponse.log = log; - typedResponse.card = (String) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.paymentAccount = (String) eventValues.getNonIndexedValues().get(0).getValue(); + typedResponse.owner = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.cardAddress = (String) eventValues.getNonIndexedValues().get(0).getValue(); + typedResponse.paymentAccount = (String) eventValues.getNonIndexedValues().get(1).getValue(); return typedResponse; } - public static PaymentReceiverSetEventResponse getPaymentReceiverSetEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(PAYMENTRECEIVERSET_EVENT, log); - PaymentReceiverSetEventResponse typedResponse = new PaymentReceiverSetEventResponse(); - typedResponse.log = log; - typedResponse.paymentReceiver = (String) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; + public Flowable paymentAccountDeployedEventFlowable( + EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getPaymentAccountDeployedEventFromLog(log)); } - public static RefundAccountSetEventResponse getRefundAccountSetEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(REFUNDACCOUNTSET_EVENT, log); - RefundAccountSetEventResponse typedResponse = new RefundAccountSetEventResponse(); - typedResponse.log = log; - typedResponse.refundAccount = (String) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; + public Flowable paymentAccountDeployedEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(PAYMENTACCOUNTDEPLOYED_EVENT)); + return paymentAccountDeployedEventFlowable(filter); } - public static List getFixedFeeSetEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(FIXEDFEESET_EVENT, transactionReceipt); - ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { - FixedFeeSetEventResponse typedResponse = new FixedFeeSetEventResponse(); - typedResponse.log = eventValues.getLog(); - typedResponse.fixedFee = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - responses.add(typedResponse); - } - return responses; - } - - public static RefundProcessedEventResponse getRefundProcessedEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(REFUNDPROCESSED_EVENT, log); - RefundProcessedEventResponse typedResponse = new RefundProcessedEventResponse(); - typedResponse.log = log; - typedResponse.card = (String) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(1).getValue(); - typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; - } - - public static RoleAdminChangedEventResponse getRoleAdminChangedEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(ROLEADMINCHANGED_EVENT, log); - RoleAdminChangedEventResponse typedResponse = new RoleAdminChangedEventResponse(); - typedResponse.log = log; - typedResponse.role = (byte[]) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.previousAdminRole = (byte[]) eventValues.getIndexedValues().get(1).getValue(); - typedResponse.newAdminRole = (byte[]) eventValues.getIndexedValues().get(2).getValue(); - return typedResponse; - } - - public static RoleGrantedEventResponse getRoleGrantedEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(ROLEGRANTED_EVENT, log); - RoleGrantedEventResponse typedResponse = new RoleGrantedEventResponse(); - typedResponse.log = log; - typedResponse.role = (byte[]) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.account = (String) eventValues.getIndexedValues().get(1).getValue(); - typedResponse.sender = (String) eventValues.getIndexedValues().get(2).getValue(); - return typedResponse; - } - - public static RoleRevokedEventResponse getRoleRevokedEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(ROLEREVOKED_EVENT, log); - RoleRevokedEventResponse typedResponse = new RoleRevokedEventResponse(); - typedResponse.log = log; - typedResponse.role = (byte[]) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.account = (String) eventValues.getIndexedValues().get(1).getValue(); - typedResponse.sender = (String) eventValues.getIndexedValues().get(2).getValue(); - return typedResponse; - } - - public static SaveRefundProcessedEventResponse getSaveRefundProcessedEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(SAVEREFUNDPROCESSED_EVENT, log); - SaveRefundProcessedEventResponse typedResponse = new SaveRefundProcessedEventResponse(); - typedResponse.log = log; - typedResponse.card = (String) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(1).getValue(); - typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; - } - - public static SecurityDelaySetEventResponse getSecurityDelaySetEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(SECURITYDELAYSET_EVENT, log); - SecurityDelaySetEventResponse typedResponse = new SecurityDelaySetEventResponse(); - typedResponse.log = log; - typedResponse.securityDelay = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; - } - - public static SettlementPeriodSetEventResponse getSettlementPeriodSetEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(SETTLEMENTPERIODSET_EVENT, log); - SettlementPeriodSetEventResponse typedResponse = new SettlementPeriodSetEventResponse(); - typedResponse.log = log; - typedResponse.settlementPeriod = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; - } - - public static List getPaymentAccountSetEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(PAYMENTACCOUNTSET_EVENT, transactionReceipt); - ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { - PaymentAccountSetEventResponse typedResponse = new PaymentAccountSetEventResponse(); - typedResponse.log = eventValues.getLog(); - typedResponse.card = (String) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.paymentAccount = (String) eventValues.getNonIndexedValues().get(0).getValue(); - responses.add(typedResponse); - } - return responses; - } - - public static SettlementProcessedEventResponse getSettlementProcessedEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(SETTLEMENTPROCESSED_EVENT, log); - SettlementProcessedEventResponse typedResponse = new SettlementProcessedEventResponse(); - typedResponse.log = log; - typedResponse.card = (String) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(1).getValue(); - typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - typedResponse.fee = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); - return typedResponse; - } - - public static List getUnpausedEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(UNPAUSED_EVENT, transactionReceipt); - ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { - UnpausedEventResponse typedResponse = new UnpausedEventResponse(); - typedResponse.log = eventValues.getLog(); - typedResponse.account = (String) eventValues.getNonIndexedValues().get(0).getValue(); - responses.add(typedResponse); - } - return responses; - } - - public static UnpausedEventResponse getUnpausedEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(UNPAUSED_EVENT, log); - UnpausedEventResponse typedResponse = new UnpausedEventResponse(); - typedResponse.log = log; - typedResponse.account = (String) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; - } - - public static List getPaymentReceiverSetEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(PAYMENTRECEIVERSET_EVENT, transactionReceipt); + public static List getPaymentReceiverSetEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(PAYMENTRECEIVERSET_EVENT, transactionReceipt); ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { + for (Contract.EventValuesWithLog eventValues : valueList) { PaymentReceiverSetEventResponse typedResponse = new PaymentReceiverSetEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.paymentReceiver = (String) eventValues.getNonIndexedValues().get(0).getValue(); @@ -517,61 +517,31 @@ class TangemBridgeProcessor extends Contract { return responses; } - public static VerifiedBalanceIncreasedForEventResponse getVerifiedBalanceIncreasedForEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(VERIFIEDBALANCEINCREASEDFOR_EVENT, log); - VerifiedBalanceIncreasedForEventResponse typedResponse = new VerifiedBalanceIncreasedForEventResponse(); + public static PaymentReceiverSetEventResponse getPaymentReceiverSetEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(PAYMENTRECEIVERSET_EVENT, log); + PaymentReceiverSetEventResponse typedResponse = new PaymentReceiverSetEventResponse(); typedResponse.log = log; - typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.increase = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + typedResponse.paymentReceiver = (String) eventValues.getNonIndexedValues().get(0).getValue(); return typedResponse; } - @Deprecated - public static TangemBridgeProcessor load(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { - return new TangemBridgeProcessor(contractAddress, web3j, credentials, gasPrice, gasLimit); + public Flowable paymentReceiverSetEventFlowable( + EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getPaymentReceiverSetEventFromLog(log)); } - @Deprecated - public static TangemBridgeProcessor load(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) { - return new TangemBridgeProcessor(contractAddress, web3j, transactionManager, gasPrice, gasLimit); + public Flowable paymentReceiverSetEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(PAYMENTRECEIVERSET_EVENT)); + return paymentReceiverSetEventFlowable(filter); } - public static List getPendingRefundProcessedEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(PENDINGREFUNDPROCESSED_EVENT, transactionReceipt); - ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { - PendingRefundProcessedEventResponse typedResponse = new PendingRefundProcessedEventResponse(); - typedResponse.log = eventValues.getLog(); - typedResponse.card = (String) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(1).getValue(); - typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - responses.add(typedResponse); - } - return responses; - } - - public static PendingRefundProcessedEventResponse getPendingRefundProcessedEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(PENDINGREFUNDPROCESSED_EVENT, log); - PendingRefundProcessedEventResponse typedResponse = new PendingRefundProcessedEventResponse(); - typedResponse.log = log; - typedResponse.card = (String) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(1).getValue(); - typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; - } - - public static TangemBridgeProcessor load(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { - return new TangemBridgeProcessor(contractAddress, web3j, credentials, contractGasProvider); - } - - public static TangemBridgeProcessor load(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { - return new TangemBridgeProcessor(contractAddress, web3j, transactionManager, contractGasProvider); - } - - public static List getRefundAccountSetEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(REFUNDACCOUNTSET_EVENT, transactionReceipt); + public static List getRefundAccountSetEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(REFUNDACCOUNTSET_EVENT, transactionReceipt); ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { + for (Contract.EventValuesWithLog eventValues : valueList) { RefundAccountSetEventResponse typedResponse = new RefundAccountSetEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.refundAccount = (String) eventValues.getNonIndexedValues().get(0).getValue(); @@ -580,72 +550,68 @@ class TangemBridgeProcessor extends Contract { return responses; } - public static RemoteCall deploy(Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider, String paymentReceiver_, String refundAccount_, String paymentAccountFactory_, String paymentToken_, BigInteger securityDelay_) { - String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(new Address(160, paymentReceiver_), - new Address(160, refundAccount_), - new Address(160, paymentAccountFactory_), - new Address(160, paymentToken_), - new Uint256(securityDelay_))); - return deployRemoteCall(TangemBridgeProcessor.class, web3j, credentials, contractGasProvider, BINARY, encodedConstructor); + public static RefundAccountSetEventResponse getRefundAccountSetEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(REFUNDACCOUNTSET_EVENT, log); + RefundAccountSetEventResponse typedResponse = new RefundAccountSetEventResponse(); + typedResponse.log = log; + typedResponse.refundAccount = (String) eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; } - public static RemoteCall deploy(Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider, String paymentReceiver_, String refundAccount_, String paymentAccountFactory_, String paymentToken_, BigInteger securityDelay_) { - String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(new Address(160, paymentReceiver_), - new Address(160, refundAccount_), - new Address(160, paymentAccountFactory_), - new Address(160, paymentToken_), - new Uint256(securityDelay_))); - return deployRemoteCall(TangemBridgeProcessor.class, web3j, transactionManager, contractGasProvider, BINARY, encodedConstructor); + public Flowable refundAccountSetEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getRefundAccountSetEventFromLog(log)); } - @Deprecated - public static RemoteCall deploy(Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit, String paymentReceiver_, String refundAccount_, String paymentAccountFactory_, String paymentToken_, BigInteger securityDelay_) { - String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(new Address(160, paymentReceiver_), - new Address(160, refundAccount_), - new Address(160, paymentAccountFactory_), - new Address(160, paymentToken_), - new Uint256(securityDelay_))); - return deployRemoteCall(TangemBridgeProcessor.class, web3j, credentials, gasPrice, gasLimit, BINARY, encodedConstructor); + public Flowable refundAccountSetEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(REFUNDACCOUNTSET_EVENT)); + return refundAccountSetEventFlowable(filter); } - public static List getRefundProcessedEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(REFUNDPROCESSED_EVENT, transactionReceipt); + public static List getRefundProcessedEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(REFUNDPROCESSED_EVENT, transactionReceipt); ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { + for (Contract.EventValuesWithLog eventValues : valueList) { RefundProcessedEventResponse typedResponse = new RefundProcessedEventResponse(); typedResponse.log = eventValues.getLog(); - typedResponse.card = (String) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(2).getValue(); typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); responses.add(typedResponse); } return responses; } - @Deprecated - public static RemoteCall deploy(Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit, String paymentReceiver_, String refundAccount_, String paymentAccountFactory_, String paymentToken_, BigInteger securityDelay_) { - String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(new Address(160, paymentReceiver_), - new Address(160, refundAccount_), - new Address(160, paymentAccountFactory_), - new Address(160, paymentToken_), - new Uint256(securityDelay_))); - return deployRemoteCall(TangemBridgeProcessor.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, encodedConstructor); + public static RefundProcessedEventResponse getRefundProcessedEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(REFUNDPROCESSED_EVENT, log); + RefundProcessedEventResponse typedResponse = new RefundProcessedEventResponse(); + typedResponse.log = log; + typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(2).getValue(); + typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; } - public Flowable authorizationChangeProcessedEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getAuthorizationChangeProcessedEventFromLog(log)); + public Flowable refundProcessedEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getRefundProcessedEventFromLog(log)); } - public Flowable authorizationChangeProcessedEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + public Flowable refundProcessedEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(AUTHORIZATIONCHANGEPROCESSED_EVENT)); - return authorizationChangeProcessedEventFlowable(filter); + filter.addSingleTopic(EventEncoder.encode(REFUNDPROCESSED_EVENT)); + return refundProcessedEventFlowable(filter); } - public static List getRoleAdminChangedEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(ROLEADMINCHANGED_EVENT, transactionReceipt); + public static List getRoleAdminChangedEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(ROLEADMINCHANGED_EVENT, transactionReceipt); ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { + for (Contract.EventValuesWithLog eventValues : valueList) { RoleAdminChangedEventResponse typedResponse = new RoleAdminChangedEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.role = (byte[]) eventValues.getIndexedValues().get(0).getValue(); @@ -656,24 +622,32 @@ class TangemBridgeProcessor extends Contract { return responses; } - public Flowable authorizationProcessedEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getAuthorizationProcessedEventFromLog(log)); + public static RoleAdminChangedEventResponse getRoleAdminChangedEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(ROLEADMINCHANGED_EVENT, log); + RoleAdminChangedEventResponse typedResponse = new RoleAdminChangedEventResponse(); + typedResponse.log = log; + typedResponse.role = (byte[]) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.previousAdminRole = (byte[]) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.newAdminRole = (byte[]) eventValues.getIndexedValues().get(2).getValue(); + return typedResponse; } - public Flowable authorizationProcessedEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + public Flowable roleAdminChangedEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getRoleAdminChangedEventFromLog(log)); + } + + public Flowable roleAdminChangedEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(AUTHORIZATIONPROCESSED_EVENT)); - return authorizationProcessedEventFlowable(filter); + filter.addSingleTopic(EventEncoder.encode(ROLEADMINCHANGED_EVENT)); + return roleAdminChangedEventFlowable(filter); } - public Flowable debtWriteOffProcessedEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getDebtWriteOffProcessedEventFromLog(log)); - } - - public static List getRoleGrantedEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(ROLEGRANTED_EVENT, transactionReceipt); + public static List getRoleGrantedEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(ROLEGRANTED_EVENT, transactionReceipt); ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { + for (Contract.EventValuesWithLog eventValues : valueList) { RoleGrantedEventResponse typedResponse = new RoleGrantedEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.role = (byte[]) eventValues.getIndexedValues().get(0).getValue(); @@ -684,26 +658,32 @@ class TangemBridgeProcessor extends Contract { return responses; } - public Flowable debtWriteOffProcessedEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + public static RoleGrantedEventResponse getRoleGrantedEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(ROLEGRANTED_EVENT, log); + RoleGrantedEventResponse typedResponse = new RoleGrantedEventResponse(); + typedResponse.log = log; + typedResponse.role = (byte[]) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.account = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.sender = (String) eventValues.getIndexedValues().get(2).getValue(); + return typedResponse; + } + + public Flowable roleGrantedEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getRoleGrantedEventFromLog(log)); + } + + public Flowable roleGrantedEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(DEBTWRITEOFFPROCESSED_EVENT)); - return debtWriteOffProcessedEventFlowable(filter); + filter.addSingleTopic(EventEncoder.encode(ROLEGRANTED_EVENT)); + return roleGrantedEventFlowable(filter); } - public Flowable fixedFeeSetEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getFixedFeeSetEventFromLog(log)); - } - - public Flowable fixedFeeSetEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(FIXEDFEESET_EVENT)); - return fixedFeeSetEventFlowable(filter); - } - - public static List getRoleRevokedEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(ROLEREVOKED_EVENT, transactionReceipt); + public static List getRoleRevokedEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(ROLEREVOKED_EVENT, transactionReceipt); ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { + for (Contract.EventValuesWithLog eventValues : valueList) { RoleRevokedEventResponse typedResponse = new RoleRevokedEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.role = (byte[]) eventValues.getIndexedValues().get(0).getValue(); @@ -714,54 +694,32 @@ class TangemBridgeProcessor extends Contract { return responses; } - public Flowable pausedEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getPausedEventFromLog(log)); + public static RoleRevokedEventResponse getRoleRevokedEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(ROLEREVOKED_EVENT, log); + RoleRevokedEventResponse typedResponse = new RoleRevokedEventResponse(); + typedResponse.log = log; + typedResponse.role = (byte[]) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.account = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.sender = (String) eventValues.getIndexedValues().get(2).getValue(); + return typedResponse; } - public Flowable pausedEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + public Flowable roleRevokedEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getRoleRevokedEventFromLog(log)); + } + + public Flowable roleRevokedEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(PAUSED_EVENT)); - return pausedEventFlowable(filter); + filter.addSingleTopic(EventEncoder.encode(ROLEREVOKED_EVENT)); + return roleRevokedEventFlowable(filter); } - public Flowable paymentAccountSetEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getPaymentAccountSetEventFromLog(log)); - } - - public static List getSaveRefundProcessedEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(SAVEREFUNDPROCESSED_EVENT, transactionReceipt); - ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { - SaveRefundProcessedEventResponse typedResponse = new SaveRefundProcessedEventResponse(); - typedResponse.log = eventValues.getLog(); - typedResponse.card = (String) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(1).getValue(); - typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - responses.add(typedResponse); - } - return responses; - } - - public Flowable paymentAccountSetEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(PAYMENTACCOUNTSET_EVENT)); - return paymentAccountSetEventFlowable(filter); - } - - public Flowable paymentReceiverSetEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getPaymentReceiverSetEventFromLog(log)); - } - - public Flowable paymentReceiverSetEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(PAYMENTRECEIVERSET_EVENT)); - return paymentReceiverSetEventFlowable(filter); - } - - public static List getSecurityDelaySetEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(SECURITYDELAYSET_EVENT, transactionReceipt); + public static List getSecurityDelaySetEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(SECURITYDELAYSET_EVENT, transactionReceipt); ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { + for (Contract.EventValuesWithLog eventValues : valueList) { SecurityDelaySetEventResponse typedResponse = new SecurityDelaySetEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.securityDelay = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); @@ -770,24 +728,30 @@ class TangemBridgeProcessor extends Contract { return responses; } - public Flowable pendingRefundProcessedEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getPendingRefundProcessedEventFromLog(log)); + public static SecurityDelaySetEventResponse getSecurityDelaySetEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(SECURITYDELAYSET_EVENT, log); + SecurityDelaySetEventResponse typedResponse = new SecurityDelaySetEventResponse(); + typedResponse.log = log; + typedResponse.securityDelay = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; } - public Flowable pendingRefundProcessedEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + public Flowable securityDelaySetEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getSecurityDelaySetEventFromLog(log)); + } + + public Flowable securityDelaySetEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(PENDINGREFUNDPROCESSED_EVENT)); - return pendingRefundProcessedEventFlowable(filter); + filter.addSingleTopic(EventEncoder.encode(SECURITYDELAYSET_EVENT)); + return securityDelaySetEventFlowable(filter); } - public Flowable refundAccountSetEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getRefundAccountSetEventFromLog(log)); - } - - public static List getSettlementPeriodSetEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(SETTLEMENTPERIODSET_EVENT, transactionReceipt); + public static List getSettlementPeriodSetEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(SETTLEMENTPERIODSET_EVENT, transactionReceipt); ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { + for (Contract.EventValuesWithLog eventValues : valueList) { SettlementPeriodSetEventResponse typedResponse = new SettlementPeriodSetEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.settlementPeriod = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); @@ -796,75 +760,140 @@ class TangemBridgeProcessor extends Contract { return responses; } - public Flowable refundAccountSetEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + public static SettlementPeriodSetEventResponse getSettlementPeriodSetEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(SETTLEMENTPERIODSET_EVENT, log); + SettlementPeriodSetEventResponse typedResponse = new SettlementPeriodSetEventResponse(); + typedResponse.log = log; + typedResponse.settlementPeriod = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + + public Flowable settlementPeriodSetEventFlowable( + EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getSettlementPeriodSetEventFromLog(log)); + } + + public Flowable settlementPeriodSetEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(REFUNDACCOUNTSET_EVENT)); - return refundAccountSetEventFlowable(filter); + filter.addSingleTopic(EventEncoder.encode(SETTLEMENTPERIODSET_EVENT)); + return settlementPeriodSetEventFlowable(filter); } - public Flowable refundProcessedEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getRefundProcessedEventFromLog(log)); - } - - public Flowable refundProcessedEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(REFUNDPROCESSED_EVENT)); - return refundProcessedEventFlowable(filter); - } - - public static List getSettlementProcessedEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(SETTLEMENTPROCESSED_EVENT, transactionReceipt); + public static List getSettlementProcessedEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(SETTLEMENTPROCESSED_EVENT, transactionReceipt); ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { + for (Contract.EventValuesWithLog eventValues : valueList) { SettlementProcessedEventResponse typedResponse = new SettlementProcessedEventResponse(); typedResponse.log = eventValues.getLog(); - typedResponse.card = (String) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(2).getValue(); typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - typedResponse.fee = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); responses.add(typedResponse); } return responses; } - public Flowable roleAdminChangedEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getRoleAdminChangedEventFromLog(log)); + public static SettlementProcessedEventResponse getSettlementProcessedEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(SETTLEMENTPROCESSED_EVENT, log); + SettlementProcessedEventResponse typedResponse = new SettlementProcessedEventResponse(); + typedResponse.log = log; + typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(2).getValue(); + typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; } - public Flowable roleAdminChangedEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + public Flowable settlementProcessedEventFlowable( + EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getSettlementProcessedEventFromLog(log)); + } + + public Flowable settlementProcessedEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(ROLEADMINCHANGED_EVENT)); - return roleAdminChangedEventFlowable(filter); + filter.addSingleTopic(EventEncoder.encode(SETTLEMENTPROCESSED_EVENT)); + return settlementProcessedEventFlowable(filter); } - public Flowable roleGrantedEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getRoleGrantedEventFromLog(log)); + public static List getUnpausedEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(UNPAUSED_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + UnpausedEventResponse typedResponse = new UnpausedEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.account = (String) eventValues.getNonIndexedValues().get(0).getValue(); + responses.add(typedResponse); + } + return responses; } - public Flowable roleGrantedEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + public static UnpausedEventResponse getUnpausedEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(UNPAUSED_EVENT, log); + UnpausedEventResponse typedResponse = new UnpausedEventResponse(); + typedResponse.log = log; + typedResponse.account = (String) eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + + public Flowable unpausedEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getUnpausedEventFromLog(log)); + } + + public Flowable unpausedEventFlowable(DefaultBlockParameter startBlock, + DefaultBlockParameter endBlock) { EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(ROLEGRANTED_EVENT)); - return roleGrantedEventFlowable(filter); + filter.addSingleTopic(EventEncoder.encode(UNPAUSED_EVENT)); + return unpausedEventFlowable(filter); } - public Flowable roleRevokedEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getRoleRevokedEventFromLog(log)); + public static List getUnsettledTransactionProcessedEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(UNSETTLEDTRANSACTIONPROCESSED_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + UnsettledTransactionProcessedEventResponse typedResponse = new UnsettledTransactionProcessedEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.transactionId = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + responses.add(typedResponse); + } + return responses; } - public Flowable roleRevokedEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + public static UnsettledTransactionProcessedEventResponse getUnsettledTransactionProcessedEventFromLog( + Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(UNSETTLEDTRANSACTIONPROCESSED_EVENT, log); + UnsettledTransactionProcessedEventResponse typedResponse = new UnsettledTransactionProcessedEventResponse(); + typedResponse.log = log; + typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.transactionId = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + + public Flowable unsettledTransactionProcessedEventFlowable( + EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getUnsettledTransactionProcessedEventFromLog(log)); + } + + public Flowable unsettledTransactionProcessedEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(ROLEREVOKED_EVENT)); - return roleRevokedEventFlowable(filter); + filter.addSingleTopic(EventEncoder.encode(UNSETTLEDTRANSACTIONPROCESSED_EVENT)); + return unsettledTransactionProcessedEventFlowable(filter); } - public Flowable saveRefundProcessedEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getSaveRefundProcessedEventFromLog(log)); - } - - public static List getVerifiedBalanceIncreasedForEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(VERIFIEDBALANCEINCREASEDFOR_EVENT, transactionReceipt); + public static List getVerifiedBalanceIncreasedForEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(VERIFIEDBALANCEINCREASEDFOR_EVENT, transactionReceipt); ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { + for (Contract.EventValuesWithLog eventValues : valueList) { VerifiedBalanceIncreasedForEventResponse typedResponse = new VerifiedBalanceIncreasedForEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); @@ -874,26 +903,33 @@ class TangemBridgeProcessor extends Contract { return responses; } - public Flowable saveRefundProcessedEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + public static VerifiedBalanceIncreasedForEventResponse getVerifiedBalanceIncreasedForEventFromLog( + Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(VERIFIEDBALANCEINCREASEDFOR_EVENT, log); + VerifiedBalanceIncreasedForEventResponse typedResponse = new VerifiedBalanceIncreasedForEventResponse(); + typedResponse.log = log; + typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.increase = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + + public Flowable verifiedBalanceIncreasedForEventFlowable( + EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getVerifiedBalanceIncreasedForEventFromLog(log)); + } + + public Flowable verifiedBalanceIncreasedForEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(SAVEREFUNDPROCESSED_EVENT)); - return saveRefundProcessedEventFlowable(filter); + filter.addSingleTopic(EventEncoder.encode(VERIFIEDBALANCEINCREASEDFOR_EVENT)); + return verifiedBalanceIncreasedForEventFlowable(filter); } - public Flowable securityDelaySetEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getSecurityDelaySetEventFromLog(log)); - } - - public Flowable securityDelaySetEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(SECURITYDELAYSET_EVENT)); - return securityDelaySetEventFlowable(filter); - } - - public static List getVerifiedBalanceSetForEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(VERIFIEDBALANCESETFOR_EVENT, transactionReceipt); + public static List getVerifiedBalanceSetForEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(VERIFIEDBALANCESETFOR_EVENT, transactionReceipt); ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { + for (Contract.EventValuesWithLog eventValues : valueList) { VerifiedBalanceSetForEventResponse typedResponse = new VerifiedBalanceSetForEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); @@ -904,7 +940,7 @@ class TangemBridgeProcessor extends Contract { } public static VerifiedBalanceSetForEventResponse getVerifiedBalanceSetForEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(VERIFIEDBALANCESETFOR_EVENT, log); + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(VERIFIEDBALANCESETFOR_EVENT, log); VerifiedBalanceSetForEventResponse typedResponse = new VerifiedBalanceSetForEventResponse(); typedResponse.log = log; typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); @@ -912,486 +948,671 @@ class TangemBridgeProcessor extends Contract { return typedResponse; } - public Flowable verifiedBalanceSetForEventFlowable(EthFilter filter) { + public Flowable verifiedBalanceSetForEventFlowable( + EthFilter filter) { return web3j.ethLogFlowable(filter).map(log -> getVerifiedBalanceSetForEventFromLog(log)); } - public Flowable verifiedBalanceSetForEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + public Flowable verifiedBalanceSetForEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); filter.addSingleTopic(EventEncoder.encode(VERIFIEDBALANCESETFOR_EVENT)); return verifiedBalanceSetForEventFlowable(filter); } - public Flowable settlementPeriodSetEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getSettlementPeriodSetEventFromLog(log)); + public static List getWithdrawalProcessedEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(WITHDRAWALPROCESSED_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + WithdrawalProcessedEventResponse typedResponse = new WithdrawalProcessedEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); + responses.add(typedResponse); + } + return responses; } - public Flowable settlementPeriodSetEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + public static WithdrawalProcessedEventResponse getWithdrawalProcessedEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(WITHDRAWALPROCESSED_EVENT, log); + WithdrawalProcessedEventResponse typedResponse = new WithdrawalProcessedEventResponse(); + typedResponse.log = log; + typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); + return typedResponse; + } + + public Flowable withdrawalProcessedEventFlowable( + EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getWithdrawalProcessedEventFromLog(log)); + } + + public Flowable withdrawalProcessedEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(SETTLEMENTPERIODSET_EVENT)); - return settlementPeriodSetEventFlowable(filter); - } - - public Flowable settlementProcessedEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getSettlementProcessedEventFromLog(log)); - } - - public Flowable settlementProcessedEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(SETTLEMENTPROCESSED_EVENT)); - return settlementProcessedEventFlowable(filter); - } - - public Flowable unpausedEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getUnpausedEventFromLog(log)); - } - - public Flowable unpausedEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(UNPAUSED_EVENT)); - return unpausedEventFlowable(filter); - } - - public Flowable verifiedBalanceIncreasedForEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getVerifiedBalanceIncreasedForEventFromLog(log)); - } - - public Flowable verifiedBalanceIncreasedForEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(VERIFIEDBALANCEINCREASEDFOR_EVENT)); - return verifiedBalanceIncreasedForEventFlowable(filter); + filter.addSingleTopic(EventEncoder.encode(WITHDRAWALPROCESSED_EVENT)); + return withdrawalProcessedEventFlowable(filter); } public RemoteFunctionCall AUTHORIZATION_PROCESSOR_ROLE() { final Function function = new Function(FUNC_AUTHORIZATION_PROCESSOR_ROLE, - List.of(), - List.of(new TypeReference() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, byte[].class); } public RemoteFunctionCall BALANCE_VERIFIER_ROLE() { final Function function = new Function(FUNC_BALANCE_VERIFIER_ROLE, - List.of(), - List.of(new TypeReference() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, byte[].class); + } + + public RemoteFunctionCall CARD_CONFIRMER_ROLE() { + final Function function = new Function(FUNC_CARD_CONFIRMER_ROLE, + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, byte[].class); } public RemoteFunctionCall DEBT_PROCESSOR_ROLE() { final Function function = new Function(FUNC_DEBT_PROCESSOR_ROLE, - List.of(), - List.of(new TypeReference() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, byte[].class); } public RemoteFunctionCall DEFAULT_ADMIN_ROLE() { final Function function = new Function(FUNC_DEFAULT_ADMIN_ROLE, - List.of(), - List.of(new TypeReference() { - })); - return executeRemoteCallSingleValueReturn(function, byte[].class); - } - - public RemoteFunctionCall FIXED_FEE_SETTER_ROLE() { - final Function function = new Function(FUNC_FIXED_FEE_SETTER_ROLE, - List.of(), - List.of(new TypeReference() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, byte[].class); } public RemoteFunctionCall PAUSER_ROLE() { final Function function = new Function(FUNC_PAUSER_ROLE, - List.of(), - List.of(new TypeReference() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, byte[].class); } - public RemoteFunctionCall PAYMENT_ACCOUNT_SETTER_ROLE() { - final Function function = new Function(FUNC_PAYMENT_ACCOUNT_SETTER_ROLE, - List.of(), - List.of(new TypeReference() { - })); + public RemoteFunctionCall PAYMENT_ACCOUNT_DEPLOYER_ROLE() { + final Function function = new Function(FUNC_PAYMENT_ACCOUNT_DEPLOYER_ROLE, + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, byte[].class); + } + + public RemoteFunctionCall PAYMENT_ACCOUNT_PROPERTY_SETTER_ROLE() { + final Function function = new Function(FUNC_PAYMENT_ACCOUNT_PROPERTY_SETTER_ROLE, + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, byte[].class); } public RemoteFunctionCall PROPERTY_SETTER_ROLE() { final Function function = new Function(FUNC_PROPERTY_SETTER_ROLE, - List.of(), - List.of(new TypeReference() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, byte[].class); } public RemoteFunctionCall REFUND_PROCESSOR_ROLE() { final Function function = new Function(FUNC_REFUND_PROCESSOR_ROLE, - List.of(), - List.of(new TypeReference() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, byte[].class); } public RemoteFunctionCall SETTLEMENT_PROCESSOR_ROLE() { final Function function = new Function(FUNC_SETTLEMENT_PROCESSOR_ROLE, - List.of(), - List.of(new TypeReference() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, byte[].class); } - public RemoteFunctionCall fixedFee() { - final Function function = new Function(FUNC_FIXEDFEE, - List.of(), - List.of(new TypeReference() { - })); - return executeRemoteCallSingleValueReturn(function, BigInteger.class); + public RemoteFunctionCall WITHDRAWAL_PROCESSOR_ROLE() { + final Function function = new Function(FUNC_WITHDRAWAL_PROCESSOR_ROLE, + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, byte[].class); } - public RemoteFunctionCall getPaymentAccount(String card) { - final Function function = new Function(FUNC_GETPAYMENTACCOUNT, - List.of(new Address(160, card)), - List.of(new TypeReference
() { - })); - return executeRemoteCallSingleValueReturn(function, String.class); + public RemoteFunctionCall deployPaymentAccount(String owner, + String cardAddress, CardParams cardParams, BigInteger authLimitMargin_, + byte[] ownerDeployAcceptanceSignature, byte[] cardDeployAcceptanceSignature) { + final Function function = new Function( + FUNC_DEPLOYPAYMENTACCOUNT, + Arrays.asList(new org.web3j.abi.datatypes.Address(160, owner), + new org.web3j.abi.datatypes.Address(160, cardAddress), + cardParams, + new org.web3j.abi.datatypes.generated.Uint256(authLimitMargin_), + new org.web3j.abi.datatypes.DynamicBytes(ownerDeployAcceptanceSignature), + new org.web3j.abi.datatypes.DynamicBytes(cardDeployAcceptanceSignature)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); } public RemoteFunctionCall getRoleAdmin(byte[] role) { final Function function = new Function(FUNC_GETROLEADMIN, - List.of(new Bytes32(role)), - List.of(new TypeReference() { - })); + Arrays.asList(new org.web3j.abi.datatypes.generated.Bytes32(role)), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, byte[].class); } public RemoteFunctionCall getRoleMember(byte[] role, BigInteger index) { final Function function = new Function(FUNC_GETROLEMEMBER, - Arrays.asList(new Bytes32(role), - new Uint256(index)), - List.of(new TypeReference
() { - })); + Arrays.asList(new org.web3j.abi.datatypes.generated.Bytes32(role), + new org.web3j.abi.datatypes.generated.Uint256(index)), + Arrays.>asList(new TypeReference
() {})); return executeRemoteCallSingleValueReturn(function, String.class); } public RemoteFunctionCall getRoleMemberCount(byte[] role) { final Function function = new Function(FUNC_GETROLEMEMBERCOUNT, - List.of(new Bytes32(role)), - List.of(new TypeReference() { - })); + Arrays.asList(new org.web3j.abi.datatypes.generated.Bytes32(role)), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, BigInteger.class); } public RemoteFunctionCall grantRole(byte[] role, String account) { final Function function = new Function( FUNC_GRANTROLE, - Arrays.asList(new Bytes32(role), - new Address(160, account)), - Collections.emptyList()); + Arrays.asList(new org.web3j.abi.datatypes.generated.Bytes32(role), + new org.web3j.abi.datatypes.Address(160, account)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } public RemoteFunctionCall hasRole(byte[] role, String account) { final Function function = new Function(FUNC_HASROLE, - Arrays.asList(new Bytes32(role), - new Address(160, account)), - List.of(new TypeReference() { - })); + Arrays.asList(new org.web3j.abi.datatypes.generated.Bytes32(role), + new org.web3j.abi.datatypes.Address(160, account)), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, Boolean.class); } - public RemoteFunctionCall increaseVerifiedBalanceFor(String paymentAccount, BigInteger increase) { + public RemoteFunctionCall increaseVerifiedBalanceFor(String paymentAccount, + BigInteger increase) { final Function function = new Function( FUNC_INCREASEVERIFIEDBALANCEFOR, - Arrays.asList(new Address(160, paymentAccount), - new Uint256(increase)), - Collections.emptyList()); + Arrays.asList(new org.web3j.abi.datatypes.Address(160, paymentAccount), + new org.web3j.abi.datatypes.generated.Uint256(increase)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } + public RemoteFunctionCall isCardConfirmer(String account) { + final Function function = new Function(FUNC_ISCARDCONFIRMER, + Arrays.asList(new org.web3j.abi.datatypes.Address(160, account)), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, Boolean.class); + } + public RemoteFunctionCall pause() { final Function function = new Function( FUNC_PAUSE, - List.of(), - Collections.emptyList()); + Arrays.asList(), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } public RemoteFunctionCall paused() { final Function function = new Function(FUNC_PAUSED, - List.of(), - List.of(new TypeReference() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, Boolean.class); } public RemoteFunctionCall paymentAccountFactory() { final Function function = new Function(FUNC_PAYMENTACCOUNTFACTORY, - List.of(), - List.of(new TypeReference
() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference
() {})); return executeRemoteCallSingleValueReturn(function, String.class); } public RemoteFunctionCall paymentReceiver() { final Function function = new Function(FUNC_PAYMENTRECEIVER, - List.of(), - List.of(new TypeReference
() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference
() {})); return executeRemoteCallSingleValueReturn(function, String.class); } public RemoteFunctionCall paymentToken() { final Function function = new Function(FUNC_PAYMENTTOKEN, - List.of(), - List.of(new TypeReference
() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference
() {})); return executeRemoteCallSingleValueReturn(function, String.class); } - public RemoteFunctionCall processAuthorization(String card, BigInteger transactionId, BigInteger amount, byte[] otp, BigInteger otpCounter, Boolean forced) { - final Function function = new Function( - FUNC_PROCESSAUTHORIZATION, - Arrays.asList(new Address(160, card), - new Uint256(transactionId), - new Uint256(amount), - new org.web3j.abi.datatypes.generated.Bytes16(otp), - new org.web3j.abi.datatypes.generated.Uint16(otpCounter), - new Bool(forced)), - Collections.emptyList()); - return executeRemoteCallTransaction(function); - } - - public RemoteFunctionCall processAuthorizationChange(String card, BigInteger transactionId, BigInteger amount) { + public RemoteFunctionCall processAuthorizationChange(String paymentAccount, + String card, BigInteger transactionId, BigInteger amount) { final Function function = new Function( FUNC_PROCESSAUTHORIZATIONCHANGE, - Arrays.asList(new Address(160, card), - new Uint256(transactionId), - new Uint256(amount)), - Collections.emptyList()); + Arrays.asList(new org.web3j.abi.datatypes.Address(160, paymentAccount), + new org.web3j.abi.datatypes.Address(160, card), + new org.web3j.abi.datatypes.generated.Uint256(transactionId), + new org.web3j.abi.datatypes.generated.Uint256(amount)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } - public RemoteFunctionCall processAuthorizationNoOtp(String card, BigInteger transactionId, BigInteger amount, Boolean forced) { + public RemoteFunctionCall processDebt(String paymentAccount, String card, + BigInteger amount) { final Function function = new Function( - FUNC_PROCESSAUTHORIZATIONNOOTP, - Arrays.asList(new Address(160, card), - new Uint256(transactionId), - new Uint256(amount), - new Bool(forced)), - Collections.emptyList()); + FUNC_PROCESSDEBT, + Arrays.asList(new org.web3j.abi.datatypes.Address(160, paymentAccount), + new org.web3j.abi.datatypes.Address(160, card), + new org.web3j.abi.datatypes.generated.Uint256(amount)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } - public RemoteFunctionCall processPendingRefund(String card, BigInteger transactionId) { + public RemoteFunctionCall processNoConfirmationAuthorization( + String paymentAccount, String card, BigInteger transactionId, BigInteger amount, + Boolean forced) { final Function function = new Function( - FUNC_PROCESSPENDINGREFUND, - Arrays.asList(new Address(160, card), - new Uint256(transactionId)), - Collections.emptyList()); + FUNC_PROCESSNOCONFIRMATIONAUTHORIZATION, + Arrays.asList(new org.web3j.abi.datatypes.Address(160, paymentAccount), + new org.web3j.abi.datatypes.Address(160, card), + new org.web3j.abi.datatypes.generated.Uint256(transactionId), + new org.web3j.abi.datatypes.generated.Uint256(amount), + new org.web3j.abi.datatypes.Bool(forced)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } - public RemoteFunctionCall processRefund(String card, BigInteger transactionId, BigInteger refundAmount) { + public RemoteFunctionCall processOtpAuthorization(String paymentAccount, + String card, BigInteger transactionId, BigInteger amount, byte[] otp, + BigInteger otpCounter, Boolean forced) { + final Function function = new Function( + FUNC_PROCESSOTPAUTHORIZATION, + Arrays.asList(new org.web3j.abi.datatypes.Address(160, paymentAccount), + new org.web3j.abi.datatypes.Address(160, card), + new org.web3j.abi.datatypes.generated.Uint256(transactionId), + new org.web3j.abi.datatypes.generated.Uint256(amount), + new org.web3j.abi.datatypes.generated.Bytes16(otp), + new org.web3j.abi.datatypes.generated.Uint16(otpCounter), + new org.web3j.abi.datatypes.Bool(forced)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteFunctionCall processRefund(String paymentAccount, String card, + BigInteger transactionId, BigInteger refundAmount) { final Function function = new Function( FUNC_PROCESSREFUND, - Arrays.asList(new Address(160, card), - new Uint256(transactionId), - new Uint256(refundAmount)), - Collections.emptyList()); + Arrays.asList(new org.web3j.abi.datatypes.Address(160, paymentAccount), + new org.web3j.abi.datatypes.Address(160, card), + new org.web3j.abi.datatypes.generated.Uint256(transactionId), + new org.web3j.abi.datatypes.generated.Uint256(refundAmount)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } public RemoteFunctionCall processRefundCallback() { final Function function = new Function( FUNC_PROCESSREFUNDCALLBACK, - List.of(), - Collections.emptyList()); + Arrays.asList(), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } - public RemoteFunctionCall processSettlement(String card, BigInteger transactionId, BigInteger amount) { + public RemoteFunctionCall processSettlement(String paymentAccount, + String card, BigInteger transactionId, BigInteger amount) { final Function function = new Function( FUNC_PROCESSSETTLEMENT, - Arrays.asList(new Address(160, card), - new Uint256(transactionId), - new Uint256(amount)), - Collections.emptyList()); + Arrays.asList(new org.web3j.abi.datatypes.Address(160, paymentAccount), + new org.web3j.abi.datatypes.Address(160, card), + new org.web3j.abi.datatypes.generated.Uint256(transactionId), + new org.web3j.abi.datatypes.generated.Uint256(amount)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteFunctionCall processSignatureAuthorization( + String paymentAccount, String card, BigInteger transactionId, BigInteger amount, + byte[] signature, Boolean forced) { + final Function function = new Function( + FUNC_PROCESSSIGNATUREAUTHORIZATION, + Arrays.asList(new org.web3j.abi.datatypes.Address(160, paymentAccount), + new org.web3j.abi.datatypes.Address(160, card), + new org.web3j.abi.datatypes.generated.Uint256(transactionId), + new org.web3j.abi.datatypes.generated.Uint256(amount), + new org.web3j.abi.datatypes.DynamicBytes(signature), + new org.web3j.abi.datatypes.Bool(forced)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteFunctionCall processUnsettledTransaction(String paymentAccount, + String card, BigInteger transactionId) { + final Function function = new Function( + FUNC_PROCESSUNSETTLEDTRANSACTION, + Arrays.asList(new org.web3j.abi.datatypes.Address(160, paymentAccount), + new org.web3j.abi.datatypes.Address(160, card), + new org.web3j.abi.datatypes.generated.Uint256(transactionId)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteFunctionCall processWithdrawal(String paymentAccount) { + final Function function = new Function( + FUNC_PROCESSWITHDRAWAL, + Arrays.asList(new org.web3j.abi.datatypes.Address(160, paymentAccount)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } public RemoteFunctionCall refundAccount() { final Function function = new Function(FUNC_REFUNDACCOUNT, - List.of(), - List.of(new TypeReference
() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference
() {})); return executeRemoteCallSingleValueReturn(function, String.class); } - public RemoteFunctionCall renounceRole(byte[] role, String callerConfirmation) { + public RemoteFunctionCall renounceRole(byte[] role, + String callerConfirmation) { final Function function = new Function( FUNC_RENOUNCEROLE, - Arrays.asList(new Bytes32(role), - new Address(160, callerConfirmation)), - Collections.emptyList()); + Arrays.asList(new org.web3j.abi.datatypes.generated.Bytes32(role), + new org.web3j.abi.datatypes.Address(160, callerConfirmation)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } public RemoteFunctionCall revokeRole(byte[] role, String account) { final Function function = new Function( FUNC_REVOKEROLE, - Arrays.asList(new Bytes32(role), - new Address(160, account)), - Collections.emptyList()); - return executeRemoteCallTransaction(function); - } - - public RemoteFunctionCall savePendingRefund(String card, BigInteger transactionId, BigInteger amount) { - final Function function = new Function( - FUNC_SAVEPENDINGREFUND, - Arrays.asList(new Address(160, card), - new Uint256(transactionId), - new Uint256(amount)), - Collections.emptyList()); + Arrays.asList(new org.web3j.abi.datatypes.generated.Bytes32(role), + new org.web3j.abi.datatypes.Address(160, account)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } public RemoteFunctionCall securityDelay() { final Function function = new Function(FUNC_SECURITYDELAY, - List.of(), - List.of(new TypeReference() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, BigInteger.class); } - public RemoteFunctionCall setFixedFee(BigInteger fixedFee_) { + public RemoteFunctionCall setAuthLimitMarginFor(String paymentAccount, + BigInteger authLimitMargin) { final Function function = new Function( - FUNC_SETFIXEDFEE, - List.of(new Uint256(fixedFee_)), - Collections.emptyList()); - return executeRemoteCallTransaction(function); - } - - public RemoteFunctionCall setPaymentAccount(String card, String paymentAccount) { - final Function function = new Function( - FUNC_SETPAYMENTACCOUNT, - Arrays.asList(new Address(160, card), - new Address(160, paymentAccount)), - Collections.emptyList()); + FUNC_SETAUTHLIMITMARGINFOR, + Arrays.asList(new org.web3j.abi.datatypes.Address(160, paymentAccount), + new org.web3j.abi.datatypes.generated.Uint256(authLimitMargin)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } public RemoteFunctionCall setPaymentReceiver(String paymentReceiver_) { final Function function = new Function( FUNC_SETPAYMENTRECEIVER, - List.of(new Address(160, paymentReceiver_)), - Collections.emptyList()); + Arrays.asList(new org.web3j.abi.datatypes.Address(160, paymentReceiver_)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } public RemoteFunctionCall setRefundAccount(String refundAccount_) { final Function function = new Function( FUNC_SETREFUNDACCOUNT, - List.of(new Address(160, refundAccount_)), - Collections.emptyList()); + Arrays.asList(new org.web3j.abi.datatypes.Address(160, refundAccount_)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } public RemoteFunctionCall setSecurityDelay(BigInteger securityDelay_) { final Function function = new Function( FUNC_SETSECURITYDELAY, - List.of(new Uint256(securityDelay_)), - Collections.emptyList()); + Arrays.asList(new org.web3j.abi.datatypes.generated.Uint256(securityDelay_)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } - public RemoteFunctionCall setSettlementPeriod(BigInteger settlementPeriod_) { - final Function function = new Function( - FUNC_SETSETTLEMENTPERIOD, - List.of(new Uint256(settlementPeriod_)), - Collections.emptyList()); - return executeRemoteCallTransaction(function); - } - - public RemoteFunctionCall setVerifiedBalanceFor(String paymentAccount, BigInteger verifiedBalance) { + public RemoteFunctionCall setVerifiedBalanceFor(String paymentAccount, + BigInteger verifiedBalance) { final Function function = new Function( FUNC_SETVERIFIEDBALANCEFOR, - Arrays.asList(new Address(160, paymentAccount), - new Uint256(verifiedBalance)), - Collections.emptyList()); + Arrays.asList(new org.web3j.abi.datatypes.Address(160, paymentAccount), + new org.web3j.abi.datatypes.generated.Uint256(verifiedBalance)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } - public RemoteFunctionCall settlementPeriod() { - final Function function = new Function(FUNC_SETTLEMENTPERIOD, - List.of(), - List.of(new TypeReference() { - })); - return executeRemoteCallSingleValueReturn(function, BigInteger.class); - } - public RemoteFunctionCall supportsInterface(byte[] interfaceId) { final Function function = new Function(FUNC_SUPPORTSINTERFACE, - List.of(new Bytes4(interfaceId)), - List.of(new TypeReference() { - })); + Arrays.asList(new org.web3j.abi.datatypes.generated.Bytes4(interfaceId)), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, Boolean.class); } public RemoteFunctionCall unpause() { final Function function = new Function( FUNC_UNPAUSE, - List.of(), - Collections.emptyList()); + Arrays.asList(), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } - public RemoteFunctionCall writeOffDebt(String card, BigInteger amount) { + public RemoteFunctionCall writeOffDebt(String paymentAccount, String card, + BigInteger amount) { final Function function = new Function( FUNC_WRITEOFFDEBT, - Arrays.asList(new Address(160, card), - new Uint256(amount)), - Collections.emptyList()); + Arrays.asList(new org.web3j.abi.datatypes.Address(160, paymentAccount), + new org.web3j.abi.datatypes.Address(160, card), + new org.web3j.abi.datatypes.generated.Uint256(amount)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } + @Deprecated + public static TangemBridgeProcessor load(String contractAddress, Web3j web3j, + Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + return new TangemBridgeProcessor(contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + @Deprecated + public static TangemBridgeProcessor load(String contractAddress, Web3j web3j, + TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) { + return new TangemBridgeProcessor(contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + public static TangemBridgeProcessor load(String contractAddress, Web3j web3j, + Credentials credentials, ContractGasProvider contractGasProvider) { + return new TangemBridgeProcessor(contractAddress, web3j, credentials, contractGasProvider); + } + + public static TangemBridgeProcessor load(String contractAddress, Web3j web3j, + TransactionManager transactionManager, ContractGasProvider contractGasProvider) { + return new TangemBridgeProcessor(contractAddress, web3j, transactionManager, contractGasProvider); + } + + public static RemoteCall deploy(Web3j web3j, Credentials credentials, + ContractGasProvider contractGasProvider, String paymentReceiver_, String refundAccount_, + String paymentAccountFactory_, String paymentToken_, BigInteger securityDelay_) { + String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(new org.web3j.abi.datatypes.Address(160, paymentReceiver_), + new org.web3j.abi.datatypes.Address(160, refundAccount_), + new org.web3j.abi.datatypes.Address(160, paymentAccountFactory_), + new org.web3j.abi.datatypes.Address(160, paymentToken_), + new org.web3j.abi.datatypes.generated.Uint256(securityDelay_))); + return deployRemoteCall(TangemBridgeProcessor.class, web3j, credentials, contractGasProvider, getDeploymentBinary(), encodedConstructor); + } + + public static RemoteCall deploy(Web3j web3j, + TransactionManager transactionManager, ContractGasProvider contractGasProvider, + String paymentReceiver_, String refundAccount_, String paymentAccountFactory_, + String paymentToken_, BigInteger securityDelay_) { + String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(new org.web3j.abi.datatypes.Address(160, paymentReceiver_), + new org.web3j.abi.datatypes.Address(160, refundAccount_), + new org.web3j.abi.datatypes.Address(160, paymentAccountFactory_), + new org.web3j.abi.datatypes.Address(160, paymentToken_), + new org.web3j.abi.datatypes.generated.Uint256(securityDelay_))); + return deployRemoteCall(TangemBridgeProcessor.class, web3j, transactionManager, contractGasProvider, getDeploymentBinary(), encodedConstructor); + } + + @Deprecated + public static RemoteCall deploy(Web3j web3j, Credentials credentials, + BigInteger gasPrice, BigInteger gasLimit, String paymentReceiver_, + String refundAccount_, String paymentAccountFactory_, String paymentToken_, + BigInteger securityDelay_) { + String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(new org.web3j.abi.datatypes.Address(160, paymentReceiver_), + new org.web3j.abi.datatypes.Address(160, refundAccount_), + new org.web3j.abi.datatypes.Address(160, paymentAccountFactory_), + new org.web3j.abi.datatypes.Address(160, paymentToken_), + new org.web3j.abi.datatypes.generated.Uint256(securityDelay_))); + return deployRemoteCall(TangemBridgeProcessor.class, web3j, credentials, gasPrice, gasLimit, getDeploymentBinary(), encodedConstructor); + } + + @Deprecated + public static RemoteCall deploy(Web3j web3j, + TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit, + String paymentReceiver_, String refundAccount_, String paymentAccountFactory_, + String paymentToken_, BigInteger securityDelay_) { + String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(new org.web3j.abi.datatypes.Address(160, paymentReceiver_), + new org.web3j.abi.datatypes.Address(160, refundAccount_), + new org.web3j.abi.datatypes.Address(160, paymentAccountFactory_), + new org.web3j.abi.datatypes.Address(160, paymentToken_), + new org.web3j.abi.datatypes.generated.Uint256(securityDelay_))); + return deployRemoteCall(TangemBridgeProcessor.class, web3j, transactionManager, gasPrice, gasLimit, getDeploymentBinary(), encodedConstructor); + } + + public static void linkLibraries(List references) { + librariesLinkedBinary = linkBinaryWithReferences(BINARY, references); + } + + private static String getDeploymentBinary() { + if (librariesLinkedBinary != null) { + return librariesLinkedBinary; + } else { + return BINARY; + } + } + + public static class OtpState extends StaticStruct { + public byte[] otp; + + public BigInteger counter; + + public OtpState(byte[] otp, BigInteger counter) { + super(new org.web3j.abi.datatypes.generated.Bytes16(otp), + new org.web3j.abi.datatypes.generated.Uint16(counter)); + this.otp = otp; + this.counter = counter; + } + + public OtpState(Bytes16 otp, Uint16 counter) { + super(otp, counter); + this.otp = otp.getValue(); + this.counter = counter.getValue(); + } + } + + public static class LimitsParams extends StaticStruct { + public BigInteger singleTransactionLimit; + + public BigInteger spendLimit; + + public BigInteger noConfirmationSpendLimit; + + public BigInteger spendLimitsPeriod; + + public LimitsParams(BigInteger singleTransactionLimit, BigInteger spendLimit, + BigInteger noConfirmationSpendLimit, BigInteger spendLimitsPeriod) { + super(new org.web3j.abi.datatypes.generated.Uint256(singleTransactionLimit), + new org.web3j.abi.datatypes.generated.Uint256(spendLimit), + new org.web3j.abi.datatypes.generated.Uint256(noConfirmationSpendLimit), + new org.web3j.abi.datatypes.generated.Uint256(spendLimitsPeriod)); + this.singleTransactionLimit = singleTransactionLimit; + this.spendLimit = spendLimit; + this.noConfirmationSpendLimit = noConfirmationSpendLimit; + this.spendLimitsPeriod = spendLimitsPeriod; + } + + public LimitsParams(Uint256 singleTransactionLimit, Uint256 spendLimit, + Uint256 noConfirmationSpendLimit, Uint256 spendLimitsPeriod) { + super(singleTransactionLimit, spendLimit, noConfirmationSpendLimit, spendLimitsPeriod); + this.singleTransactionLimit = singleTransactionLimit.getValue(); + this.spendLimit = spendLimit.getValue(); + this.noConfirmationSpendLimit = noConfirmationSpendLimit.getValue(); + this.spendLimitsPeriod = spendLimitsPeriod.getValue(); + } + } + + public static class CardParams extends StaticStruct { + public Boolean isOwner; + + public OtpState otpState; + + public LimitsParams limitsParams; + + public CardParams(Boolean isOwner, OtpState otpState, LimitsParams limitsParams) { + super(new org.web3j.abi.datatypes.Bool(isOwner), + otpState, + limitsParams); + this.isOwner = isOwner; + this.otpState = otpState; + this.limitsParams = limitsParams; + } + + public CardParams(Bool isOwner, OtpState otpState, LimitsParams limitsParams) { + super(isOwner, otpState, limitsParams); + this.isOwner = isOwner.getValue(); + this.otpState = otpState; + this.limitsParams = limitsParams; + } + } + + public static class AuthLimitMarginSetForEventResponse extends BaseEventResponse { + public String paymentAccount; + + public BigInteger authLimitMargin; + } + public static class AuthorizationChangeProcessedEventResponse extends BaseEventResponse { + public String paymentAccount; + public String card; public BigInteger transactionId; public BigInteger amount; - - public BigInteger fee; } public static class AuthorizationProcessedEventResponse extends BaseEventResponse { + public String paymentAccount; + public String card; public BigInteger transactionId; public BigInteger amount; - - public BigInteger fee; } - public static class DebtWriteOffProcessedEventResponse extends BaseEventResponse { + public static class DebtProcessedEventResponse extends BaseEventResponse { + public String paymentAccount; + public String card; public BigInteger amount; } - public static class FixedFeeSetEventResponse extends BaseEventResponse { - public BigInteger fixedFee; + public static class DebtWriteOffProcessedEventResponse extends BaseEventResponse { + public String paymentAccount; + + public String card; + + public BigInteger amount; } public static class PausedEventResponse extends BaseEventResponse { public String account; } - public static class PaymentAccountSetEventResponse extends BaseEventResponse { - public String card; + public static class PaymentAccountDeployedEventResponse extends BaseEventResponse { + public String owner; + + public String cardAddress; public String paymentAccount; } @@ -1400,19 +1621,13 @@ class TangemBridgeProcessor extends Contract { public String paymentReceiver; } - public static class PendingRefundProcessedEventResponse extends BaseEventResponse { - public String card; - - public BigInteger transactionId; - - public BigInteger amount; - } - public static class RefundAccountSetEventResponse extends BaseEventResponse { public String refundAccount; } public static class RefundProcessedEventResponse extends BaseEventResponse { + public String paymentAccount; + public String card; public BigInteger transactionId; @@ -1444,14 +1659,6 @@ class TangemBridgeProcessor extends Contract { public String sender; } - public static class SaveRefundProcessedEventResponse extends BaseEventResponse { - public String card; - - public BigInteger transactionId; - - public BigInteger amount; - } - public static class SecurityDelaySetEventResponse extends BaseEventResponse { public BigInteger securityDelay; } @@ -1461,19 +1668,27 @@ class TangemBridgeProcessor extends Contract { } public static class SettlementProcessedEventResponse extends BaseEventResponse { + public String paymentAccount; + public String card; public BigInteger transactionId; public BigInteger amount; - - public BigInteger fee; } public static class UnpausedEventResponse extends BaseEventResponse { public String account; } + public static class UnsettledTransactionProcessedEventResponse extends BaseEventResponse { + public String paymentAccount; + + public String card; + + public BigInteger transactionId; + } + public static class VerifiedBalanceIncreasedForEventResponse extends BaseEventResponse { public String paymentAccount; @@ -1485,4 +1700,8 @@ class TangemBridgeProcessor extends Contract { public BigInteger verifiedBalance; } -} + + public static class WithdrawalProcessedEventResponse extends BaseEventResponse { + public String paymentAccount; + } +} \ No newline at end of file diff --git a/libs/visa/src/main/java/com/tangem/lib/visa/TangemPaymentAccount.java b/libs/visa/src/main/java/com/tangem/lib/visa/TangemPaymentAccount.java index 834d85f3c2..df19c6cee9 100644 --- a/libs/visa/src/main/java/com/tangem/lib/visa/TangemPaymentAccount.java +++ b/libs/visa/src/main/java/com/tangem/lib/visa/TangemPaymentAccount.java @@ -1,10 +1,30 @@ package com.tangem.lib.visa; +import io.reactivex.Flowable; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.Callable; import org.web3j.abi.EventEncoder; import org.web3j.abi.FunctionEncoder; import org.web3j.abi.TypeReference; -import org.web3j.abi.datatypes.*; -import org.web3j.abi.datatypes.generated.*; +import org.web3j.abi.datatypes.Address; +import org.web3j.abi.datatypes.Bool; +import org.web3j.abi.datatypes.DynamicArray; +import org.web3j.abi.datatypes.DynamicBytes; +import org.web3j.abi.datatypes.Event; +import org.web3j.abi.datatypes.Function; +import org.web3j.abi.datatypes.StaticStruct; +import org.web3j.abi.datatypes.Type; +import org.web3j.abi.datatypes.Utf8String; +import org.web3j.abi.datatypes.generated.Bytes1; +import org.web3j.abi.datatypes.generated.Bytes16; +import org.web3j.abi.datatypes.generated.Bytes32; +import org.web3j.abi.datatypes.generated.Uint16; +import org.web3j.abi.datatypes.generated.Uint256; +import org.web3j.abi.datatypes.generated.Uint64; import org.web3j.crypto.Credentials; import org.web3j.protocol.Web3j; import org.web3j.protocol.core.DefaultBlockParameter; @@ -14,36 +34,36 @@ import org.web3j.protocol.core.methods.request.EthFilter; import org.web3j.protocol.core.methods.response.BaseEventResponse; import org.web3j.protocol.core.methods.response.Log; import org.web3j.protocol.core.methods.response.TransactionReceipt; -import org.web3j.tuples.generated.Tuple3; +import org.web3j.tuples.generated.Tuple4; +import org.web3j.tuples.generated.Tuple5; import org.web3j.tuples.generated.Tuple7; import org.web3j.tx.Contract; import org.web3j.tx.TransactionManager; import org.web3j.tx.gas.ContractGasProvider; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.Callable; - -import io.reactivex.Flowable; - /** *

Auto generated code. *

Do not modify! *

Please use the web3j command line tools, - * or the org.web3j.codegen.SolidityFunctionWrapperGenerator in the - * codegen module to update. + * or the org.web3j.codegen.SolidityFunctionWrapperGenerator in the + * codegen module to update. * - *

Generated with web3j version 1.5.2. + *

Generated with web3j version 1.6.1. */ @SuppressWarnings("rawtypes") -class TangemPaymentAccount extends Contract { - public static final String BINARY = "60c06040523060a0523480156200001557600080fd5b5060405162005aa938038062005aa983398101604081905262000038916200010a565b6001600160a01b0381166080526200004f62000056565b506200013c565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff1615620000a75760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b0390811614620001075780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b6000602082840312156200011d57600080fd5b81516001600160a01b03811681146200013557600080fd5b9392505050565b60805160a05161592b6200017e600039600081816132fe0152818161332701526135880152600081816104d301528181610578015261290d015261592b6000f3fe6080604052600436106102c85760003560e01c806386489ba911610175578063c470d703116100dc578063df7727b411610095578063e3dbffd51161006f578063e3dbffd514610a40578063e4d7ddb914610a60578063e6e268f414610a80578063f89db45714610a9557600080fd5b8063df7727b4146102f5578063e1a8eafd146109b2578063e37b8154146109d257600080fd5b8063c470d703146108da578063c81656c81461090e578063ce1b1d431461093b578063d47ae89c1461095b578063dbed8faa14610970578063dcab7e501461099057600080fd5b8063a789457d1161012e578063a789457d1461077b578063ad3cb1cc14610827578063b4d02d0d14610865578063b9603bdf14610885578063be69191d146108a5578063c45a0155146108ba57600080fd5b806386489ba9146106c657806386f15d09146106e65780638bbe11af146106fb5780638c3b2a9b1461071b5780638da5cb5b1461073b578063a075b7c71461075b57600080fd5b80633c1a5012116102345780636b2a3830116101ed5780637da0a877116101c75780637da0a87714610569578063806679e41461059c57806384b0196e146105bc578063860aefcf146105e457600080fd5b80636b2a3830146105135780636b4943a7146105335780637b1039991461054957600080fd5b80633c1a501214610439578063456575e51461045957806346236eb9146104795780634f1ef2861461048e57806352d1902d146104a1578063572b6c05146104b657600080fd5b806322611280116102865780632261128014610377578063229865d11461038c5780633013ce29146103ac578063309433ba146103e457806334284dfb1461040457806335ba9af81461042457600080fd5b806274f356146102cd57806301e948ff146102f55780630381b4dd1461030a5780630f1071be1461032c57806319cdeb6f146103415780631f852f4b14610357575b600080fd5b3480156102d957600080fd5b506102e2610ab5565b6040519081526020015b60405180910390f35b34801561030157600080fd5b506102e2610acf565b34801561031657600080fd5b5061032a610325366004614b0d565b610ae0565b005b34801561033857600080fd5b506102e2610dde565b34801561034d57600080fd5b506102e260065481565b34801561036357600080fd5b5061032a610372366004614b8d565b610e63565b34801561038357600080fd5b5061032a610fa7565b34801561039857600080fd5b5061032a6103a7366004614be2565b611034565b3480156103b857600080fd5b506000546103cc906001600160a01b031681565b6040516001600160a01b0390911681526020016102ec565b3480156103f057600080fd5b5061032a6103ff366004614c2a565b6110cb565b34801561041057600080fd5b5061032a61041f366004614cb0565b611337565b34801561043057600080fd5b506102e26113fd565b34801561044557600080fd5b5061032a610454366004614d0b565b611490565b34801561046557600080fd5b5061032a610474366004614b0d565b61151c565b34801561048557600080fd5b50601c546102e2565b61032a61049c366004614d3e565b6115bc565b3480156104ad57600080fd5b506102e26115db565b3480156104c257600080fd5b506105036104d1366004614d0b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b60405190151581526020016102ec565b34801561051f57600080fd5b5061032a61052e366004614be2565b6115f8565b34801561053f57600080fd5b506102e260075481565b34801561055557600080fd5b506002546103cc906001600160a01b031681565b34801561057557600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103cc565b3480156105a857600080fd5b5061032a6105b7366004614e02565b611749565b3480156105c857600080fd5b506105d16117ed565b6040516102ec9796959493929190614e8b565b3480156105f057600080fd5b506040805160a08082018352600d54825282518084018452600e548152600f546020828101919091528084019190915283518085018552601054815260115481830152838501528351808201855260125481526060808501919091526013546080808601919091528551938401865260145484528551808701875260155481526016548185015284840152855180870187526017548152601854818501528487015285519283019095526019548252820152601a5492810192909252601b546106b7929083565b6040516102ec93929190614f6c565b3480156106d257600080fd5b5061032a6106e1366004614f97565b611899565b3480156106f257600080fd5b50610503611a66565b34801561070757600080fd5b5061032a610716366004614be2565b611a90565b34801561072757600080fd5b5061032a610736366004614ff0565b611ba9565b34801561074757600080fd5b506004546103cc906001600160a01b031681565b34801561076757600080fd5b5061032a610776366004615023565b611cf8565b34801561078757600080fd5b506040805180820182526008546001600160a01b039081168252825180840184526009546001600160801b0319608082811b8216845261ffff600160801b9384900481166020868101919091528088019590955287518089018952600a5490961686528751808901909852600b549182901b9092168752919091041684820152810192909252600c54610818929083565b6040516102ec93929190615086565b34801561083357600080fd5b50610858604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516102ec91906150af565b34801561087157600080fd5b5061032a610880366004614be2565b611de0565b34801561089157600080fd5b5061032a6108a0366004614be2565b611ee3565b3480156108b157600080fd5b5061050361201c565b3480156108c657600080fd5b506001546103cc906001600160a01b031681565b3480156108e657600080fd5b507f3fc394ec90f88dd7e18c46ffeef55f1b6719a2027f4ae9fbc4ab118271891200546102e2565b34801561091a57600080fd5b506102e2610929366004614be2565b6000908152601d602052604090205490565b34801561094757600080fd5b506003546103cc906001600160a01b031681565b34801561096757600080fd5b506102e2612044565b34801561097c57600080fd5b5061032a61098b366004614be2565b6120c8565b34801561099c57600080fd5b506000805160206154fc833981519152546102e2565b3480156109be57600080fd5b5061032a6109cd366004614d0b565b612127565b3480156109de57600080fd5b50610a1b6109ed366004614be2565b600560205260009081526040902080546001909101546001600160801b03811690600160801b900460ff1683565b604080519384526001600160801b0390921660208401521515908201526060016102ec565b348015610a4c57600080fd5b5061032a610a5b366004614be2565b6122c6565b348015610a6c57600080fd5b5061032a610a7b366004614b0d565b6124ac565b348015610a8c57600080fd5b506102e261265c565b348015610aa157600080fd5b5061032a610ab0366004614be2565b612673565b6000806000805160206154dc8339815191525b5492915050565b6000610adb600061284d565b905090565b6003546001600160a01b0316610af4612909565b6001600160a01b0316146040518060600160405280603381526020016153166033913990610b3e5760405162461bcd60e51b8152600401610b3591906150af565b60405180910390fd5b50610b488161295b565b60008281526005602052604081205490818311610b7b575081808203828214610b7557610b75858261299b565b50610bff565b50806000610b89600d6129e0565b8054909150600081851015610bbf57610bae858303610ba98560006129ff565b612a6b565b9050610bbc81610ba9610acf565b90505b8015610be7576000610bd382878903612a6b565b948501949050610be584826000612a83565b505b838603868514610bfa57610bfa81612aaa565b505050505b8160075410156040518060600160405280602981526020016158226029913990610c3c5760405162461bcd60e51b8152600401610b3591906150af565b50600780548390039055600084815260056020908152604080832092835560019290920180546001600160881b0319169055600354825163659bf9d960e11b81529251610cdf936001600160a01b039092169263cb37f3b292600480820193918290030181865afa158015610cb5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd991906150c2565b82612b0b565b604080518481526020810183905285917fa06caae8c696e5deb33f685024044b74125cb932e11521aef47de748321657c4910160405180910390a26000546040516370a0823160e01b81523060048201527f273f30c859762d267fd40559825ed2fa0f467908c92843dfd0184b9d577dc082916001600160a01b0316906370a0823190602401602060405180830381865afa158015610d82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610da691906150df565b600754610db1610ab5565b601c546040805194855260208501939093529183015260608201526080015b60405180910390a150505050565b6000610adb600360009054906101000a90046001600160a01b03166001600160a01b0316630f1071be6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e5a91906150df565b6283d600612a6b565b6004546001600160a01b0316610e77612909565b6001600160a01b03161480610eae5750610e916008612c1b565b546001600160a01b0316610ea3612909565b6001600160a01b0316145b6040518060600160405280602f815260200161589e602f913990610ee55760405162461bcd60e51b8152600401610b3591906150af565b50610ef1838383612c36565b600480546001600160a01b038581166001600160a01b0319831681178455600254604051635cd2673760e01b815293831694840185905260248401919091521690635cd2673790604401600060405180830381600087803b158015610f5557600080fd5b505af1158015610f69573d6000803e3d6000fd5b50506040516001600160a01b03871681527f50146d0e3c60aa1d17a70635b05494f864e86144a2201275021014fbf08bafe292506020019050610dd0565b6004546001600160a01b0316610fbb612909565b6001600160a01b03161480610ff25750610fd56008612c1b565b546001600160a01b0316610fe7612909565b6001600160a01b0316145b6040518060600160405280602f815260200161589e602f9139906110295760405162461bcd60e51b8152600401610b3591906150af565b50611032612d2a565b565b6004546001600160a01b0316611048612909565b6001600160a01b0316148061107f57506110626008612c1b565b546001600160a01b0316611074612909565b6001600160a01b0316145b6040518060600160405280602f815260200161589e602f9139906110b65760405162461bcd60e51b8152600401610b3591906150af565b506110c8816110c3612044565b612d7b565b50565b6004546001600160a01b03166110df612909565b6001600160a01b0316148061111657506110f96008612c1b565b546001600160a01b031661110b612909565b6001600160a01b0316145b6040518060600160405280602f815260200161589e602f91399061114d5760405162461bcd60e51b8152600401610b3591906150af565b50611159858383612c36565b600c541561122857600a546040805180820182526001600160a01b03888116825282518084019093526001600160801b03198816835261ffff87166020848101919091528201929092529116906111bb906111b2612044565b60089190612e79565b600254604051630747fc3760e41b81526001600160a01b03838116600483015288811660248301529091169063747fc37090604401600060405180830381600087803b15801561120a57600080fd5b505af115801561121e573d6000803e3d6000fd5b50505050506112db565b61127b6040518060400160405280876001600160a01b031681526020016040518060400160405280886001600160801b03191681526020018761ffff16815250815250600861302090919063ffffffff16565b60025460405163346b888d60e11b81526001600160a01b038781166004830152909116906368d7111a90602401600060405180830381600087803b1580156112c257600080fd5b505af11580156112d6573d6000803e3d6000fd5b505050505b604080516001600160a01b03871681526001600160801b03198616602082015261ffff85168183015290517fae81d31085749debb22edb9a09f263e50cf6047cfc57ec741c07ce62b1121b9a9181900360600190a15050505050565b6003546001600160a01b031661134b612909565b6001600160a01b031614604051806060016040528060338152602001615316603391399061138c5760405162461bcd60e51b8152600401610b3591906150af565b50600161139a8484846130c1565b6113a68686848461311d565b604080518681526001600160801b03198616602082015261ffff851681830152905187917faab1db26b8ce0ed14d67fd3d8eab92617f4caf4134148122ad6f2a4e20068df7919081900360600190a2505050505050565b600080546040516370a0823160e01b815230600482015282916001600160a01b0316906370a0823190602401602060405180830381865afa158015611446573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146a91906150df565b905060075481101561147d57600061148a565b60075461148a908261510e565b91505090565b6004546001600160a01b03166114a4612909565b6001600160a01b031614806114db57506114be6008612c1b565b546001600160a01b03166114d0612909565b6001600160a01b0316145b6040518060600160405280602f815260200161589e602f9139906115125760405162461bcd60e51b8152600401610b3591906150af565b506110c881613186565b6003546001600160a01b0316611530612909565b6001600160a01b03161460405180606001604052806033815260200161531660339139906115715760405162461bcd60e51b8152600401610b3591906150af565b5061157e601c8383613274565b817fea92e836c1b642a333bb58b44d5f13c5a066c5b0f35b8d6da5032af605c9e031826040516115b091815260200190565b60405180910390a25050565b6115c46132f3565b6115cd82613398565b6115d782826134c0565b5050565b60006115e561357d565b506000805160206155cf83398151915290565b6003546001600160a01b031661160c612909565b6001600160a01b031614604051806060016040528060338152602001615316603391399061164d5760405162461bcd60e51b8152600401610b3591906150af565b5060008160065461165e9190615121565b6000546040516370a0823160e01b81523060048201529192506001600160a01b0316906370a0823190602401602060405180830381865afa1580156116a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116cb91906150df565b8111156040518060600160405280603781526020016153c760379139906117055760405162461bcd60e51b8152600401610b3591906150af565b50600681905560408051838152602081018390527fd6004694c2f543b69302481de26731f63c1d41062795b5366d8ca20fd3e3d6d391015b60405180910390a15050565b6003546001600160a01b031661175d612909565b6001600160a01b031614604051806060016040528060338152602001615316603391399061179e5760405162461bcd60e51b8152600401610b3591906150af565b5060006117ad8484848461311d565b837f5e1266400272ee17509f7d7edb190c0fa83572f90677ee6a3bbfac22bf1f679d846040516117df91815260200190565b60405180910390a250505050565b60006060808280808381600080516020615541833981519152805490915015801561181a57506001810154155b61185e5760405162461bcd60e51b81526020600482015260156024820152741152540dcc4c8e88155b9a5b9a5d1a585b1a5e9959605a1b6044820152606401610b35565b6118666135c6565b61186e613689565b60408051600080825260208201909252600f60f81b9c939b5091995046985030975095509350915050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff166000811580156118df5750825b905060008267ffffffffffffffff1660011480156118fc5750303b155b90508115801561190a575080155b156119285760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561195257845460ff60401b1916600160401b1785555b61195a6136c8565b6119626136c8565b6119b16040518060400160405280601481526020017315185b99d95b54185e5b595b9d1058d8dbdd5b9d60621b815250604051806040016040528060018152602001603160f81b8152506136d0565b6119b96136c8565b6119c1612909565b600180546001600160a01b03199081166001600160a01b03938416179091556004805482168e841617905560028054909116918c16919091179055611a13611a0b8a8a8a8a6136e2565b600d90613780565b8315611a5957845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050505050565b6000805160206154fc8339815191525460009060008051602061549c83398151915290151561148a565b6000818152600560205260409020600181015490546001600160801b0390911690611ab9610dde565b611ac39083615121565b42116040518060600160405280602b8152602001615349602b913990611afc5760405162461bcd60e51b8152600401610b3591906150af565b508060075410156040518060600160405280602981526020016158226029913990611b3a5760405162461bcd60e51b8152600401610b3591906150af565b5060078054829003905560008381526005602052604080822091825560019190910180546001600160881b03191690555183907f056bed1bad5d90aa1df671c8d28b1bbb82ff67fd545f804e63cd261140b11f7b90611b9c9084815260200190565b60405180910390a2505050565b6004546001600160a01b0316611bbd612909565b6001600160a01b03161480611bf45750611bd76008612c1b565b546001600160a01b0316611be9612909565b6001600160a01b0316145b6040518060600160405280602f815260200161589e602f913990611c2b5760405162461bcd60e51b8152600401610b3591906150af565b50600c5415156040518060600160405280603181526020016157c66031913990611c685760405162461bcd60e51b8152600401610b3591906150af565b50604080518082018252600a546001600160a01b0316815281518083019092526001600160801b03198416825261ffff8316602083810191909152810191909152611cb5906111b2612044565b604080516001600160801b03198416815261ffff831660208201527fc50d2cc66f62a75104edeabfbcedb2a37ebd1cb8ce0b873ec3afa504e8bb1480910161173d565b6004546001600160a01b0316611d0c612909565b6001600160a01b03161480611d435750611d266008612c1b565b546001600160a01b0316611d38612909565b6001600160a01b0316145b6040518060600160405280602f815260200161589e602f913990611d7a5760405162461bcd60e51b8152600401610b3591906150af565b50611d9b611d8a858585856136e2565b611d92612044565b600d919061380c565b6040805185815260208101859052908101839052606081018290527ffc3ccf3ca5a38fad8786ed39386de19cb574b06205422992c583e4753aa6268f90608001610dd0565b6004546001600160a01b0316611df4612909565b6001600160a01b03161480611e2b5750611e0e6008612c1b565b546001600160a01b0316611e20612909565b6001600160a01b0316145b6040518060600160405280602f815260200161589e602f913990611e625760405162461bcd60e51b8152600401610b3591906150af565b506110c881600360009054906101000a90046001600160a01b03166001600160a01b031663cb37f3b26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611eba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ede91906150c2565b6138fa565b6003546001600160a01b0316611ef7612909565b6001600160a01b0316146040518060600160405280603381526020016153166033913990611f385760405162461bcd60e51b8152600401610b3591906150af565b506000546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015611f81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fa591906150df565b8111156040518060600160405280603781526020016153c76037913990611fdf5760405162461bcd60e51b8152600401610b3591906150af565b5060068190556040518181527f321b800465e47508430424e6c089344256e17f9a5b0b43c751dffbdfd3930263906020015b60405180910390a150565b600060008051602061549c83398151915261148a6000805160206154fc833981519152613a4c565b6000610adb600360009054906101000a90046001600160a01b03166001600160a01b031663d47ae89c6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561209c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120c091906150df565b610e10612a6b565b6003546001600160a01b03166120dc612909565b6001600160a01b031614604051806060016040528060338152602001615316603391399061211d5760405162461bcd60e51b8152600401610b3591906150af565b506110c881613ab4565b6004546001600160a01b031661213b612909565b6001600160a01b0316148061217257506121556008612c1b565b546001600160a01b0316612167612909565b6001600160a01b0316145b6040518060600160405280602f815260200161589e602f9139906121a95760405162461bcd60e51b8152600401610b3591906150af565b50600354604080516060810190915260238082526001600160a01b0390921615916153fe6020830139906121f05760405162461bcd60e51b8152600401610b3591906150af565b50600380546001600160a01b0319166001600160a01b03831690811790915560408051633013ce2960e01b81529051633013ce29916004808201926020929091908290030181865afa15801561224a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061226e91906150c2565b600080546001600160a01b0319166001600160a01b0392831690811790915560408051928416835260208301919091527fb84a8bf26086331c9421c7ce6650da3b0ef748bd335c3f00ada56f481e4321939101612011565b6003546001600160a01b03166122da612909565b6001600160a01b031614604051806060016040528060338152602001615316603391399061231b5760405162461bcd60e51b8152600401610b3591906150af565b50600080546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015612365573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061238991906150df565b9050600360009054906101000a90046001600160a01b03166001600160a01b0316632cc326416040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156123db57600080fd5b505af11580156123ef573d6000803e3d6000fd5b5050600080546040516370a0823160e01b81523060048201529193508492506001600160a01b0316906370a0823190602401602060405180830381865afa15801561243e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061246291906150df565b61246c919061510e565b905061247a601c8483613b81565b827f2c6a6ee02f179bb5f13a4b7fdc9ccd1dd37e524b48ff0957a931348cc9ad75c082604051611b9c91815260200190565b6003546001600160a01b03166124c0612909565b6001600160a01b03161460405180606001604052806033815260200161531660339139906125015760405162461bcd60e51b8152600401610b3591906150af565b506000600560008481526020019081526020016000206000015490506000811160405180606001604052806023815260200161547960239139906125585760405162461bcd60e51b8152600401610b3591906150af565b508082106040518060600160405280603b81526020016156d7603b9139906125935760405162461bcd60e51b8152600401610b3591906150af565b508181036125a1848261299b565b80600754101560405180606001604052806029815260200161582260299139906125de5760405162461bcd60e51b8152600401610b3591906150af565b50600780548290039055600083900361261857600084815260056020526040812090815560010180546001600160881b031916905561262a565b60008481526005602052604090208390555b837f8274e5392b3ab6bba68ee0567f4ede55e361239b8d0122fa5d3b5dc36497b91d846040516117df91815260200190565b60008060008051602061549c833981519152610ac8565b6003546001600160a01b0316612687612909565b6001600160a01b03161460405180606001604052806033815260200161531660339139906126c85760405162461bcd60e51b8152600401610b3591906150af565b50600080546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015612712573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061273691906150df565b9050600360009054906101000a90046001600160a01b03166001600160a01b0316632cc326416040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561278857600080fd5b505af115801561279c573d6000803e3d6000fd5b5050600080546040516370a0823160e01b81523060048201529193508492506001600160a01b0316906370a0823190602401602060405180830381865afa1580156127eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061280f91906150df565b612819919061510e565b9050827f2c6a6ee02f179bb5f13a4b7fdc9ccd1dd37e524b48ff0957a931348cc9ad75c082604051611b9c91815260200190565b600080546040516370a0823160e01b815230600482015282916128c8916001600160a01b03909116906370a0823190602401602060405180830381865afa15801561289c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128c091906150df565b600654612a6b565b600754909150836128e8576128db61265c565b6128e59082615121565b90505b808210156128f7576000612901565b612901818361510e565b949350505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633148015612944575060143610155b15612956575060131936013560601c90565b503390565b60408051808201909152601b81526000805160206154218339815191526020820152816115d75760405162461bcd60e51b8152600401610b3591906150af565b6000828152600560205260409020600101546001600160801b03811690600160801b900460ff166129da8383836129d2600d6129e0565b929190613c6c565b50505050565b60004282600e015411156129f457816129f9565b816007015b92915050565b6000612a0d83600501613a4c565b15612a3e578115612a23575060018201546129f9565b60018301546003840154612a379190612a6b565b90506129f9565b8115612a5057612a3783600101613c9a565b612a37612a5f84600101613c9a565b610ba985600301613c9a565b6000818310612a7a5781612a7c565b825b9392505050565b612a8c83613cbc565b612a968383613cee565b80612aa557612aa58383613cfb565b505050565b6000805160206154dc833981519152805482908290600090612acd908490615121565b909155505080546040805184815260208101929092527ff3a2c404b3362c4238317c3dad1020c2e9e984ba8df38a4a1ff18d57e92a242a910161173d565b600080546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015612b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b7891906150df565b905080600654146040518060600160405280603381526020016157656033913990612bb65760405162461bcd60e51b8152600401610b3591906150af565b5060408051808201909152601f81526000805160206154bc833981519152602082015282821015612bfa5760405162461bcd60e51b8152600401610b3591906150af565b50600680548390039055600054612aa5906001600160a01b03168484613d08565b60004282600401541115612c2f57816129f9565b5060020190565b60408051602081019091527f3fc394ec90f88dd7e18c46ffeef55f1b6719a2027f4ae9fbc4ab1182718912008054825290600090612c7c90612c7790613d5a565b613db2565b90506000612cc08286868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613ddf92505050565b9050856001600160a01b0316816001600160a01b0316146040518060600160405280602b81526020016157f7602b913990612d0e5760405162461bcd60e51b8152600401610b3591906150af565b508254836000612d1d83615134565b9190505550505050505050565b600060008051602061549c8339815191528181556000805160206154fc83398151915282905560405190917f8892a543ee6d561b73cc067b2cde5a76c251a4e0b978d92390f1301db5d125ab91a150565b60408051808201909152601b8152600080516020615421833981519152602082015282612dbb5760405162461bcd60e51b8152600401610b3591906150af565b50612dc46113fd565b8211156040518060400160405280601f81526020016000805160206154bc83398151915281525090612e095760405162461bcd60e51b8152600401610b3591906150af565b5060008051602061549c833981519152828155612e346000805160206154fc83398151915283613e09565b60018101546040805185815260208101929092527ffa4870dc2e2f95d11863e7e765a98e12fe92c3d1d2a703b4cf983f9c4b1052e691015b60405180910390a1505050565b602082015151600384015460801b6001600160801b03199081169116141580612ebc575060208083015101516003840154600160801b900461ffff908116911614155b80612ed95750815160028401546001600160a01b03908116911614155b60405180606001604052806027815260200161568e6027913990612f105760405162461bcd60e51b8152600401610b3591906150af565b506004830154421015612f895781516002840180546001600160a01b039092166001600160a01b03199092169190911790556020808301518051600386018054929093015161ffff16600160801b026001600160901b031990921660809190911c17179055612f7f8142615121565b6004840155505050565b60028301805484546001600160a01b03199081166001600160a01b0380841691909117875560038701805460018901805461ffff600160801b808504821681026001600160901b03199384166001600160801b03871617179093558a51909516959096169490941790955560208088015180519101519092169092029290931660809390931c92909217179055612f7f8142615121565b60048201541515156040518060600160405280602f81526020016152e7602f91399061305f5760405162461bcd60e51b8152600401610b3591906150af565b5080516002830180546001600160a01b039092166001600160a01b03199092169190911790556020908101518051600384018054929093015161ffff16600160801b026001600160901b031990921660809190911c1717905542600490910155565b600c54421015806130cf5750805b60405180606001604052806035815260200161565960359139906131065760405162461bcd60e51b8152600401610b3591906150af565b50612aa583836131166008612c1b565b9190613e6c565b600560008581526020019081526020016000206000015460001460405180606001604052806029815260200161573c602991399061316e5760405162461bcd60e51b8152600401610b3591906150af565b5061317a838383613e87565b6129da84848484613ec8565b60008051602061549c833981519152805461319f6113fd565b8111156040518060400160405280601f81526020016000805160206154bc833981519152815250906131e45760405162461bcd60e51b8152600401610b3591906150af565b506131ed61201c565b60405180606001604052806038815260200161544160389139906132245760405162461bcd60e51b8152600401610b3591906150af565b50600080835560018301556132398382614067565b826001600160a01b03167fa578b4c05763eb039caef37b2d7b949c22914c3838384c9c73cefb78c4a8ed0a82604051611b9c91815260200190565b826001016000838152602001908152602001600020546000146040518060600160405280602a8152602001615374602a9139906132c45760405162461bcd60e51b8152600401610b3591906150af565b50600082815260018401602052604081208290558354829185916132e9908490615121565b9091555050505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061337a57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661336e6000805160206155cf833981519152546001600160a01b031690565b6001600160a01b031614155b156110325760405163703e46dd60e11b815260040160405180910390fd5b6004546001600160a01b03166133ac612909565b6001600160a01b031614806133e357506133c66008612c1b565b546001600160a01b03166133d8612909565b6001600160a01b0316145b6040518060600160405280602f815260200161589e602f91399061341a5760405162461bcd60e51b8152600401610b3591906150af565b506001546040516316da1fb760e11b81526001600160a01b03838116600483015290911690632db43f6e90602401602060405180830381865afa158015613465573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613489919061514d565b6040518060600160405280602981526020016158cd60299139906115d75760405162461bcd60e51b8152600401610b3591906150af565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561351a575060408051601f3d908101601f19168201909252613517918101906150df565b60015b61354257604051634c9c8ce360e01b81526001600160a01b0383166004820152602401610b35565b6000805160206155cf833981519152811461357357604051632a87526960e21b815260048101829052602401610b35565b612aa583836140a0565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146110325760405163703e46dd60e11b815260040160405180910390fd5b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1028054606091600080516020615541833981519152916136059061516a565b80601f01602080910402602001604051908101604052809291908181526020018280546136319061516a565b801561367e5780601f106136535761010080835404028352916020019161367e565b820191906000526020600020905b81548152906001019060200180831161366157829003601f168201915b505050505091505090565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1038054606091600080516020615541833981519152916136059061516a565b6110326140f6565b6136d86140f6565b6115d7828261413f565b6136ea614a94565b600082116040518060600160405280602e815260200161584b602e9139906137255760405162461bcd60e51b8152600401610b3591906150af565b50506040805160a0810182529485528051808201825293845260006020858101829052808701959095528151808301835293845283850152848101929092528151928301909152600182526060830191909152608082015290565b600e8201541515156040518060600160405280602f81526020016152e7602f9139906137bf5760405162461bcd60e51b8152600401610b3591906150af565b508051600783015560208082015180516008850155810151600984015560408201518051600a8501550151600b830155606081015151600c83015560800151600d82015542600e90910155565b600e830154421015613870578151600784015560208083015180516008860155810151600985015560408301518051600a8601550151600b840155606082015151600c8401556080820151600d8401556138668142615121565b600e840155505050565b600783018054845560088401805460018601556009850180546002870155600a860180546003880155600b870180546004890155600c8801805460058a0155600d8901805460068b01558851909655602080890151805190965594850151909355604087015180519092559201519091556060840151519055608083015190556138668142615121565b6000805160206154dc8339815191526000613913610acf565b825460408051808201909152601b8152600080516020615421833981519152602082015291925090856139595760405162461bcd60e51b8152600401610b3591906150af565b5060408051808201909152601d81527f353430327c446562743a206e6f2066756e647320617661696c61626c650000006020820152826139ac5760405162461bcd60e51b8152600401610b3591906150af565b508085111560405180606001604052806025815260200161556160259139906139e85760405162461bcd60e51b8152600401610b3591906150af565b5060006139f58387612a6b565b845481900385559050613a088582614151565b83546040805183815260208101929092527f75aec94f6ad949cfd9728eb818639f1b0b882089b480409ab73245c06469eef4910160405180910390a1505050505050565b6000613a588254151590565b6040518060400160405280601d81526020017f353534317c54696d6572733a2074696d6572206e6f742061637469766500000081525090613aac5760405162461bcd60e51b8152600401610b3591906150af565b505054421190565b6000805160206154dc833981519152805460408051808201909152601b8152600080516020615421833981519152602082015283613b055760405162461bcd60e51b8152600401610b3591906150af565b50808311156040518060600160405280602581526020016155616025913990613b415760405162461bcd60e51b8152600401610b3591906150af565b5081548390038083556040805185815260208101929092527fb940258db5193d85cafbc591d0c29fad88d804ff8b9ab71c8f9545af2bb2c07c9101612e6c565b60008360010160008481526020019081526020016000205490506000811160405180606001604052806025815260200161551c6025913990613bd65760405162461bcd60e51b8152600401610b3591906150af565b508082146040518060600160405280602581526020016158796025913990613c115760405162461bcd60e51b8152600401610b3591906150af565b5083600001548111156040518060600160405280602a8152602001615712602a913990613c515760405162461bcd60e51b8152600401610b3591906150af565b50835403835550600090815260019091016020526040812055565b613c76848361415b565b156129da57613c886001850184614199565b806129da576129da6003850184614199565b805460018201546000919080821015613cb4576000612901565b900392915050565b613cc881600501613a4c565b156110c857600060028201556000600482015560068101546110c8906005830190613e09565b6115d760018301826141e8565b6115d760038301826141e8565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052612aa5908490614205565b60006040518060600160405280602281526020016156b56022913980516020918201208351604051613d959301918252602082015260400190565b604051602081830303815290604052805190602001209050919050565b60006129f9613dbf614268565b8360405161190160f01b8152600281019290925260228201526042902090565b600080600080613def8686614272565b925092509250613dff82826142bf565b5090949350505050565b60408051808201909152601781527f353534307c54696d6572733a207a65726f2064656c6179000000000000000000602082015281613e5b5760405162461bcd60e51b8152600401610b3591906150af565b50613e668142615121565b90915550565b8254612aa59060018501906001600160a01b03168484614378565b601b5442101580613e955750815b15613eb057612aa58382613ea9600d6129e0565b9190614500565b613ebc600d8483614500565b612aa560148483614500565b613ed18361295b565b60008215613f3c576000613ee5600161284d565b9050848110613ef657849150613f36565b809150857f83067e3478aa8b638f7e34eeecb23875cc3671e615445e892cc22dcd4c8b8df3828703604051613f2d91815260200190565b60405180910390a25b50613f8e565b613f44610acf565b8411156040518060400160405280601f81526020016000805160206154bc83398151915281525090613f895760405162461bcd60e51b8152600401610b3591906150af565b508390505b60408051808201909152601f81527f353331337c4163636f756e743a206e6f2066756e647320746f20626c6f636b00602082015281613fe05760405162461bcd60e51b8152600401610b3591906150af565b50604080516060810182528281526001600160801b03428116602080840191825286151584860190815260008b815260059092529481209351845590516001909301805494511515600160801b026001600160881b03199095169390921692909217929092179091556007805483929061405b908490615121565b90915550505050505050565b806006541015614078576000614086565b80600654614086919061510e565b6006556000546115d7906001600160a01b03168383613d08565b6140a982614562565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a28051156140ee57612aa582826145c7565b6115d761463d565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661103257604051631afcd79f60e31b815260040160405180910390fd5b6141476140f6565b6115d7828261465c565b6115d78282612b0b565b60006005830161416a81613a4c565b156141795760009150506129f9565b6006840154815460009161418c9161510e565b84101592506129f9915050565b80826001015410156040518060600160405280602e8152602001615798602e9139906141d85760405162461bcd60e51b8152600401610b3591906150af565b5060019091018054919091039055565b808260010160008282546141fc9190615121565b90915550505050565b600061421a6001600160a01b038416836146bd565b9050805160001415801561423f57508080602001905181019061423d919061514d565b155b15612aa557604051635274afe760e01b81526001600160a01b0384166004820152602401610b35565b6000610adb6146cb565b600080600083516041036142ac5760208401516040850151606086015160001a61429e8882858561473f565b9550955095505050506142b8565b50508151600091506002905b9250925092565b60008260038111156142d3576142d36151a4565b036142dc575050565b60018260038111156142f0576142f06151a4565b0361430e5760405163f645eedf60e01b815260040160405180910390fd5b6002826003811115614322576143226151a4565b036143435760405163fce698f760e01b815260048101829052602401610b35565b6003826003811115614357576143576151a4565b036115d7576040516335e2f38360e21b815260048101829052602401610b35565b83546040805160608101909152602980825261ffff600160801b90930483169284168311919061539e6020830139906143c45760405162461bcd60e51b8152600401610b3591906150af565b5082825b8261ffff168161ffff161015614482576040516bffffffffffffffffffffffff19606088901b1660208201526001600160f01b031960f083901b1660348201526001600160801b03198316603682015260029060460160408051601f1981840301815290829052614438916151ba565b602060405180830381855afa158015614455573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061447891906150df565b91506001016143c8565b5085546040805160608101909152602180825260809290921b6001600160801b031990811690841614916155ae6020830139906144d25760405162461bcd60e51b8152600401610b3591906150af565b5050845461ffff909216600160801b026001600160901b031990921660809390931c92909217179092555050565b82600001548211156040518060600160405280603b815260200161561e603b91399061453f5760405162461bcd60e51b8152600401610b3591906150af565b5061454983613cbc565b614553838361480e565b80612aa557612aa5838361485d565b806001600160a01b03163b60000361459857604051634c9c8ce360e01b81526001600160a01b0382166004820152602401610b35565b6000805160206155cf83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b0316846040516145e491906151ba565b600060405180830381855af49150503d806000811461461f576040519150601f19603f3d011682016040523d82523d6000602084013e614624565b606091505b50915091506146348583836148af565b95945050505050565b34156110325760405163b398979f60e01b815260040160405180910390fd5b6146646140f6565b6000805160206155418339815191527fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10261469e8482615226565b50600381016146ad8382615226565b5060008082556001909101555050565b6060612a7c8383600061490b565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6146f66149a8565b6146fe614a12565b60408051602081019490945283019190915260608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561477a5750600091506003905082614804565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa1580156147ce573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166147fa57506000925060019150829050614804565b9250600091508190505b9450945094915050565b61481b6001830182614a56565b60405180606001604052806028815260200161558660289139906148525760405162461bcd60e51b8152600401610b3591906150af565b506115d78282613cee565b61486a6003830182614a56565b6040518060600160405280602f81526020016155ef602f9139906148a15760405162461bcd60e51b8152600401610b3591906150af565b506115d760038301826141e8565b6060826148c4576148bf82614a6b565b612a7c565b81511580156148db57506001600160a01b0384163b155b1561490457604051639996b31560e01b81526001600160a01b0385166004820152602401610b35565b5092915050565b6060814710156149305760405163cd78605960e01b8152306004820152602401610b35565b600080856001600160a01b0316848660405161494c91906151ba565b60006040518083038185875af1925050503d8060008114614989576040519150601f19603f3d011682016040523d82523d6000602084013e61498e565b606091505b509150915061499e8683836148af565b9695505050505050565b6000600080516020615541833981519152816149c26135c6565b8051909150156149da57805160209091012092915050565b815480156149e9579392505050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470935050505090565b600060008051602061554183398151915281614a2c613689565b805190915015614a4457805160209091012092915050565b600182015480156149e9579392505050565b6000614a6183613c9a565b9091111592915050565b805115614a7b5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6040518060a0016040528060008152602001614ac3604051806040016040528060008152602001600081525090565b8152602001614ae5604051806040016040528060008152602001600081525090565b8152602001614b006040518060200160405280600081525090565b8152602001600081525090565b60008060408385031215614b2057600080fd5b50508035926020909101359150565b6001600160a01b03811681146110c857600080fd5b60008083601f840112614b5657600080fd5b50813567ffffffffffffffff811115614b6e57600080fd5b602083019150836020828501011115614b8657600080fd5b9250929050565b600080600060408486031215614ba257600080fd5b8335614bad81614b2f565b9250602084013567ffffffffffffffff811115614bc957600080fd5b614bd586828701614b44565b9497909650939450505050565b600060208284031215614bf457600080fd5b5035919050565b80356001600160801b031981168114614c1357600080fd5b919050565b803561ffff81168114614c1357600080fd5b600080600080600060808688031215614c4257600080fd5b8535614c4d81614b2f565b9450614c5b60208701614bfb565b9350614c6960408701614c18565b9250606086013567ffffffffffffffff811115614c8557600080fd5b614c9188828901614b44565b969995985093965092949392505050565b80151581146110c857600080fd5b600080600080600060a08688031215614cc857600080fd5b8535945060208601359350614cdf60408701614bfb565b9250614ced60608701614c18565b91506080860135614cfd81614ca2565b809150509295509295909350565b600060208284031215614d1d57600080fd5b8135612a7c81614b2f565b634e487b7160e01b600052604160045260246000fd5b60008060408385031215614d5157600080fd5b8235614d5c81614b2f565b9150602083013567ffffffffffffffff80821115614d7957600080fd5b818501915085601f830112614d8d57600080fd5b813581811115614d9f57614d9f614d28565b604051601f8201601f19908116603f01168101908382118183101715614dc757614dc7614d28565b81604052828152886020848701011115614de057600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b600080600060608486031215614e1757600080fd5b83359250602084013591506040840135614e3081614ca2565b809150509250925092565b60005b83811015614e56578181015183820152602001614e3e565b50506000910152565b60008151808452614e77816020860160208601614e3b565b601f01601f19169290920160200192915050565b60ff60f81b881681526000602060e06020840152614eac60e084018a614e5f565b8381036040850152614ebe818a614e5f565b606085018990526001600160a01b038816608086015260a0850187905284810360c08601528551808252602080880193509091019060005b81811015614f1257835183529284019291840191600101614ef6565b50909c9b505050505050505050505050565b8051825260208082015180518285015290810151604084015250604081015180516060840152602081015160808401525060608101515160a08301526080015160c090910152565b6101e08101614f7b8286614f24565b614f8860e0830185614f24565b826101c0830152949350505050565b60008060008060008060c08789031215614fb057600080fd5b8635614fbb81614b2f565b95506020870135614fcb81614b2f565b95989597505050506040840135936060810135936080820135935060a0909101359150565b6000806040838503121561500357600080fd5b61500c83614bfb565b915061501a60208401614c18565b90509250929050565b6000806000806080858703121561503957600080fd5b5050823594602084013594506040840135936060013592509050565b80516001600160a01b0316825260209081015180516001600160801b03191682840152015161ffff16604090910152565b60e081016150948286615055565b6150a16060830185615055565b8260c0830152949350505050565b602081526000612a7c6020830184614e5f565b6000602082840312156150d457600080fd5b8151612a7c81614b2f565b6000602082840312156150f157600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b818103818111156129f9576129f96150f8565b808201808211156129f9576129f96150f8565b600060018201615146576151466150f8565b5060010190565b60006020828403121561515f57600080fd5b8151612a7c81614ca2565b600181811c9082168061517e57607f821691505b60208210810361519e57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052602160045260246000fd5b600082516151cc818460208701614e3b565b9190910192915050565b601f821115612aa5576000816000526020600020601f850160051c810160208610156151ff5750805b601f850160051c820191505b8181101561521e5782815560010161520b565b505050505050565b815167ffffffffffffffff81111561524057615240614d28565b6152548161524e845461516a565b846151d6565b602080601f83116001811461528957600084156152715750858301515b600019600386901b1c1916600185901b17855561521e565b600085815260208120601f198616915b828110156152b857888601518255948401946001909101908401615299565b50858210156152d65787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fe353530307c44656c6179656453657474696e67733a2076616c756520616c726561647920696e697469616c697a6564353330327c4163636f756e743a206f6e6c792070726f636573736f722063616e2063616c6c20746869732066756e6374696f6e353334307c4163636f756e743a20736574746c656d656e7420706572696f64206973206e6f74206f766572353432307c526566756e64733a20726566756e64207265636f726420616c726561647920657869737473353531307c4f6e6554696d6550617373776f72643a20696e76616c6964204f545020636f756e746572353335307c4163636f756e743a20726573756c74696e672076657269666965642062616c616e636520657863656564732061637475616c353335317c4163636f756e743a2070726f636573736f7220616c726561647920736574353130307c436f6d6d6f6e3a20616d6f756e74206973207a65726f0000000000353431307c44656c617965645769746864726177616c733a207769746864726177616c2074696d656c6f636b206e6f742065787072696564353332307c4163636f756e743a207472616e73616374696f6e206e6f7420666f756e6476d8021c4b979e99674b80f4e0cc10154af0e5f32df05eb51b29a464e2435500353130317c436f6d6d6f6e3a20696e73756666696369656e742066756e6473003486e95df892f06bd37fd38c44e2fee4c4efb6660a66e6eb20ed6d8a167eae0076d8021c4b979e99674b80f4e0cc10154af0e5f32df05eb51b29a464e2435501353432317c526566756e64733a20726566756e64207265636f7264206e6f7420666f756e64a16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100353430337c446562743a20616d6f756e7420697320686967686572207468616e2064656274353532317c4163636f756e744c696d6974733a207370656e64206c696d6974206578636565646564353531317c4f6e6554696d6550617373776f72643a20696e76616c6964204f5450360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc353532337c4163636f756e744c696d6974733a206e6f206f7470207370656e64206c696d6974206578636565646564353532307c4163636f756e744c696d6974733a20616d6f756e7420657863656564732073696e676c65207472616e73616374696f6e206c696d6974353331327c4163636f756e743a2063617264206f72204f5450207374617465206368616e676520697320696e2070726f6772657373353530317c44656c6179656453657474696e67733a2076616c756520616c7265616479207365744f776e657273686970416363657074616e63652875696e74323536206e6f6e636529353332317c4163636f756e743a206e657720616d6f756e7420697320657175616c206f7220686967686572207468616e20617574686f72697a6564353432337c526566756e64733a2070656e64696e6720616d6f756e74206578636565647320746f74616c353331307c4163636f756e743a207472616e73616374696f6e20494420616c72656164792075736564353333307c4163636f756e743a2076657269666965642062616c616e6365206e6f7420657175616c20746f2062616c616e6365353533317c5370656e644c696d6974733a20696e73756666696369656e74207370656e7420746f2063616e63656c353335327c4163636f756e743a20636172642077697468206f7470207374617465206e6f7420696e697469616c697a6564353535307c4f776e657273686970416363657074616e63653a20696e76616c6964207369676e6174757265353330347c4163636f756e743a20696e73756666696369656e7420626c6f636b656420616d6f756e74353532347c4163636f756e744c696d6974733a207370656e64206c696d697420706572696f64206973207a65726f353432327c526566756e64733a20696e76616c696420616d6f756e74207265636569766564353330317c4163636f756e743a206f6e6c79206f776e65722063616e2063616c6c20746869732066756e6374696f6e353337307c4163636f756e743a20756e617574686f72697a656420696d706c656d656e746174696f6ea26469706673582212201bf402f34a1057d0d739b2911423245677cc744b072d4af8e7f665bc51781a7f64736f6c63430008160033"; +public class TangemPaymentAccount extends Contract { + public static final String BINARY = "60c06040523462000050576200001e62000018620000f3565b62000116565b604051616e73620002b28239608051818181610fea0152612efb015260a0518181816149490152614b830152616e7390f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b90601f01601f191681019081106001600160401b038211176200008d57604052565b62000055565b90620000aa620000a260405190565b92836200006b565b565b6001600160a01b031690565b90565b6001600160a01b038116036200005057565b90505190620000aa82620000bb565b906020828203126200005057620000b891620000cd565b620000b862007125803803806200010a8162000093565b928339810190620000dc565b620001219062000157565b620000aa620001fa565b620000b890620000ac906001600160a01b031682565b620000b8906200012b565b620000b89062000141565b60805262000168620000aa80808080565b62000173306200014c565b60a052565b620000b89060401c60ff1690565b620000b8905462000178565b620000b8905b6001600160401b031690565b620000b8905462000192565b620000b89062000198906001600160401b031682565b90620001da620000b8620001f692620001b0565b82546001600160401b0319166001600160401b03919091161790565b9055565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00620002268162000186565b6200029f576200023681620001a4565b6001600160401b03919082908116036200024e575050565b81620002807fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2936200029a93620001c6565b604051918291826001600160401b03909116815260200190565b0390a1565b60405163f92ee8a960e01b8152600490fdfe6080604052600436101561001257600080fd5b60003560e01c806274f3561461037c57806301e948ff1461029657806312a168311461037757806316fc32971461037257806319cdeb6f1461036d5780631d6ae778146103685780631f852f4b14610363578063226112801461035e578063246f8b96146103595780632ea63823146103545780633013ce291461034f57806334d6ee4a1461034a578063357a03331461034557806335ba9af81461034057806337a1d4151461033b5780633e0fc2ff1461033657806340345137146103315780634e6d8a731461032c5780634f1ef2861461032757806352d1902d14610322578063563b9b0f1461031d578063572b6c05146103185780636b2a3830146103135780636b4943a71461030e5780636fb7e9c11461030957806370908f21146103045780637917cf6f146102ff5780637b103999146102fa5780637da0a877146102f557806384b0196e146102f057806386f15d09146102eb5780638da5cb5b146102e65780638ef008b8146102e1578063997584a4146102dc5780639cadd226146102d7578063aa37ff1b146102d2578063ad3cb1cc146102cd578063b9603bdf146102c8578063bc77d495146102c3578063be69191d146102be578063c45a0155146102b9578063c470d703146102b4578063c9a557fa146102af578063ce1b1d43146102aa578063d47ae89c146102a5578063dbed8faa146102a0578063dcab7e501461029b578063df7727b414610296578063e2b7202514610291578063e37b81541461028c578063e6e268f414610287578063e96ede8e14610282578063eec4f8121461027d578063f2bcd022146102785763f93184c10361038c57611620565b611605565b6115ed565b6115d4565b6115b9565b611588565b611496565b6103c7565b61147b565b611463565b611448565b61142d565b611406565b6113eb565b6113d0565b6113a9565b611390565b611378565b611351565b6112e3565b6112c4565b611247565b61120c565b611191565b61116a565b611136565b610fd5565b610fba565b610f93565b610f56565b610bb9565b610b17565b610af3565b610ac6565b610a93565b610a11565b6109fd565b61093d565b6108f5565b610879565b610861565b610846565b61082d565b6107e3565b610748565b6106c6565b6105e1565b6105c9565b6105b0565b61052c565b6104c0565b610486565b610441565b610397565b600091031261038c57565b600080fd5b9052565b565b3461038c576103a7366004610381565b6103c36103b261163c565b6040515b9182918290815260200190565b0390f35b3461038c576103d7366004610381565b6103c36103b2611655565b6001600160a01b031690565b90565b6001600160a01b0381165b0361038c57565b90503590610395826103f1565b9081604091031261038c5790565b919060608382031261038c576103ee90602061043a8286610403565b9401610410565b3461038c5761045a61045436600461041e565b90611869565b604051005b806103fc565b905035906103958261045f565b9060208282031261038c576103ee91610465565b3461038c5761045a610499366004610472565b611938565b6103ee916008021c81565b906103ee915461049e565b6103ee600060076104a9565b3461038c576104d0366004610381565b6103c36103b26104b4565b8015156103fc565b90503590610395826104db565b60808183031261038c576105048282610403565b926103ee6105158460208501610465565b9360606105258260408701610465565b94016104e3565b3461038c5761045a61053f3660046104f0565b92919091611a30565b909182601f8301121561038c578135916001600160401b03831161038c57602001926001830284011161038c57565b91909160408184031261038c5761058e8382610403565b9260208201356001600160401b03811161038c576105ac9201610548565b9091565b3461038c5761045a6105c3366004610577565b91611c61565b3461038c576105d9366004610381565b61045a611c82565b3461038c576105f1366004610381565b61045a611cda565b634e487b7160e01b600052604160045260246000fd5b90601f01601f191681019081106001600160401b0382111761063057604052565b6105f9565b9061039561064260405190565b928361060f565b919060808382031261038c5761069c9060606106656080610635565b946106708382610465565b865261067f8360208301610465565b60208701526106918360408301610465565b604087015201610465565b6060830152565b919060a08382031261038c576103ee9060206106bf8286610403565b9401610649565b3461038c5761045a6106d93660046106a3565b90611d9b565b6103ee916008021c6001600160a01b031690565b906103ee91546106df565b6103ee6000806106f3565b6103ee906103e2906001600160a01b031682565b6103ee90610709565b6103ee9061071d565b61039190610726565b602081019291610395919061072f565b3461038c57610758366004610381565b6103c36107636106fe565b60405191829182610738565b0190565b9061079361078c610782845190565b8084529260200190565b9260200190565b9060005b8181106107a45750505090565b9091926107ca6107c360019286516001600160a01b0316815260200190565b9460200190565b929101610797565b60208082526103ee92910190610773565b3461038c576107f3366004610381565b6103c36107fe611da5565b604051918291826107d2565b919060408382031261038c576103ee9060206108268286610403565b9401610465565b3461038c5761045a61084036600461080a565b90611dd1565b3461038c57610856366004610381565b6103c36103b2611e24565b3461038c57610871366004610381565b61045a611fd5565b3461038c5761045a61088c36600461080a565b906122fe565b908160e091031261038c5790565b90916101808284031261038c576108b78383610403565b926108c58160208501610403565b926108d38260408301610403565b926103ee6108e48460608501610403565b936101606108268260808701610892565b3461038c5761045a6109083660046108a0565b9493909392919261286e565b909160608284031261038c576103ee61092d8484610403565b9360406108268260208701610465565b3461038c5761045a610950366004610914565b91612c73565b6001600160401b03811161063057602090601f01601f19160190565b90826000939282370152565b9092919261099361098e82610956565b610635565b938185528183011161038c57610395916020850190610972565b9080601f8301121561038c578160206103ee9335910161097e565b91909160408184031261038c576109df8382610403565b9260208201356001600160401b03811161038c576103ee92016109ad565b61045a610a0b3660046109c8565b90612c9e565b3461038c57610a21366004610381565b6103c36103b2612ceb565b91906101408382031261038c57610a438184610403565b92610a518260208301610892565b926101008201356001600160401b03811161038c5783610a72918401610548565b9290936101208201356001600160401b03811161038c576105ac9201610548565b3461038c5761045a610aa6366004610a2c565b94939093929192612ee5565b9060208282031261038c576103ee91610403565b3461038c576103c3610ae1610adc366004610ab2565b612ef3565b60405191829182901515815260200190565b3461038c5761045a610b06366004610472565b613063565b6103ee600060086104a9565b3461038c57610b27366004610381565b6103c36103b2610b0b565b6001600160801b031981166103fc565b9050359061039582610b32565b61ffff81166103fc565b9050359061039582610b4f565b909160c08284031261038c57610b7c8383610403565b92610b8a8160208501610465565b92610b988260408301610465565b926103ee610ba98460608501610b42565b9360a06105258260808701610b59565b3461038c5761045a610bcc366004610b66565b94939093929192613103565b90610be290610726565b600052602052604060002090565b6103ee905b60ff1690565b6103ee9054610bf0565b6103ee9060081c610bf5565b6103ee9054610c05565b6103ee9060101c5b6001600160401b031690565b6103ee9054610c1b565b6103ee9060801c5b61ffff1690565b6103ee9054610c39565b6103ee6040610635565b90610395610c946000610c6d610c52565b94610c8e610c7e8383015460801b90565b6001600160801b03191687840152565b01610c48565b61ffff166020840152565b6103ee9081565b6103ee9054610c9f565b6103ee6060610635565b90610395610cf86002610ccb610cb0565b94610cdc610cd882610c5c565b8752565b610cf2610ceb60018301610c5c565b6020880152565b01610ca6565b6040840152565b90610395610d1d6001610d10610c52565b94610cf2610cd882610ca6565b6020840152565b6103ee6020610635565b90610395610d466000610d3f610d24565b9401610ca6565b8352565b6103ee60a0610635565b90610395610dad6006610d65610d4a565b94610d72610cd882610ca6565b610d81610ceb60018301610cff565b610d97610d9060038301610cff565b6040880152565b610cf2610da660058301610d2e565b6060880152565b6080840152565b90610395610cf8600e610dc5610cb0565b94610dd2610cd882610d54565b610cf2610ceb60078301610d54565b610dec906005610bd8565b610df581610bfb565b91610dff82610c11565b91610e0981610c2f565b916103ee6004610e1b60018501610cba565b9301610db4565b805180516001600160801b031916835260209081015161ffff16908301526103959190608090604090610e7460208201518386019080516001600160801b031916825260209081015161ffff16910152565b0151910152565b8051825261039591906020908190610e74565b516103959152565b80518252610395919060c090608090610eb760208201516020860190610e7b565b610ec960408201516060860190610e7b565b610e74606082015160a0860190610e8e565b906101c0604061039593610ef760008201516000860190610e96565b610e74602082015160e0860190610e96565b90151581526102e08101959461039594909361010093610f4f9291610f4591610f359015156020870152565b6001600160401b03166040850152565b6060830190610e22565b0190610edb565b3461038c576103c3610f71610f6c366004610ab2565b610de1565b91610f7e95939560405190565b95869586610f09565b6103ee600060096104a9565b3461038c57610fa3366004610381565b6103c36103b2610f87565b6103ee600060026106f3565b3461038c57610fca366004610381565b6103c3610763610fae565b3461038c57610fe5366004610381565b6103c37f00000000000000000000000000000000000000000000000000000000000000005b6040515b918291826001600160a01b03909116815260200190565b60005b8381106110385750506000910152565b8181015183820152602001611028565b61106961107260209361076f9361105d815190565b80835293849260200190565b95869101611025565b601f01601f191690565b9061108b61078c610782845190565b9060005b81811061109c5750505090565b9091926110b26107c36001928651815260200190565b92910161108f565b9395919461111261110a611129956110fc611122956103ee9c9a6110ef60e08c019260008d01906001600160f81b0319169052565b8a820360208c0152611048565b9088820360408a0152611048565b976060870152565b6001600160a01b03166080850152565b60a0830152565b60c081840391015261107c565b3461038c57611146366004610381565b6103c36111516131a1565b9361116197959793919360405190565b978897886110ba565b3461038c5761117a366004610381565b6103c3610ae161323f565b6103ee600060046106f3565b3461038c576111a1366004610381565b6103c361100a611185565b9160a08383031261038c576111c18284610403565b926111cf8360208301610465565b926111dd8160408401610465565b9260608301356001600160401b03811161038c57826112036080946103ee938701610548565b949095016104e3565b3461038c5761045a61121f3660046111ac565b9493909392919261330a565b919060408382031261038c576103ee9060206105258286610403565b3461038c5761045a61125a36600461122b565b906134ab565b919060808382031261038c576112768184610403565b9261128482602083016104e3565b9260408201356001600160401b03811161038c57836112a4918401610548565b92909360608201356001600160401b03811161038c576105ac9201610548565b3461038c5761045a6112d7366004611260565b949390939291926135ea565b3461038c5761045a6112f6366004610ab2565b6136c8565b9061130861098e83610956565b918252565b61131760056112fb565b640352e302e360dc1b602082015290565b6103ee61130d565b6103ee611328565b6103ee611330565b60208082526103ee92910190611048565b3461038c57611361366004610381565b6103c361136c611338565b60405191829182611340565b3461038c5761045a61138b366004610472565b613745565b3461038c5761045a6113a336600461080a565b906138cf565b3461038c576113b9366004610381565b6103c3610ae16138d9565b6103ee600060016106f3565b3461038c576113e0366004610381565b6103c36107636113c4565b3461038c576113fb366004610381565b6103c36103b2613902565b3461038c57611416366004610381565b6103c36103b261392d565b6103ee600060036106f3565b3461038c5761143d366004610381565b6103c3610763611421565b3461038c57611458366004610381565b6103c36103b2613963565b3461038c5761045a611476366004610472565b6139e1565b3461038c5761148b366004610381565b6103c36103b26139ea565b3461038c576114a6366004610381565b6103c36103b2613a13565b6103ee6103ee6103ee9290565b90610be2906114b1565b6103ee906103e2565b6103ee90546114c8565b6103ee9060a01c610c23565b6103ee90546114db565b6103ee9060e01c610bf5565b6103ee90546114f1565b6115129060066114be565b9061151c82610ca6565b91611529600182016114d1565b916103ee600161153a8185016114e7565b93016114fd565b61158061039594611570606094989795611560608086019a6000870152565b6001600160a01b03166020850152565b6001600160401b03166040830152565b019015159052565b3461038c576103c36115a361159e366004610472565b611507565b906115b094929460405190565b94859485611541565b3461038c576115c9366004610381565b6103c36103b2613a3e565b3461038c5761045a6115e7366004610914565b91613c48565b3461038c5761045a611600366004610472565b613c92565b3461038c57611615366004610381565b6103c361100a613c9b565b3461038c576103c36103b261163636600461080a565b90613d3b565b6103ee6000600080516020616dfe833981519152610cf2565b6103ee6000613d47565b611669602f6112fb565b7f353330317c4163636f756e743a206f6e6c79206f776e65722063616e2063616c60208201526e36103a3434b990333ab731ba34b7b760891b604082015290565b6103ee61165f565b6103ee6116aa565b156116c25750565b6116e4906116cf60405190565b62461bcd60e51b815291829160048301611340565b0390fd5b90610395916117276116f8613de3565b6117056103e260046114d1565b6001600160a01b0382161490811561172c575b506117216116b2565b906116ba565b611803565b61174491506103ee61173f916005610bd8565b613e1c565b38611718565b919060408382031261038c576117799060206117666040610635565b946117718382610b42565b865201610b59565b6020830152565b6103ee90369061174a565b506103ee906020810190610b42565b506103ee906020810190610b59565b9060206117da610395936117d16117c3600083018361178b565b6001600160801b0319168552565b8281019061179a565b61ffff16910152565b6001600160a01b03909116815260608101929161039591602001906117a9565b907fec402263d6c2da14e65d81be89696eecf02dad51b4edf01a00f7f001fdae65839161184f6118376103ee836005610bd8565b61183f613963565b9061184985611780565b90613e88565b61186461185b60405190565b928392836117e3565b0390a1565b90610395916116e8565b610395906118826116f8613de3565b6118b4565b90505190610395826103f1565b9060208282031261038c576103ee91611887565b6040513d6000823e3d90fd5b6118c66118c160036114d1565b610726565b9060206118d260405190565b63659bf9d960e11b815292839060049082905afa908115611933576118ff92600092611902575b50613f43565b50565b61192591925060203d60201161192c575b61191d818361060f565b810190611894565b90386118f9565b503d611913565b6118a8565b61039590611873565b61194b60336112fb565b7f353330327c4163636f756e743a206f6e6c792070726f636573736f722063616e6020820152721031b0b636103a3434b990333ab731ba34b7b760691b604082015290565b6103ee611941565b6103ee611990565b906103959392916119db6119b2613de3565b6119d26119c56103e26118c160036114d1565b916001600160a01b031690565b14611721611998565b9192611a21611a1b7f6f9b3fed74d79ecbab600aa9408ec793100801e0e811317a78db1cd7f56c589893611a166000611a2b9589848a614050565b6114b1565b93610726565b936103b660405190565b0390a3565b906103959392916119a0565b906103959291611a4d6116f8613de3565b611ac2565b6103e26103ee6103ee9290565b6103ee90611a52565b906001600160a01b03905b9181191691161790565b90611a8d6103ee611a9492610726565b8254611a68565b9055565b6001600160a01b039091168152604081019291610395916020905b01906001600160a01b03169052565b91611ad691611ad084614135565b836141c4565b611ae060046114d1565b600090611aef6103e283611a5f565b6001600160a01b03821603611bb75750611b0a826004611a7d565b611b176118c160026114d1565b91823b1561038c5781611b2960405190565b630d00929760e01b81526001600160a01b0383166004820152938490602490829084905af1918215611933577f50146d0e3c60aa1d17a70635b05494f864e86144a2201275021014fbf08bafe29361186493611b8a575b505060405161100e565b81611ba992903d10611bb0575b611ba1818361060f565b810190610381565b3880611b80565b503d611b97565b91611bc3816004611a7d565b611bd06118c160026114d1565b803b1561038c57818391611c079583611be860405190565b809881958294611bfc63f00d4b5d60e01b90565b845260048401611a98565b03925af1918215611933577f50146d0e3c60aa1d17a70635b05494f864e86144a2201275021014fbf08bafe29361186493611c44575b505061100a565b81611c5a92903d10611bb057611ba1818361060f565b3880611c3d565b906103959291611a3c565b611c776116f8613de3565b610395610395614254565b610395611c6c565b611c956116f8613de3565b6103957f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da611864611cc660046114d1565b61100a611cd36000611a5f565b6004611a7d565b610395611c8a565b9061039591611cf26116f8613de3565b611d43565b8051825261039591906060908190611d1460208201516020860152565b610e7460408201516040860152565b6001600160a01b03909116815260a0810192916103959160200190611cf7565b907f92daafee7b0d3ce63f680acb8054b3dc8e73ffb341502efa1b45a15b1687752991611d86611d776103ee836005610bd8565b83611d80613963565b916142de565b611864611d9260405190565b92839283611d23565b9061039591611ce2565b6103ee600a614307565b9061039591611dbf6116f8613de3565b61039591611dcb613963565b91614360565b9061039591611daf565b905051906103958261045f565b9060208282031261038c576103ee91611ddb565b634e487b7160e01b600052601160045260246000fd5b91908203918211611e1f57565b611dfc565b611e706020611e366118c160006114d1565b611e3f30610726565b90611e4960405190565b938492839182916370a0823160e01b5b83526001600160a01b031660048301526024820190565b03915afa90811561193357600091611eb6575b50611e916103ee6008610ca6565b8110611eab576103ee90611ea56008610ca6565b90611e12565b506103ee60006114b1565b611ed8915060203d602011611ede575b611ed0818361060f565b810190611de8565b38611e83565b503d611ec6565b611eef603c6112fb565b7f353330337c4163636f756e743a206f6e6c792070726f636573736f72206f722060208201527f6f776e65722063616e2063616c6c20746869732066756e6374696f6e00000000604082015290565b6103ee611ee5565b6103ee611f3e565b611f8c611f59613de3565b611f696103e26118c160036114d1565b6001600160a01b03821614908115611fad575b8115611f94575b50611721611f46565b610395611fcd565b611fa791506103ee61173f916005610bd8565b38611f83565b9050611fbc6103e260046114d1565b6001600160a01b0382161490611f7c565b61039561445f565b610395611f4e565b9061039591611fed6119b2613de3565b6121f4565b81810292918115918404141715611e1f57565b6103ee6127106114b1565b634e487b7160e01b600052601260045260246000fd5b90612030565b9190565b90811561203b570490565b612010565b61204a60236112fb565b7f353334317c4163636f756e743a207472616e73616374696f6e206e6f7420666f6020820152621d5b9960ea1b604082015290565b6103ee612040565b6103ee61207f565b612099603e6112fb565b7f353338327c4163636f756e743a207472616e73616374696f6e2077617320617560208201527f74686f72697a65642077697468206120646966666572656e7420636172640000604082015290565b6103ee61208f565b6103ee6120e8565b61210260296112fb565b7f353330347c4163636f756e743a20696e73756666696369656e7420626c6f636b602082015268195908185b5bdd5b9d60ba1b604082015290565b6103ee6120f8565b6103ee61213d565b9060001990611a73565b906121676103ee611a94926114b1565b825461214d565b91908201809211611e1f57565b9160001960089290920291821b911b611a73565b91906121a06103ee611a94936114b1565b90835461217b565b6103959160009161218f565b6000906001906121c483826121a8565b0155565b634e487b7160e01b600052600060045260246000fd5b906000036121ef57610395906121b4565b6121c8565b7fec2d267131598e18b6231352c72c82d77f6236d7da371ad09865737055a23180611a2b611a21611a1b6001956122e96122e26122356103ee8460066114be565b6122a661228b61224483610ca6565b9b8c9361228561226e61226061225a6009610ca6565b88611ff2565b612268612005565b90612026565b9561227c61202c60006114b1565b11611721612087565b016114d1565b61229d6001600160a01b038c166119c5565b146117216120f0565b6122c06122b36008610ca6565b8b905b1015611721612145565b6122dc6122d58b6122d16008610ca6565b0390565b6008612157565b8961216e565b87836144e9565b611a1660006122f98360066114be565b6121de565b9061039591611fdd565b6103ee9060401c610bf5565b6103ee9054612308565b6103ee90610c23565b6103ee905461231e565b610c236103ee6103ee9290565b906001600160401b0390611a73565b610c236103ee6103ee926001600160401b031690565b906123736103ee611a949261234d565b825461233e565b9068ff00000000000000009060401b611a73565b9061239e6103ee611a9492151590565b825461237a565b61039190612331565b60208101929161039591906123a5565b9093949291926123eb7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0090565b9586936124076124016123fd87612314565b1590565b95612327565b9560009761241489612331565b6001600160401b038916148061250c575b6001986124416124348b612331565b916001600160401b031690565b1490816124e8575b155b90816124df575b506124cd5761247b95876124728b6124698c612331565b9d019c8d612363565b6124be576126b7565b61248457505050565b6124b2611864927fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29461238e565b604051918291826123ae565b6124c8898c61238e565b6126b7565b60405163f92ee8a960e01b8152600490fd5b15905038612452565b905061244b6124f630610726565b3b61250361202c8d6114b1565b14919050612449565b5086612425565b61251d60146112fb565b7315185b99d95b54185e5b595b9d1058d8dbdd5b9d60621b602082015290565b6103ee612513565b61254f60016112fb565b603160f81b602082015290565b6103ee612545565b919060e08382031261038c576125a490606061257f81610635565b9461258a83826104e3565b8652612599836020830161174a565b602087015201610649565b6040830152565b6103ee903690612564565b6103fc816114c8565b90505190610395826125b6565b9060208282031261038c576103ee916125bf565b506103ee9060208101906104e3565b506103ee906020810190610465565b9060606126536103959361261c61261860008301836125ef565b8552565b61263361262c60208301836125ef565b6020860152565b61264a61264360408301836125ef565b6040860152565b828101906125ef565b910152565b90606061268e6103959361267861267260008301836125e0565b15158552565b6126896020820160208601906117a9565b820190565b9101906125fe565b6001600160a01b039091168152610100810192916103959160200190612658565b90612752612759936118c161274b611cd3946126d287614135565b6126db81614135565b6126e484614135565b6126ed89614135565b6126f5614547565b6126fd614547565b61271661270861253d565b61271061255c565b90614566565b61271e614547565b612726614547565b61272e614547565b612736614547565b6118c16127446118c1613de3565b6001611a7d565b6003611a7d565b6002611a7d565b61277961276a6103ee836005610bd8565b612773846125ab565b9061460c565b61278481600a614696565b506127926118c160036114d1565b92602061279e60405190565b633013ce2960e01b815294859060049082905afa908115611933576127f26127f9927f778238c396424814c7113c41823459473262293bc693b847480fcbc85a6d94bd9660009161283f575b506000611a7d565b6009612157565b7f50146d0e3c60aa1d17a70635b05494f864e86144a2201275021014fbf08bafe261282761100a60046114d1565b0390a161186461283660405190565b92839283612696565b612861915060203d602011612867575b612859818361060f565b8101906125cc565b386127ea565b503d61284f565b9061039595949392916123be565b90610395929161288d6119b2613de3565b612907565b61289c60206112fb565b7f353338307c4163636f756e743a2063617264206973206e6f7420616374697665602082015290565b6103ee612892565b6103ee6128c5565b9081526040810192916103959160200152565b0152565b9081526060810193926103959290916040916128e890611779565b9190916129186103ee8460066114be565b9161292281614706565b61296f6001840193612933856114d1565b9060009586926129486119c56103e286611a5f565b03612c505750610cf26129676129626103ee886005610bd8565b614720565b6117216128cd565b926129866122606129806009610ca6565b86611ff2565b93600094818411612b2b576129dd916129ad6122d5928698506129a887840390565b61216e565b6129b6856114b1565b8111612b1a575b505b6129d36129cc6008610ca6565b82906122b6565b6122d16008610ca6565b6129ec816122f98760066114be565b6129f96118c160036114d1565b916020612a0560405190565b63659bf9d960e11b815293849060049082905afa938415611933577fabb0c23c76702883b6d5427581380669e510735331d9dc6a0eb99a1312dd5d5a86612a68611a1b612a869a611a1660209b611e369b6118c19b600091612afc575b506148a6565b93612a7e612a7560405190565b928392836128d5565b0390a36114d1565b03915afa8015611933577fc638d270f17f849b0216682c6cf6ee6fd9af6cac195b4647eb3b4857bbc10dc791600091612add575b50612ac56008610ca6565b90611864612ad161163c565b604051938493846128ec565b612af6915060203d602011611ede57611ed0818361060f565b38612aba565b612b1491508e3d60201161192c5761191d818361060f565b38612a62565b612b2590878a6144e9565b386129bd565b948195612b46612b41600461076f896005610bd8565b614741565b90612b52858301610ca6565b848491612b5c8190565b8210612c28575b5050612b6e866114b1565b8111612baf575b5050506129dd916122d59150612b8a87860390565b612b93856114b1565b8111612ba0575b506129bf565b612ba9906147fd565b38612b9a565b6129dd9492985090612bce6122d59492612bc8858a0390565b906147c7565b868482019a83831015612bf9575050612bea90612bf192611e12565b888b6144e9565b918193612b75565b9091838111612c0c575b50505050612bf1565b612c1f93612c1991611e12565b906147d4565b38858180612c03565b612c499250612c41919003612bc88461076f8a88614759565b612bc8611655565b8438612b63565b612c5c612c6e916114d1565b61229d6001600160a01b0388166119c5565b610cf2565b90610395929161287c565b9061039591612c8b61493e565b9061039591612c9981614a86565b614a8f565b9061039591612c7e565b6103ee90612cb4614b6d565b612ce2565b6103ee7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6114b1565b506103ee612cb9565b6103ee6000612ca8565b906103959594939291612d096116f8613de3565b612d89565b356103ee816104db565b90505190610395826104db565b9060208282031261038c576103ee91612d18565b612d4360246112fb565b7f353335337c4163636f756e743a20696e76616c6964206361726420636f6e667260208201526334b6b2b960e11b604082015290565b6103ee612d39565b6103ee612d79565b94612db79194612da8612ddb95602095612da28a614135565b896141c4565b612db186612d0e565b87614baf565b612dc46118c160036114d1565b604051938492839182916399fef6bb60e01b611e59565b03915afa801561193357612dfa91600091612eb6575b50611721612d81565b612e14612e0b6103ee846005610bd8565b612773836125ab565b612e1f82600a614696565b50612e2d6118c160026114d1565b91823b1561038c576000612e4060405190565b631ee284a960e11b81526001600160a01b0383166004820152938490602490829084905af1928315611933577f778238c396424814c7113c41823459473262293bc693b847480fcbc85a6d94bd93612ea0575b5061186461283660405190565b612eb0906000611ba1818361060f565b38612e93565b612ed8915060203d602011612ede575b612ed0818361060f565b810190612d25565b38612df1565b503d612ec6565b906103959594939291612cf5565b612f1f6119c57f00000000000000000000000000000000000000000000000000000000000000006103e2565b1490565b61039590612f326119b2613de3565b612fa0565b612f4160376112fb565b7f353335307c4163636f756e743a20726573756c74696e6720766572696669656460208201527f2062616c616e636520657863656564732061637475616c000000000000000000604082015290565b6103ee612f37565b6103ee612f90565b612fe990612fb2816129a86007610ca6565b906020612fc26118c160006114d1565b612fcb30610726565b90612fd560405190565b958692839182916370a0823160e01b611e59565b03915afa801561193357613027613033917fd6004694c2f543b69302481de26731f63c1d41062795b5366d8ca20fd3e3d6d39560009161304a575090565b835b1115611721612f98565b61303e826007612157565b611864612a7560405190565b6103ee915060203d602011611ede57611ed0818361060f565b61039590612f23565b9061039595949392916130806119b2613de3565b93946130cf6130c9859493611a166001856130c1611a2b978d7f30ac254a4e36e31e8baa2471788b94b8879347196809fce466f5c214c7d71e639c8e614c91565b87848c614050565b95610726565b956130d960405190565b938493849081526001600160801b031991909116602082015261ffff909116604082015260600190565b90610395959493929161306c565b1561311857565b60405162461bcd60e51b81526020600482015260156024820152741152540dcc4c8e88155b9a5b9a5d1a585b1a5e9959605a1b6044820152606490fd5b6001600160401b0381116106305760208091020190565b9061130861098e83613155565b369037565b9061039561319461318e8461316c565b93613155565b601f190160208401613179565b600080516020616e1e8339815191526131da6131bc82610ca6565b916000926131cc61202c856114b1565b14908161321f575b50613111565b6131e2614dd3565b916131eb614dee565b916131f530610726565b9061321061320b613205836114b1565b926114b1565b61317e565b600f60f81b9594934693929190565b61322c9150600101610ca6565b61323861202c846114b1565b14386131d4565b6103ee7f76d8021c4b979e99674b80f4e0cc10154af0e5f32df05eb51b29a464e2435502614e07565b90610395959493929161327c6119b2613de3565b6132b7565b9190611072816132988161076f9560209181520190565b8095610972565b9081526040602082018190526103ee93910191613281565b93946132f76130c97f8b7b934d191c6093eafb9a1fc61ef68d088dc5a0438697fe2ceac68b79574a52959493611a166001611a2b956130c18c8a8d614e89565b9561330160405190565b9384938461329f565b906103959594939291613268565b90610395916133286116f8613de3565b613406565b6103ee6103ee6103ee926001600160401b031690565b61334d60266112fb565b7f353338317c4163636f756e743a20636172642064697361626c6520696e2070726020820152656f677265737360d01b604082015290565b6103ee613343565b6103ee613385565b61339f60216112fb565b7f353335347c4163636f756e743a2069734f776e657220616c72656164792073656020820152601d60fa1b604082015290565b6103ee613395565b6103ee6133d2565b9061ff009060081b611a73565b906133ff6103ee611a9492151590565b82546133e2565b6118649061100a7f6a5e3421b4ba058a580be88d10e1c5940843a54923898f281b2fdf1ae733aef893600061343f6103ee856005610bd8565b61344b61296782614720565b0161347e61345882610c2f565b61347561346f6103ee613469613963565b4261216e565b9161332d565b1161172161338d565b6134a66134976000613491876005610bd8565b01610c11565b151583151514156117216133da565b6133ef565b9061039591613318565b9061039595949392916134c96116f8613de3565b6134ed565b6001600160a01b03909116815260408101929161039591602090611580565b94612db7919461350361350a95602095896141c4565b8587614baf565b03915afa80156119335761352891600091612eb65750611721612d81565b61353f8161353a6103ee856005610bd8565b614f34565b61354a82600a614696565b506135586118c160026114d1565b91823b1561038c57600061356b60405190565b631ee284a960e11b81526001600160a01b0383166004820152938490602490829084905af1928315611933577f1526aa7b69cd2d8a922030e75d5e009a330a1e46b715fd6f0e438df811d8ce8b936135d4575b506118646135cb60405190565b928392836134ce565b6135e4906000611ba1818361060f565b386135be565b9061039595949392916134b5565b610395906136076116f8613de3565b6136266136186103ee836005610bd8565b613620613963565b90614fba565b61363181600a615005565b5061363f6118c160026114d1565b90813b1561038c57600061365260405190565b634149177b60e01b81526001600160a01b0383166004820152928390602490829084905af1908115611933577f6a5e3421b4ba058a580be88d10e1c5940843a54923898f281b2fdf1ae733aef892611864926136b2575b5060405161100e565b6136c2906000611ba1818361060f565b386136a9565b610395906135f8565b610395906136e06119b2613de3565b6136f26020611e366118c160006114d1565b03915afa9182156119335761373a6137347f321b800465e47508430424e6c089344256e17f9a5b0b43c751dffbdfd3930263946118649460009161304a575090565b82613029565b6103b2816007612157565b610395906136d1565b906103959161375e6119b2613de3565b61376b6118c160006114d1565b6370a0823161377930610726565b90602061378560405190565b80946137918460e01b90565b82526001600160a01b038516600483015260249082905afa928315611933576000936138ae575b506137c66118c160036114d1565b91823b1561038c5760006137d960405190565b632cc3264160e01b8152938490600490829084905af19182156119335761382a93602093613898575b50611e596138136118c160006114d1565b9161381d60405190565b9586948593849360e01b90565b03915afa91821561193357611a1b613873611a21927faef62a4e4bd58df7ff5d05f9b40355fadfa67884312a36b7f64c53fd699d4f5695611a2b95600091613879575b50611e12565b956114b1565b613892915060203d602011611ede57611ed0818361060f565b3861386d565b6138a8906000611ba1818361060f565b38613802565b6138c891935060203d602011611ede57611ed0818361060f565b91386137b8565b906103959161374e565b6103ee7f76d8021c4b979e99674b80f4e0cc10154af0e5f32df05eb51b29a464e2435502615068565b6103ee60007f3fc394ec90f88dd7e18c46ffeef55f1b6719a2027f4ae9fbc4ab118271891200610cf2565b6103ee60007f5066de352c02692985a663f298a4534cb506e7947f703135018b6c3e10f82e00610cf2565b6103ee610e106114b1565b6139706118c160036114d1565b602061397b60405190565b63351eba2760e21b815291829060049082905afa8015611933576103ee916000916139aa575b50612bc8613958565b6139c3915060203d602011611ede57611ed0818361060f565b386139a1565b610395906139d86119b2613de3565b61039590615093565b610395906139c9565b6103ee7f76d8021c4b979e99674b80f4e0cc10154af0e5f32df05eb51b29a464e2435502610ca6565b6103ee60007fa715e0242b72e6c41603cf400167fb9f6392ccc61630d77addc87403bc041800610cf2565b6103ee6001600080516020616dde833981519152610cf2565b906103959291613a686119b2613de3565b613b25565b613a7760236112fb565b7f353332307c4163636f756e743a207472616e73616374696f6e206e6f7420666f6020820152621d5b9960ea1b604082015290565b6103ee613a6d565b6103ee613aac565b613ac6603b6112fb565b7f353332317c4163636f756e743a206e657720616d6f756e74206973206571756160208201527f6c206f7220686967686572207468616e20617574686f72697a65640000000000604082015290565b6103ee613abc565b6103ee613b15565b90611a2b611a21611a1b7f69cb00da9d035cbf84d93e5abc808a960d34e0da15bbddbda1e24f1b38bab89993613b5f6103ee8260066114be565b613c1c6122d56129bf8a613b7285610ca6565b613b89613b7f60006114b1565b8211611721613ab4565b613bac8c61229d6119c5613b9f60018b016114d1565b926001600160a01b031690565b613bba818310611721613b1d565b6122d1613c15613bd3613bcd6009610ca6565b84611ff2565b611ea5613c0e613c07613bee613be7612005565b8095612026565b93613c02613bfc6009610ca6565b8a611ff2565b612026565b928661216e565b918661216e565b8d896144e9565b87613c2760006114b1565b8103613c3f575050611a1660006122f98360066114be565b611a1691612157565b906103959291613a57565b61039590613c626119b2613de3565b6118647f7c8919e8b0586f5fc7dfabcfce8ecf5465b6ac9f6aaa0bcba610c55e30dad8c3916103b2816009612157565b61039590613c53565b6103ee6000600080516020616dde833981519152612285565b906103ee9291613cc56119b2613de3565b92919250613cec613ce1612b41600461076f6000956005610bd8565b93612bc88386614759565b90613cfa6118c160036114d1565b6020613d0560405190565b63659bf9d960e11b815291829060049082905afa80156119335761039593613d34926000926119025750613f43565b80946147d4565b6103ee91906000613cb4565b613d596020611e366118c160006114d1565b03915afa801561193357613d7a91600091613dc4575b50612bc86007610ca6565b90613d856008610ca6565b90819015613dab575b50808210613d9f576103ee91611e12565b50506103ee60006114b1565b613dbe9150613db8613a3e565b9061216e565b38613d8e565b613ddd915060203d602011611ede57611ed0818361060f565b38613d6f565b613dec33612ef3565b80613e06575b15613e0257601436033560601c90565b3390565b5036613e1561202c60146114b1565b1015613df2565b613e2581610c11565b9081613e2f575090565b6103ee9150614720565b613e4360236112fb565b7f353536317c43617264733a2063617264206973206e6f7420696e697469616c696020820152621e995960ea1b604082015290565b6103ee613e39565b6103ee613e78565b90613eaa6001610395949361076f613ea260008301610bfb565b611721613e80565b615241565b613eb9601d6112fb565b7f353430327c446562743a206e6f2066756e647320617661696c61626c65000000602082015290565b6103ee613eaf565b6103ee613ee2565b613efc60256112fb565b7f353430337c446562743a20616d6f756e7420697320686967686572207468616e602082015264081919589d60da1b604082015290565b6103ee613ef2565b6103ee613f33565b91907f75aec94f6ad949cfd9728eb818639f1b0b882089b480409ab73245c06469eef490613fee613fc5600080516020616dfe83398151915295613f85611655565b613fc0613fb4613f948a610ca6565b613f9d85614706565b6103ee613faa60006114b1565b8511611721613eea565b835b1115611721613f3b565b6147c7565b948592613fe9908490613fe4613fde836122d187610ca6565b85612157565b615305565b610ca6565b90611864612a7560405190565b61400560296112fb565b7f353331307c4163636f756e743a207472616e73616374696f6e20494420616c726020820152681958591e481d5cd95960ba1b604082015290565b6103ee613ffb565b6103ee614040565b906103959493929161406183614706565b61408a6140746000610cf28560066114be565b61408161202c60006114b1565b14611721614048565b61409e6129676129626103ee846005610bd8565b83156140d4575b6140cf85856140c96140c36122606140bd6009610ca6565b89611ff2565b8761216e565b8461530f565b615477565b6140ed61345860006140e7846005610bd8565b01610c2f565b6140a5565b6140fc601c6112fb565b7f353130327c436f6d6d6f6e3a2061646472657373206973207a65726f00000000602082015290565b6103ee6140f2565b6103ee614125565b610395906141496119c56103e26000611a5f565b141561172161412d565b6103ee91369161097e565b614168602b6112fb565b7f353535307c4f776e657273686970416363657074616e63653a20696e76616c6960208201526a64207369676e617475726560a81b604082015290565b6103ee61415e565b6103ee6141a5565b6000198114611e1f5760010190565b61423d906142346119c5613b9f610395969561422e60006142027f3fc394ec90f88dd7e18c46ffeef55f1b6719a2027f4ae9fbc4ab11827189120090565b01976142286142236142138b610ca6565b61421e611308610d24565b6155ff565b615646565b92614153565b9061566f565b146117216141ad565b61424e61424982610ca6565b6141b5565b90612157565b600080516020616dde8339815191527fc04d7db2ae23be2ba46893b43d7c4af2fc045905461f3df891e1d6c4d0683ef66142d96142cf614293846114d1565b6118c16142ca6002600188019761076f6142ac8a610ca6565b996142c06142ba6000611a5f565b84611a7d565b61424e60006114b1565b615685565b926103b660405190565b0390a2565b906143016142fb6004610395959461076f613ea260008301610bfb565b91615768565b906159b6565b60609061431890615a83565b930190565b905090565b614327601f6112fb565b7f353130317c436f6d6d6f6e3a20696e73756666696369656e742066756e647300602082015290565b6103ee61431d565b6103ee614350565b6143e96143e360007f31f69201fab7912e3ec9850e3ab705964bf46d9d4276bdcbb6d05e965e5f5401949561439487614706565b6143ae6143a26103ee611e24565b885b1115611721614358565b610cf26002600080516020616dde8339815191526143ce88868301611a7d565b6143db8a60018301612157565b019182615adb565b91610726565b926142d9612a7560405190565b61440060386112fb565b7f353431307c44656c617965645769746864726177616c733a207769746864726160208201527f77616c2074696d656c6f636b206e6f7420657870726965640000000000000000604082015290565b6103ee6143f6565b6103ee61444f565b600080516020616dde8339815191527fa578b4c05763eb039caef37b2d7b949c22914c3838384c9c73cefb78c4a8ed0a6142d96142cf61449e846114d1565b6144df6142ca6002600188019761076f6144b78a610ca6565b996144cc6144c66103ee611e24565b8c6143a4565b6142c06144d76138d9565b611721614457565b6118c18582615afa565b6144fd600461076f61039595946005610bd8565b9161453a614534600161452e6145266145218361451b8960066114be565b016114e7565b61332d565b9560066114be565b016114fd565b93614741565b615b37565b610395615b72565b61039561453f565b906103959161455c615b72565b9061039591615d4c565b906103959161454f565b61457a60246112fb565b7f353536307c43617264733a206361726420616c726561647920696e697469616c6020820152631a5e995960e21b604082015290565b6103ee614570565b6103ee6145b0565b9060ff90611a73565b906145d96103ee611a9492151590565b82546145c0565b9069ffffffffffffffff00009060101b611a73565b906146056103ee611a949261234d565b82546145e0565b9061467e60406146766004610395956146646001600160401b03600083016146416146396123fd83610bfb565b6117216145b8565b61464c6001826145c9565b61465f6146598a51151590565b826133ef565b6145f5565b61076f60018201602088015190615db3565b920151615768565b90615de4565b6103ee9081906001600160a01b031681565b906146be61202c611a166146b960006103ee966146b1600090565b50019461071d565b614684565b615e8e565b6146cd601b6112fb565b7f353130307c436f6d6d6f6e3a20616d6f756e74206973207a65726f0000000000602082015290565b6103ee6146c3565b6103ee6146f6565b6103959061471761202c60006114b1565b116117216146fe565b61472981610bfb565b9081614733575090565b6103ee91506123fd90615ed4565b61474d600e8201610ca6565b42106103ee5760070190565b9061476660058301615068565b1561479b571561477c576103ee90600101610ca6565b6103ee90612bc86000600361479360018501610ca6565b930101610ca6565b156147b1576103ee90600101615ef7565b615ef7565b6103ee90612bc86147ac60036143136001850183565b9080821015614318575090565b916147ec906147e284615f18565b6123fd8385615f5a565b6147f4575050565b61039591615f6c565b7ff3a2c404b3362c4238317c3dad1020c2e9e984ba8df38a4a1ff18d57e92a242a90613fee600080516020616dfe833981519152613fe9614841846129a884610ca6565b82612157565b61485160336112fb565b7f353333307c4163636f756e743a2076657269666965642062616c616e6365206e6020820152726f7420657175616c20746f2062616c616e636560681b604082015290565b6103ee614847565b6103ee614896565b906148ba916020612fc26118c160006114d1565b03915afa92831561193357610395936148f89160009161491f575b506148ed6148e36007610ca6565b821461172161489e565b831115611721614358565b614910614909836122d16007610ca6565b6007612157565b61491a60006114d1565b615fbc565b614938915060203d602011611ede57611ed0818361060f565b386148d5565b61494730610726565b7f00000000000000000000000000000000000000000000000000000000000000009061497b6001600160a01b0383166119c5565b1490811561499d575b5061498b57565b60405163703e46dd60e11b8152600490fd5b90506149ad6119c5613b9f616004565b141538614984565b610395906149c46116f8613de3565b614a1e565b6149d360296112fb565b7f353337307c4163636f756e743a20756e617574686f72697a656420696d706c6560208201526836b2b73a30ba34b7b760b91b604082015290565b6103ee6149c9565b6103ee614a0e565b6020614a4891614a316118c160016114d1565b604051938492839182916316da1fb760e11b611e59565b03915afa80156119335761039591600091614a67575b50611721614a16565b614a80915060203d602011612ede57612ed0818361060f565b38614a5e565b610395906149b5565b90614a9c6118c183610726565b906020614aa860405190565b6352d1902d60e01b815292839060049082905afa60009281614b4c575b50614b065750506001614ad55750565b6116e490614ae260405190565b634c9c8ce360e01b8152918291600483016001600160a01b03909116815260200190565b909291614b146103ee612cb9565b8403614b2557610395929350616014565b6116e484614b3260405190565b632a87526960e21b81529182916004830190815260200190565b614b6691935060203d602011611ede57611ed0818361060f565b9138614ac5565b614b7630610726565b614ba86001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166119c5565b0361498b57565b9261422e9192614c33614c266142236103ee97614bca600090565b507f5066de352c02692985a663f298a4534cb506e7947f703135018b6c3e10f82e0097614c21906125a4614bfd8b610ca6565b91614c18614c09610cb0565b6001600160a01b039096168652565b15156020850152565b61610e565b9461424e61424982610ca6565b614153565b614c42602d6112fb565b7f353331327c4163636f756e743a204f5450207374617465206368616e6765206960208201526c7320696e2070726f677265737360981b604082015290565b6103ee614c38565b6103ee614c81565b614cce61039594614cc9614cab600161076f866005610bd8565b91614cb86123fd84616151565b908115614cd3575b50611721614c89565b616164565b6162a9565b905038614cc0565b634e487b7160e01b600052602260045260246000fd5b9060016002830492168015614d11575b6020831014614d0c57565b614cdb565b91607f1691614d01565b80546000939291614d38614d2e83614cf1565b8085529360200190565b9160018116908115614d8a5750600114614d5157505050565b614d649192939450600052602060002090565b916000925b818410614d765750500190565b805484840152602090930192600101614d69565b92949550505060ff1916825215156020020190565b906103ee91614d1b565b90610395614dc392614dba60405190565b93848092614d9f565b038361060f565b6103ee90614da9565b6103ee6002600080516020616e1e8339815191525b01614dca565b6103ee6003600080516020616e1e833981519152614de8565b6000614e1c91614e15600090565b5001610ca6565b614e2961202c60006114b1565b141590565b614e38602f6112fb565b7f353535317c5472616e73616374696f6e436f6e6669726d6174696f6e3a20696e60208201526e76616c6964207369676e617475726560881b604082015290565b6103ee614e2e565b6103ee614e79565b61423d90614ee86119c5613b9f610395969561422e6000614ec77fa715e0242b72e6c41603cf400167fb9f6392ccc61630d77addc87403bc04180090565b0197614228614223614ed88b610ca6565b614ee3611308610d24565b6163ce565b14611721614e81565b614efb60206112fb565b7f353536327c43617264733a2063617264206973206e6f742064697361626c6564602082015290565b6103ee614ef1565b6103ee614f24565b6103959190614f59614f5182614f4c613ea282610bfb565b615ed4565b611721614f2c565b6134a66001600160401b03826145f5565b614f7460246112fb565b7f353536327c43617264733a206361726420697320616c72656164792064697361602082015263189b195960e21b604082015290565b6103ee614f6a565b6103ee614faa565b60008091614fff61039594614ff9614ff485850192613469614fdb85610c2f565b614feb6001600160401b03612434565b14611721614fb2565b612331565b906145f5565b016133ef565b9061502061202c611a166146b960006103ee966146b1600090565b616435565b61502f601d6112fb565b7f353534317c54696d6572733a2074696d6572206e6f7420616374697665000000602082015290565b6103ee615025565b6103ee615058565b6103ee600061508e92615079600090565b50610cf261508682614e07565b611721615060565b421190565b7fb940258db5193d85cafbc591d0c29fad88d804ff8b9ab71c8f9545af2bb2c07c90613fee600080516020616dfe8339815191526150e56150df6150d683610ca6565b6103ee86614706565b84613fb6565b613fe9614841846122d184610ca6565b6150ff60276112fb565b7f353530317c44656c6179656453657474696e67733a2076616c756520616c726560208201526618591e481cd95d60ca1b604082015290565b6103ee6150f5565b6103ee615138565b906fffffffffffffffffffffffffffffffff90611a73565b6001600160801b03191690565b9061518b615185611a94926001600160801b03191690565b60801c90565b8254615148565b9061ffff60801b9060801b611a73565b610c416103ee6103ee9261ffff1690565b906151c36103ee611a94926151a2565b8254615192565b908082036151d6575050565b61039591906151f8906151f36151ed825460801b90565b8461516d565b610c48565b906151b3565b90610395916151ca565b610395916151f89060209061522e61522882516001600160801b03191690565b8561516d565b015161ffff1690565b9061039591615208565b906001820161528e81615255815460801b90565b61527b61526d61516087516001600160801b03191690565b916001600160801b03191690565b14159081156152d6575b50611721615140565b61529783616151565b156152b657610395936134696002936152af93615237565b9101612157565b61039593613469600293836152d16152af95600089016151fe565b615237565b6152e09150610c48565b6152fd6152f5610c41602087015161ffff1690565b9161ffff1690565b141538615285565b90610395916148a6565b600461076f615322929594956005610bd8565b9261532f6123fd856164f5565b908115615362575b501561534e5761534961039593614741565b61656c565b610395926153499060079061076f85858386565b905038615337565b615374601f6112fb565b7f353331337c4163636f756e743a206e6f2066756e647320746f20626c6f636b00602082015290565b6103ee61536a565b6103ee61539d565b6103ee6080610635565b9067ffffffffffffffff60a01b9060a01b611a73565b906153dd6103ee611a949261234d565b82546153b7565b9060ff60e01b9060e01b611a73565b906154036103ee611a9492151590565b82546153e4565b906154676060600161039594615424614841600087015190565b019261544361543d60208301516001600160a01b031690565b85611a7d565b61546061545a60408301516001600160401b031690565b856153cd565b0151151590565b906153f3565b906103959161540a565b61039594916122d594615488600090565b5015615575576154986001613d47565b84811061552257506155139061550c615518945b6154c36154b960006114b1565b88116117216153a5565b6155036154cf42612331565b6154f36154da6153ad565b976154e38b8a52565b6001600160a01b03166020890152565b6001600160401b03166040870152565b15156060850152565b60066114be565b61546d565b6129a86008610ca6565b9061550c615518946155378461551395980390565b615540846114b1565b7f398a399795162d7b100f484c496bd46d45b5d80499256c51a0a1c0322b32986361556d611a2189610726565b0390a36154ac565b6155139061550c615518949561559561558f6103ee611655565b826143a4565b956154ac565b6155a560226112fb565b7f4f776e657273686970416363657074616e63652875696e74323536206e6f6e63602082015261652960f01b604082015290565b6103ee61559b565b6155e96155d9565b6155fb6155f4825190565b9160200190565b2090565b6155e961563a9161560e600090565b50615622600061561c6155e1565b92015190565b9061562c60405190565b9384926020840192836128d5565b9081038252038261060f565b6103ee906156526165af565b6042916040519161190160f01b8352600283015260228201522090565b6103ee9161567c916165b7565b90929192616652565b6103959060006152af816114b1565b61569c610c52565b906000825260006020830152565b6103ee615694565b6156ba610d24565b9060008252565b6103ee6156b2565b6156d1610d4a565b906000825260208080808086016156e66156aa565b8152016156f16156aa565b8152016156fc6156c1565b8152016000905250565b6103ee6156c9565b615718602e6112fb565b7f353532347c4163636f756e744c696d6974733a207370656e64206c696d69742060208201526d706572696f64206973207a65726f60901b604082015290565b6103ee61570e565b6103ee615758565b615770615706565b506103ee6060820191615854615784845190565b936157a060009561579761202c886114b1565b11611721615760565b61584d6157ad8685015190565b936158466157bc602083015190565b6157ce6157c7610c52565b918a830152565b61580a6157f060406157df8c6114b1565b956157eb876020870152565b015190565b936158036157fc610c52565b958c870152565b6020850152565b61583f615830615818610d24565b9661582c61582660016114b1565b8d8a0152565b5190565b97615839610d4a565b9a8b0152565b6020890152565b6040870152565b6060850152565b6080830152565b818103615866575050565b60016152af8184610cf261587f60006103959801610ca6565b86612157565b906103959161585b565b81810361589a575050565b60006152af816103959401610ca6565b906103959161588f565b8181036158bf575050565b60066152af81846158d861587f60006103959801610ca6565b6158e86001820160018701615885565b6158f86003820160038701615885565b610cf260058201600587016158aa565b90610395916158b4565b60016152af6020610395946157eb61587f600083015190565b9061039591615912565b60006152af8161039594015190565b9061039591615935565b60066152af60806103959461596761587f600083015190565b61597e615975602083015190565b6001870161592b565b61599561598c604083015190565b6003870161592b565b6157eb6159a3606083015190565b60058701615944565b906103959161594e565b906159c0826164f5565b156159db576152af61039593613469600e93600786016159ac565b6152af61039593613469600e93600786016159f98160008901615908565b6159ac565b90615a19615a0d610782845490565b92600052602060002090565b9060005b818110615a2a5750505090565b909192615a4e615a47600192615a3f87610ca6565b815260200190565b9460010190565b929101615a1d565b906103ee916159fe565b90610395614dc392615a7160405190565b93848092615a56565b6103ee90615a60565b60006103ee91615a91606090565b5001615a7a565b615aa260176112fb565b7f353534307c54696d6572733a207a65726f2064656c6179000000000000000000602082015290565b6103ee615a98565b6103ee615acb565b60006152af61039593613469615af0846114b1565b8211611721615ad3565b9061039591615b096007610ca6565b8211615b255761491061490983615b206007610ca6565b611e12565b614910615b3260006114b1565b614909565b929091615b44908461671b565b615b4d57505050565b615b5e906123fd83600186016167b0565b615b66575050565b610395916003016167b0565b615b7d6123fd6167dc565b615b8357565b604051631afcd79f60e31b8152600490fd5b9061039591615ba2615b72565b615cfd565b818110615bb2575050565b80615bc060006001936121a8565b01615ba7565b9190601f8111615bd557505050565b615be761039593600052602060002090565b906020601f840181900483019310615c09575b6020601f909101040190615ba7565b9091508190615bfa565b90615c1c815190565b906001600160401b03821161063057615c3f82615c398554614cf1565b85615bc6565b602090601f8311600114615c7a57611a94929160009183615c6f575b5050600019600883021c1916906002021790565b015190503880615c5b565b601f19831691615c8f85600052602060002090565b9260005b818110615ccd57509160029391856001969410615cb4575b50505002019055565b01516000196008601f8516021c19169055388080615cab565b91936020600181928787015181550195019201615c93565b9061039591615c13565b906121676103ee611a949290565b615d2f61039592615d26615d1c600080516020616e1e83398151915290565b9360028501615ce5565b60038301615ce5565b6001615d3b60006114b1565b91615d468382615cef565b01615cef565b9061039591615b95565b615d6060316112fb565b7f353530307c44656c6179656453657474696e67733a2073657474696e6720616c6020820152701c9958591e481a5b9a5d1a585b1a5e9959607a1b604082015290565b6103ee615d56565b6103ee615da3565b615dda61039592615dd1615dc96123fd85616805565b611721615dab565b60018301615237565b6002429101612157565b615e0361039592615dfa615dc96123fd85616813565b600783016159ac565b600e429101612157565b634e487b7160e01b600052603260045260246000fd5b8054821015615e4657615e3d600191600052602060002090565b91020190600090565b615e0d565b91906121a06103ee611a949390565b90815491680100000000000000008310156106305782615e8291600161039595018155615e23565b90615e4b565b90610be2565b615e9b6123fd8383616821565b15615ecd57615ec891615ec3906001615ebc84615eb88482615e5a565b5490565b9301615e88565b612157565b600190565b5050600090565b6000615ee991615ee2600090565b5001610c2f565b615ef24261346f565b111590565b615f0c6001615f0583610ca6565b9201610ca6565b808210613d9f57900390565b60058101615f2581615068565b615f2d575050565b615f54600683615f48615f436001610395970190565b61683a565b610cf26003820161683a565b90615adb565b610395919060010161684a565b61684a565b610395919060030161684a565b615f92615f8c6103ee9263ffffffff1690565b60e01b90565b6001600160e01b03191690565b6001600160a01b0390911681526040810192916103959160200152565b615fff600492615ff061039595615fd663a9059cbb615f79565b92615fe060405190565b9687946020860190815201615f9f565b6020820181038252038361060f565b61685f565b6103ee60006122856103ee612cb9565b9061601e826168e7565b61602782610726565b7fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b61605160405190565b600090a2805161606461202c60006114b1565b1115616073576118ff91616955565b5050610395616912565b61608760406112fb565b7f43617264436f6e6669726d6174696f6e2861646472657373206361726441646460208201527f726573732c626f6f6c2069734f776e65722c75696e74323536206e6f6e636529604082015290565b6103ee61607d565b6155e96160d6565b6128e861039594616105606094989795611560608086019a6000870152565b15156040830152565b6155e96161196160de565b82516001600160a01b03169061563a616140604061613a6020880151151590565b96015190565b6040519586946020860194856160e6565b600261615f91614e15600090565b421090565b61617060028201610ca6565b42106103ee5760010190565b61618660296112fb565b7f353531307c4f6e6554696d6550617373776f72643a20696e76616c6964204f54602082015268281031b7bab73a32b960b91b604082015290565b6103ee61617c565b6103ee6161c1565b60016103ee910161ffff1690565b610391906001600160a01b031660601b90565b6103919061ffff1660f01b90565b6010939261622160148361621960029561076f976161df565b0180926161f2565b0180926001600160801b0319169052565b61076f61624a92602092616244815190565b94859290565b93849101611025565b6103ee91616232565b61626660216112fb565b7f353531317c4f6e6554696d6550617373776f72643a20696e76616c6964204f546020820152600560fc1b604082015290565b6103ee61625c565b6103ee616299565b9391929091906162b885610c48565b946162cf61ffff871661ffff8416106117216161c9565b8482955b61ffff88165b61ffff8816101561634457600061631660209261630a8a8a61563a6162fd60405190565b9485938985019384616200565b60405191829182616253565b039060025afa15611933576162d961633c61633661516060005160001b90565b976161d1565b9690506162d3565b6163719192949750610395965061637793955061636861526d615160875460801b90565b146117216162a1565b8261516d565b6151b3565b61638660266112fb565b7f5472616e73616374696f6e436f6e6669726d6174696f6e2875696e74323536206020820152656e6f6e63652960d01b604082015290565b6103ee61637c565b6155e96163be565b6155e961563a916163dd600090565b50615622600061561c6163c6565b634e487b7160e01b600052603160045260246000fd5b61039591600091615e4b565b8054801561643057600019019061642d6164278383615e23565b90616401565b55565b6163eb565b90616446613fe98260018501615e88565b61645060006114b1565b81146164ed576164af6103ee926000926164a4956164a9600197889361647e616478866114b1565b82611e12565b8885019161649661648d845490565b611ea5896114b1565b8083036164b4575b50505090565b61640d565b01615e88565b6121a8565b615e826164dd6164e5946164d46164ce615ec39589615e23565b906104a9565b92839188615e23565b888801615e88565b38808061649e565b505050600090565b600e61615f91614e15600090565b61650d603b6112fb565b7f353532307c4163636f756e744c696d6974733a20616d6f756e7420657863656560208201527f64732073696e676c65207472616e73616374696f6e206c696d69740000000000604082015290565b6103ee616503565b6103ee61655c565b9161659e9061658b6165806103ee86610ca6565b841115611721616564565b61659484615f18565b6123fd83856169d0565b6165a6575050565b61039591616a4d565b6103ee616a9c565b906000916165c3825190565b6165d061202c60416114b1565b036165fa576165f392506020820151906060604084015193015160001a90616b19565b9192909190565b509050616612611a1661660d6000611a5f565b925190565b909160029190565b634e487b7160e01b600052602160045260246000fd5b6004111561663a57565b61661a565b9061039582616630565b6103ee906114b1565b61665c600061663f565b6166658261663f565b0361666e575050565b616678600161663f565b6166818261663f565b036166985760405163f645eedf60e01b8152600490fd5b6166a2600261663f565b6166ab8261663f565b036166d9576116e46166bc83616649565b60405163fce698f760e01b81529182916004830190815260200190565b6166ec6166e6600361663f565b9161663f565b146166f45750565b6116e49061670160405190565b6335e2f38360e21b81529182916004830190815260200190565b600581019061672982615068565b1561673657505050600090565b6103ee61202c91611ea56006615f0560006167519701610ca6565b101590565b616760602e6112fb565b7f353533317c5370656e644c696d6974733a20696e73756666696369656e74207360208201526d1c195b9d081d1bc818d85b98d95b60921b604082015290565b6103ee616756565b6103ee6167a0565b9061424e60016103959301916167d36167c884610ca6565b8211156117216167a8565b6122d183610ca6565b6103ee7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00612314565b6002614e1c91614e15600090565b600e614e1c91614e15600090565b614e1c916001613fe992616833600090565b5001615e88565b6103959060016152af60006114b1565b9061424e60016103959301916129a883610ca6565b61686b61687291610726565b9182616be0565b805161688161202c60006114b1565b141590816168c3575b506168925750565b6116e49061689f60405190565b635274afe760e01b8152918291600483016001600160a01b03909116815260200190565b6168e191508060206168d66123fd935190565b818301019101612d25565b3861688a565b803b6168f661202c60006114b1565b14614ad55761039590600061690c6103ee612cb9565b01611a7d565b61691c60006114b1565b341161692457565b60405163b398979f60e01b8152600490fd5b3d15616950576169453d6112fb565b903d6000602084013e565b606090565b6000806103ee93616964606090565b50602081519101845af4616976616936565b91616bf4565b61698660286112fb565b7f353532317c4163636f756e744c696d6974733a207370656e64206c696d697420602082015267195e18d95959195960c21b604082015290565b6103ee61697c565b6103ee6169c0565b61039591906169ed6169e58360018401616c64565b6117216169c8565b615f5a565b6169fc602f6112fb565b7f353532337c4163636f756e744c696d6974733a206e6f206f7470207370656e6460208201526e081b1a5b5a5d08195e18d959591959608a1b604082015290565b6103ee6169f2565b6103ee616a3d565b6103959190600301615f67616a628383616c64565b611721616a45565b909594926103959461069c611ab392616a95608096616a8e60a088019c6000890152565b6020870152565b6040850152565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6155e9616ac8616c7c565b616ad0616d00565b9061563a616add30610726565b6040519586946020860194469286616a6a565b6128e8610395946125a4606094989795616b0f608086019a6000870152565b60ff166020850152565b9091616b2484616649565b616b5061202c7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a06114b1565b11616bcc5790616b7260209460009493616b6960405190565b94859485616af0565b838052039060015afa1561193357600051600091616b8f83611a5f565b6001600160a01b0381166001600160a01b03841614616bb85750616bb2836114b1565b91929190565b915091616bc4906114b1565b909160019190565b505050616bd96000611a5f565b9160039190565b6103ee91616bee60006114b1565b91616d4f565b90616bff5750616dae565b8151616c0e61202c60006114b1565b1480616c4e575b616c1d575090565b6116e490616c2a60405190565b639996b31560e01b8152918291600483016001600160a01b03909116815260200190565b50803b616c5e61202c60006114b1565b14616c15565b61202c6103ee615ef292616c76600090565b50615ef7565b600080516020616e1e833981519152616c966103ee614dd3565b90616c9f825190565b616cac61202c60006114b1565b1115616cbe57506155fb6155f4825190565b616cc89150610ca6565b616cd260006114b1565b8114616cdb5790565b507fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47090565b600080516020616e1e833981519152616d1a6103ee614dee565b90616d23825190565b616d3061202c60006114b1565b1115616d4257506155fb6155f4825190565b616cc89150600101610ca6565b91616d5930610726565b81813110616d7d5750600082819260206103ee969551920190855af1616976616936565b6116e490616d8a60405190565b63cd78605960e01b8152918291600483016001600160a01b03909116815260200190565b8051616dbd61202c60006114b1565b1115616dcb57805190602001fd5b604051630a12f52160e11b8152600490fdfe76d8021c4b979e99674b80f4e0cc10154af0e5f32df05eb51b29a464e24355003486e95df892f06bd37fd38c44e2fee4c4efb6660a66e6eb20ed6d8a167eae00a16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100a2646970667358221220299c9946e80716a606163fc8482c2e4aa42277a57c723d628ffa5e98c614887064736f6c63430008160033"; + + private static String librariesLinkedBinary; public static final String FUNC_UPGRADE_INTERFACE_VERSION = "UPGRADE_INTERFACE_VERSION"; + public static final String FUNC_ACTIVECARDADDRESSES = "activeCardAddresses"; + + public static final String FUNC_ADDCARD = "addCard"; + + public static final String FUNC_AUTHLIMITMARGIN = "authLimitMargin"; + public static final String FUNC_AUTHORIZEDTRANSACTIONS = "authorizedTransactions"; public static final String FUNC_AVAILABLEFORDEBTPAYMENT = "availableForDebtPayment"; @@ -56,12 +76,18 @@ class TangemPaymentAccount extends Contract { public static final String FUNC_CANCELWITHDRAWAL = "cancelWithdrawal"; - public static final String FUNC_CARDWITHOTP = "cardWithOtp"; + public static final String FUNC_CARDCONFIRMATIONNONCE = "cardConfirmationNonce"; + + public static final String FUNC_CARDS = "cards"; public static final String FUNC_DEBTAMOUNT = "debtAmount"; + public static final String FUNC_DISABLECARD = "disableCard"; + public static final String FUNC_EIP712DOMAIN = "eip712Domain"; + public static final String FUNC_ENABLECARD = "enableCard"; + public static final String FUNC_FACTORY = "factory"; public static final String FUNC_INCREASEVERIFIEDBALANCE = "increaseVerifiedBalance"; @@ -76,32 +102,30 @@ class TangemPaymentAccount extends Contract { public static final String FUNC_ISWITHDRAWALREADY = "isWithdrawalReady"; - public static final String FUNC_LIMITS = "limits"; - public static final String FUNC_OWNER = "owner"; public static final String FUNC_OWNERSHIPACCEPTANCENONCE = "ownershipAcceptanceNonce"; + public static final String FUNC_PAYDEBT = "payDebt"; + public static final String FUNC_PAYMENTTOKEN = "paymentToken"; - public static final String FUNC_PENDINGREFUNDAMOUNT = "pendingRefundAmount"; - - public static final String FUNC_PENDINGREFUNDTOTAL = "pendingRefundTotal"; - - public static final String FUNC_PROCESSAUTHORIZATION = "processAuthorization"; - public static final String FUNC_PROCESSAUTHORIZATIONCHANGE = "processAuthorizationChange"; - public static final String FUNC_PROCESSAUTHORIZATIONNOOTP = "processAuthorizationNoOtp"; - public static final String FUNC_PROCESSDEBT = "processDebt"; - public static final String FUNC_PROCESSPENDINGREFUNDPAYMENT = "processPendingRefundPayment"; + public static final String FUNC_PROCESSNOCONFIRMATIONAUTHORIZATION = "processNoConfirmationAuthorization"; + + public static final String FUNC_PROCESSOTPAUTHORIZATION = "processOtpAuthorization"; public static final String FUNC_PROCESSREFUNDPAYMENT = "processRefundPayment"; public static final String FUNC_PROCESSSETTLEMENT = "processSettlement"; + public static final String FUNC_PROCESSSIGNATUREAUTHORIZATION = "processSignatureAuthorization"; + + public static final String FUNC_PROCESSUNSETTLEDTRANSACTION = "processUnsettledTransaction"; + public static final String FUNC_PROCESSWITHDRAWAL = "processWithdrawal"; public static final String FUNC_PROCESSOR = "processor"; @@ -110,11 +134,13 @@ class TangemPaymentAccount extends Contract { public static final String FUNC_REGISTRY = "registry"; - public static final String FUNC_SAVEPENDINGREFUND = "savePendingRefund"; + public static final String FUNC_REMOVEOWNER = "removeOwner"; public static final String FUNC_SECURITYDELAY = "securityDelay"; - public static final String FUNC_SETCARD = "setCard"; + public static final String FUNC_SETAUTHLIMITMARGIN = "setAuthLimitMargin"; + + public static final String FUNC_SETCARDISOWNER = "setCardIsOwner"; public static final String FUNC_SETLIMITS = "setLimits"; @@ -122,20 +148,18 @@ class TangemPaymentAccount extends Contract { public static final String FUNC_SETOWNER = "setOwner"; - public static final String FUNC_SETPROCESSOR = "setProcessor"; - public static final String FUNC_SETVERIFIEDBALANCE = "setVerifiedBalance"; - public static final String FUNC_SETTLEMENTPERIOD = "settlementPeriod"; + public static final String FUNC_TRANSACTIONCONFIRMATIONNONCE = "transactionConfirmationNonce"; public static final String FUNC_TRUSTEDFORWARDER = "trustedForwarder"; - public static final String FUNC_UNBLOCKUNSETTLEDTRANSACTION = "unblockUnsettledTransaction"; - public static final String FUNC_UPGRADETOANDCALL = "upgradeToAndCall"; public static final String FUNC_VERIFIEDBALANCE = "verifiedBalance"; + public static final String FUNC_WITHDRAWALADDRESS = "withdrawalAddress"; + public static final String FUNC_WITHDRAWALAMOUNT = "withdrawalAmount"; public static final String FUNC_WITHDRAWALREADYTIMESTAMP = "withdrawalReadyTimestamp"; @@ -143,240 +167,319 @@ class TangemPaymentAccount extends Contract { public static final String FUNC_WRITEOFFDEBT = "writeOffDebt"; public static final Event ACCOUNTSTATEAFTERSETTLEMENT_EVENT = new Event("AccountStateAfterSettlement", - Arrays.asList(new TypeReference() { - }, new TypeReference() { - }, new TypeReference() { - }, new TypeReference() { - })); + Arrays.>asList(new TypeReference() {}, new TypeReference() {}, new TypeReference() {})); + ; - public static final Event CARDSET_EVENT = new Event("CardSet", - Arrays.asList(new TypeReference

() { - }, new TypeReference() { - }, new TypeReference() { - })); + public static final Event AUTHLIMITMARGINSET_EVENT = new Event("AuthLimitMarginSet", + Arrays.>asList(new TypeReference() {})); + ; + + public static final Event CARDADDED_EVENT = new Event("CardAdded", + Arrays.>asList(new TypeReference
() {}, new TypeReference() {})); + ; + + public static final Event CARDDISABLED_EVENT = new Event("CardDisabled", + Arrays.>asList(new TypeReference
() {})); + ; + + public static final Event CARDENABLED_EVENT = new Event("CardEnabled", + Arrays.>asList(new TypeReference
() {}, new TypeReference() {})); + ; public static final Event DEBTINCREASED_EVENT = new Event("DebtIncreased", - Arrays.asList(new TypeReference() { - }, new TypeReference() { - })); + Arrays.>asList(new TypeReference() {}, new TypeReference() {})); + ; public static final Event DEBTPAID_EVENT = new Event("DebtPaid", - Arrays.asList(new TypeReference() { - }, new TypeReference() { - })); + Arrays.>asList(new TypeReference() {}, new TypeReference() {})); + ; public static final Event DEBTWRITTENOFF_EVENT = new Event("DebtWrittenOff", - Arrays.asList(new TypeReference() { - }, new TypeReference() { - })); + Arrays.>asList(new TypeReference() {}, new TypeReference() {})); + ; public static final Event EIP712DOMAINCHANGED_EVENT = new Event("EIP712DomainChanged", - List.of()); + Arrays.>asList()); + ; public static final Event INITIALIZED_EVENT = new Event("Initialized", - List.of(new TypeReference() { - })); + Arrays.>asList(new TypeReference() {})); + ; public static final Event INSUFFICIENTFUNDSONFORCEDAUTH_EVENT = new Event("InsufficientFundsOnForcedAuth", - Arrays.asList(new TypeReference(true) { - }, new TypeReference() { - })); + Arrays.>asList(new TypeReference(true) {}, new TypeReference
(true) {}, new TypeReference() {})); + ; public static final Event LIMITSSET_EVENT = new Event("LimitsSet", - Arrays.asList(new TypeReference() { - }, new TypeReference() { - }, new TypeReference() { - }, new TypeReference() { - })); - - public static final Event NOOTPTRANSACTIONAUTHORIZED_EVENT = new Event("NoOtpTransactionAuthorized", - Arrays.asList(new TypeReference(true) { - }, new TypeReference() { - })); + Arrays.>asList(new TypeReference
() {}, new TypeReference() {})); + ; public static final Event OTPSTATESET_EVENT = new Event("OtpStateSet", - Arrays.asList(new TypeReference() { - }, new TypeReference() { - })); + Arrays.>asList(new TypeReference
() {}, new TypeReference() {})); + ; + + public static final Event OWNERREMOVED_EVENT = new Event("OwnerRemoved", + Arrays.>asList(new TypeReference
() {})); + ; public static final Event OWNERSET_EVENT = new Event("OwnerSet", - List.of(new TypeReference
() { - })); - - public static final Event PENDINGREFUNDSAVED_EVENT = new Event("PendingRefundSaved", - Arrays.asList(new TypeReference(true) { - }, new TypeReference() { - })); + Arrays.>asList(new TypeReference
() {})); + ; public static final Event PROCESSORSET_EVENT = new Event("ProcessorSet", - Arrays.asList(new TypeReference
() { - }, new TypeReference
() { - })); + Arrays.>asList(new TypeReference
() {}, new TypeReference
() {})); + ; public static final Event REFUNDPAID_EVENT = new Event("RefundPaid", - Arrays.asList(new TypeReference(true) { - }, new TypeReference() { - })); + Arrays.>asList(new TypeReference(true) {}, new TypeReference
(true) {}, new TypeReference() {})); + ; public static final Event TRANSACTIONAMOUNTCHANGED_EVENT = new Event("TransactionAmountChanged", - Arrays.asList(new TypeReference(true) { - }, new TypeReference() { - })); + Arrays.>asList(new TypeReference(true) {}, new TypeReference
(true) {}, new TypeReference() {})); + ; - public static final Event TRANSACTIONAUTHORIZED_EVENT = new Event("TransactionAuthorized", - Arrays.asList(new TypeReference(true) { - }, new TypeReference() { - }, new TypeReference() { - }, new TypeReference() { - })); + public static final Event TRANSACTIONAUTHORIZEDNOCONFIRMATION_EVENT = new Event("TransactionAuthorizedNoConfirmation", + Arrays.>asList(new TypeReference(true) {}, new TypeReference
(true) {}, new TypeReference() {})); + ; + + public static final Event TRANSACTIONAUTHORIZEDWITHOTP_EVENT = new Event("TransactionAuthorizedWithOtp", + Arrays.>asList(new TypeReference(true) {}, new TypeReference
(true) {}, new TypeReference() {}, new TypeReference() {}, new TypeReference() {})); + ; + + public static final Event TRANSACTIONAUTHORIZEDWITHSIGNATURE_EVENT = new Event("TransactionAuthorizedWithSignature", + Arrays.>asList(new TypeReference(true) {}, new TypeReference
(true) {}, new TypeReference() {}, new TypeReference() {})); + ; public static final Event TRANSACTIONSETTLED_EVENT = new Event("TransactionSettled", - Arrays.asList(new TypeReference(true) { - }, new TypeReference() { - }, new TypeReference() { - })); + Arrays.>asList(new TypeReference(true) {}, new TypeReference
(true) {}, new TypeReference() {}, new TypeReference() {})); + ; public static final Event UNSETTLEDTRANSACTIONUNBLOCKED_EVENT = new Event("UnsettledTransactionUnblocked", - Arrays.asList(new TypeReference(true) { - }, new TypeReference() { - })); + Arrays.>asList(new TypeReference(true) {}, new TypeReference
(true) {}, new TypeReference() {})); + ; public static final Event UPGRADED_EVENT = new Event("Upgraded", - List.of(new TypeReference
(true) { - })); + Arrays.>asList(new TypeReference
(true) {})); + ; public static final Event VERIFIEDBALANCEINCREASED_EVENT = new Event("VerifiedBalanceIncreased", - Arrays.asList(new TypeReference() { - }, new TypeReference() { - })); + Arrays.>asList(new TypeReference() {}, new TypeReference() {})); + ; public static final Event VERIFIEDBALANCESET_EVENT = new Event("VerifiedBalanceSet", - List.of(new TypeReference() { - })); + Arrays.>asList(new TypeReference() {})); + ; public static final Event WITHDRAWALCANCELED_EVENT = new Event("WithdrawalCanceled", - List.of()); + Arrays.>asList(new TypeReference
(true) {}, new TypeReference() {})); + ; public static final Event WITHDRAWALCOMPLETE_EVENT = new Event("WithdrawalComplete", - Arrays.asList(new TypeReference
(true) { - }, new TypeReference() { - })); + Arrays.>asList(new TypeReference
(true) {}, new TypeReference() {})); + ; public static final Event WITHDRAWALINITIATED_EVENT = new Event("WithdrawalInitiated", - Arrays.asList(new TypeReference() { - }, new TypeReference() { - })); + Arrays.>asList(new TypeReference
(true) {}, new TypeReference() {}, new TypeReference() {})); + ; @Deprecated - protected TangemPaymentAccount(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + protected TangemPaymentAccount(String contractAddress, Web3j web3j, Credentials credentials, + BigInteger gasPrice, BigInteger gasLimit) { super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); } - protected TangemPaymentAccount(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { + protected TangemPaymentAccount(String contractAddress, Web3j web3j, Credentials credentials, + ContractGasProvider contractGasProvider) { super(BINARY, contractAddress, web3j, credentials, contractGasProvider); } @Deprecated - protected TangemPaymentAccount(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) { + protected TangemPaymentAccount(String contractAddress, Web3j web3j, + TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) { super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); } - protected TangemPaymentAccount(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { + protected TangemPaymentAccount(String contractAddress, Web3j web3j, + TransactionManager transactionManager, ContractGasProvider contractGasProvider) { super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); } - public static List getAccountStateAfterSettlementEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(ACCOUNTSTATEAFTERSETTLEMENT_EVENT, transactionReceipt); + public static List getAccountStateAfterSettlementEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(ACCOUNTSTATEAFTERSETTLEMENT_EVENT, transactionReceipt); ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { + for (Contract.EventValuesWithLog eventValues : valueList) { AccountStateAfterSettlementEventResponse typedResponse = new AccountStateAfterSettlementEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.balance = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); typedResponse.blockedAmount = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); typedResponse.debtTotal = (BigInteger) eventValues.getNonIndexedValues().get(2).getValue(); - typedResponse.pendingRefundTotal = (BigInteger) eventValues.getNonIndexedValues().get(3).getValue(); responses.add(typedResponse); } return responses; } - public static AccountStateAfterSettlementEventResponse getAccountStateAfterSettlementEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(ACCOUNTSTATEAFTERSETTLEMENT_EVENT, log); + public static AccountStateAfterSettlementEventResponse getAccountStateAfterSettlementEventFromLog( + Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(ACCOUNTSTATEAFTERSETTLEMENT_EVENT, log); AccountStateAfterSettlementEventResponse typedResponse = new AccountStateAfterSettlementEventResponse(); typedResponse.log = log; typedResponse.balance = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); typedResponse.blockedAmount = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); typedResponse.debtTotal = (BigInteger) eventValues.getNonIndexedValues().get(2).getValue(); - typedResponse.pendingRefundTotal = (BigInteger) eventValues.getNonIndexedValues().get(3).getValue(); return typedResponse; } - public static CardSetEventResponse getCardSetEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(CARDSET_EVENT, log); - CardSetEventResponse typedResponse = new CardSetEventResponse(); + public Flowable accountStateAfterSettlementEventFlowable( + EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getAccountStateAfterSettlementEventFromLog(log)); + } + + public Flowable accountStateAfterSettlementEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(ACCOUNTSTATEAFTERSETTLEMENT_EVENT)); + return accountStateAfterSettlementEventFlowable(filter); + } + + public static List getAuthLimitMarginSetEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(AUTHLIMITMARGINSET_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + AuthLimitMarginSetEventResponse typedResponse = new AuthLimitMarginSetEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.authLimitMargin = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public static AuthLimitMarginSetEventResponse getAuthLimitMarginSetEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(AUTHLIMITMARGINSET_EVENT, log); + AuthLimitMarginSetEventResponse typedResponse = new AuthLimitMarginSetEventResponse(); typedResponse.log = log; - typedResponse.card = (String) eventValues.getNonIndexedValues().get(0).getValue(); - typedResponse.otpRoot = (byte[]) eventValues.getNonIndexedValues().get(1).getValue(); - typedResponse.otpCounter = (BigInteger) eventValues.getNonIndexedValues().get(2).getValue(); + typedResponse.authLimitMargin = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); return typedResponse; } - public static DebtIncreasedEventResponse getDebtIncreasedEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(DEBTINCREASED_EVENT, log); - DebtIncreasedEventResponse typedResponse = new DebtIncreasedEventResponse(); + public Flowable authLimitMarginSetEventFlowable( + EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getAuthLimitMarginSetEventFromLog(log)); + } + + public Flowable authLimitMarginSetEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(AUTHLIMITMARGINSET_EVENT)); + return authLimitMarginSetEventFlowable(filter); + } + + public static List getCardAddedEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(CARDADDED_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + CardAddedEventResponse typedResponse = new CardAddedEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.cardAddress = (String) eventValues.getNonIndexedValues().get(0).getValue(); + typedResponse.cardData = (CardParams) eventValues.getNonIndexedValues().get(1); + responses.add(typedResponse); + } + return responses; + } + + public static CardAddedEventResponse getCardAddedEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(CARDADDED_EVENT, log); + CardAddedEventResponse typedResponse = new CardAddedEventResponse(); typedResponse.log = log; - typedResponse.increase = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - typedResponse.debtAmount = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); + typedResponse.cardAddress = (String) eventValues.getNonIndexedValues().get(0).getValue(); + typedResponse.cardData = (CardParams) eventValues.getNonIndexedValues().get(1); return typedResponse; } - public static List getCardSetEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(CARDSET_EVENT, transactionReceipt); - ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { - CardSetEventResponse typedResponse = new CardSetEventResponse(); + public Flowable cardAddedEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getCardAddedEventFromLog(log)); + } + + public Flowable cardAddedEventFlowable(DefaultBlockParameter startBlock, + DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(CARDADDED_EVENT)); + return cardAddedEventFlowable(filter); + } + + public static List getCardDisabledEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(CARDDISABLED_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + CardDisabledEventResponse typedResponse = new CardDisabledEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.card = (String) eventValues.getNonIndexedValues().get(0).getValue(); - typedResponse.otpRoot = (byte[]) eventValues.getNonIndexedValues().get(1).getValue(); - typedResponse.otpCounter = (BigInteger) eventValues.getNonIndexedValues().get(2).getValue(); responses.add(typedResponse); } return responses; } - public static DebtPaidEventResponse getDebtPaidEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(DEBTPAID_EVENT, log); - DebtPaidEventResponse typedResponse = new DebtPaidEventResponse(); + public static CardDisabledEventResponse getCardDisabledEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(CARDDISABLED_EVENT, log); + CardDisabledEventResponse typedResponse = new CardDisabledEventResponse(); typedResponse.log = log; - typedResponse.paid = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - typedResponse.debtLeft = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); + typedResponse.card = (String) eventValues.getNonIndexedValues().get(0).getValue(); return typedResponse; } - public static DebtWrittenOffEventResponse getDebtWrittenOffEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(DEBTWRITTENOFF_EVENT, log); - DebtWrittenOffEventResponse typedResponse = new DebtWrittenOffEventResponse(); - typedResponse.log = log; - typedResponse.writtenOff = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - typedResponse.debtLeft = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); - return typedResponse; + public Flowable cardDisabledEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getCardDisabledEventFromLog(log)); } - public static List getEIP712DomainChangedEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(EIP712DOMAINCHANGED_EVENT, transactionReceipt); - ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { - EIP712DomainChangedEventResponse typedResponse = new EIP712DomainChangedEventResponse(); + public Flowable cardDisabledEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(CARDDISABLED_EVENT)); + return cardDisabledEventFlowable(filter); + } + + public static List getCardEnabledEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(CARDENABLED_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + CardEnabledEventResponse typedResponse = new CardEnabledEventResponse(); typedResponse.log = eventValues.getLog(); + typedResponse.card = (String) eventValues.getNonIndexedValues().get(0).getValue(); + typedResponse.isOwner = (Boolean) eventValues.getNonIndexedValues().get(1).getValue(); responses.add(typedResponse); } return responses; } - public static List getDebtIncreasedEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(DEBTINCREASED_EVENT, transactionReceipt); + public static CardEnabledEventResponse getCardEnabledEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(CARDENABLED_EVENT, log); + CardEnabledEventResponse typedResponse = new CardEnabledEventResponse(); + typedResponse.log = log; + typedResponse.card = (String) eventValues.getNonIndexedValues().get(0).getValue(); + typedResponse.isOwner = (Boolean) eventValues.getNonIndexedValues().get(1).getValue(); + return typedResponse; + } + + public Flowable cardEnabledEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getCardEnabledEventFromLog(log)); + } + + public Flowable cardEnabledEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(CARDENABLED_EVENT)); + return cardEnabledEventFlowable(filter); + } + + public static List getDebtIncreasedEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(DEBTINCREASED_EVENT, transactionReceipt); ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { + for (Contract.EventValuesWithLog eventValues : valueList) { DebtIncreasedEventResponse typedResponse = new DebtIncreasedEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.increase = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); @@ -386,34 +489,31 @@ class TangemPaymentAccount extends Contract { return responses; } - public static EIP712DomainChangedEventResponse getEIP712DomainChangedEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(EIP712DOMAINCHANGED_EVENT, log); - EIP712DomainChangedEventResponse typedResponse = new EIP712DomainChangedEventResponse(); + public static DebtIncreasedEventResponse getDebtIncreasedEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(DEBTINCREASED_EVENT, log); + DebtIncreasedEventResponse typedResponse = new DebtIncreasedEventResponse(); typedResponse.log = log; + typedResponse.increase = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + typedResponse.debtAmount = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); return typedResponse; } - public static InitializedEventResponse getInitializedEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(INITIALIZED_EVENT, log); - InitializedEventResponse typedResponse = new InitializedEventResponse(); - typedResponse.log = log; - typedResponse.version = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; + public Flowable debtIncreasedEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getDebtIncreasedEventFromLog(log)); } - public static InsufficientFundsOnForcedAuthEventResponse getInsufficientFundsOnForcedAuthEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(INSUFFICIENTFUNDSONFORCEDAUTH_EVENT, log); - InsufficientFundsOnForcedAuthEventResponse typedResponse = new InsufficientFundsOnForcedAuthEventResponse(); - typedResponse.log = log; - typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.insufficientAmount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; + public Flowable debtIncreasedEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(DEBTINCREASED_EVENT)); + return debtIncreasedEventFlowable(filter); } - public static List getDebtPaidEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(DEBTPAID_EVENT, transactionReceipt); + public static List getDebtPaidEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(DEBTPAID_EVENT, transactionReceipt); ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { + for (Contract.EventValuesWithLog eventValues : valueList) { DebtPaidEventResponse typedResponse = new DebtPaidEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.paid = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); @@ -423,39 +523,31 @@ class TangemPaymentAccount extends Contract { return responses; } - public static LimitsSetEventResponse getLimitsSetEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(LIMITSSET_EVENT, log); - LimitsSetEventResponse typedResponse = new LimitsSetEventResponse(); + public static DebtPaidEventResponse getDebtPaidEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(DEBTPAID_EVENT, log); + DebtPaidEventResponse typedResponse = new DebtPaidEventResponse(); typedResponse.log = log; - typedResponse.singleTransactionLimit = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - typedResponse.spendLimit = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); - typedResponse.noOtpSpendLimit = (BigInteger) eventValues.getNonIndexedValues().get(2).getValue(); - typedResponse.spendLimitsPeriod = (BigInteger) eventValues.getNonIndexedValues().get(3).getValue(); + typedResponse.paid = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + typedResponse.debtLeft = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); return typedResponse; } - public static NoOtpTransactionAuthorizedEventResponse getNoOtpTransactionAuthorizedEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(NOOTPTRANSACTIONAUTHORIZED_EVENT, log); - NoOtpTransactionAuthorizedEventResponse typedResponse = new NoOtpTransactionAuthorizedEventResponse(); - typedResponse.log = log; - typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; + public Flowable debtPaidEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getDebtPaidEventFromLog(log)); } - public static OtpStateSetEventResponse getOtpStateSetEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(OTPSTATESET_EVENT, log); - OtpStateSetEventResponse typedResponse = new OtpStateSetEventResponse(); - typedResponse.log = log; - typedResponse.otpRoot = (byte[]) eventValues.getNonIndexedValues().get(0).getValue(); - typedResponse.otpCounter = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); - return typedResponse; + public Flowable debtPaidEventFlowable(DefaultBlockParameter startBlock, + DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(DEBTPAID_EVENT)); + return debtPaidEventFlowable(filter); } - public static List getDebtWrittenOffEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(DEBTWRITTENOFF_EVENT, transactionReceipt); + public static List getDebtWrittenOffEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(DEBTWRITTENOFF_EVENT, transactionReceipt); ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { + for (Contract.EventValuesWithLog eventValues : valueList) { DebtWrittenOffEventResponse typedResponse = new DebtWrittenOffEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.writtenOff = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); @@ -465,10 +557,232 @@ class TangemPaymentAccount extends Contract { return responses; } - public static List getOwnerSetEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(OWNERSET_EVENT, transactionReceipt); + public static DebtWrittenOffEventResponse getDebtWrittenOffEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(DEBTWRITTENOFF_EVENT, log); + DebtWrittenOffEventResponse typedResponse = new DebtWrittenOffEventResponse(); + typedResponse.log = log; + typedResponse.writtenOff = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + typedResponse.debtLeft = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); + return typedResponse; + } + + public Flowable debtWrittenOffEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getDebtWrittenOffEventFromLog(log)); + } + + public Flowable debtWrittenOffEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(DEBTWRITTENOFF_EVENT)); + return debtWrittenOffEventFlowable(filter); + } + + public static List getEIP712DomainChangedEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(EIP712DOMAINCHANGED_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + EIP712DomainChangedEventResponse typedResponse = new EIP712DomainChangedEventResponse(); + typedResponse.log = eventValues.getLog(); + responses.add(typedResponse); + } + return responses; + } + + public static EIP712DomainChangedEventResponse getEIP712DomainChangedEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(EIP712DOMAINCHANGED_EVENT, log); + EIP712DomainChangedEventResponse typedResponse = new EIP712DomainChangedEventResponse(); + typedResponse.log = log; + return typedResponse; + } + + public Flowable eIP712DomainChangedEventFlowable( + EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getEIP712DomainChangedEventFromLog(log)); + } + + public Flowable eIP712DomainChangedEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(EIP712DOMAINCHANGED_EVENT)); + return eIP712DomainChangedEventFlowable(filter); + } + + public static List getInitializedEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(INITIALIZED_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + InitializedEventResponse typedResponse = new InitializedEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.version = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public static InitializedEventResponse getInitializedEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(INITIALIZED_EVENT, log); + InitializedEventResponse typedResponse = new InitializedEventResponse(); + typedResponse.log = log; + typedResponse.version = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + + public Flowable initializedEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getInitializedEventFromLog(log)); + } + + public Flowable initializedEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(INITIALIZED_EVENT)); + return initializedEventFlowable(filter); + } + + public static List getInsufficientFundsOnForcedAuthEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(INSUFFICIENTFUNDSONFORCEDAUTH_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + InsufficientFundsOnForcedAuthEventResponse typedResponse = new InsufficientFundsOnForcedAuthEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.insufficientAmount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public static InsufficientFundsOnForcedAuthEventResponse getInsufficientFundsOnForcedAuthEventFromLog( + Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(INSUFFICIENTFUNDSONFORCEDAUTH_EVENT, log); + InsufficientFundsOnForcedAuthEventResponse typedResponse = new InsufficientFundsOnForcedAuthEventResponse(); + typedResponse.log = log; + typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.insufficientAmount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + + public Flowable insufficientFundsOnForcedAuthEventFlowable( + EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getInsufficientFundsOnForcedAuthEventFromLog(log)); + } + + public Flowable insufficientFundsOnForcedAuthEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(INSUFFICIENTFUNDSONFORCEDAUTH_EVENT)); + return insufficientFundsOnForcedAuthEventFlowable(filter); + } + + public static List getLimitsSetEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(LIMITSSET_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + LimitsSetEventResponse typedResponse = new LimitsSetEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.card = (String) eventValues.getNonIndexedValues().get(0).getValue(); + typedResponse.limitsParams = (LimitsParams) eventValues.getNonIndexedValues().get(1); + responses.add(typedResponse); + } + return responses; + } + + public static LimitsSetEventResponse getLimitsSetEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(LIMITSSET_EVENT, log); + LimitsSetEventResponse typedResponse = new LimitsSetEventResponse(); + typedResponse.log = log; + typedResponse.card = (String) eventValues.getNonIndexedValues().get(0).getValue(); + typedResponse.limitsParams = (LimitsParams) eventValues.getNonIndexedValues().get(1); + return typedResponse; + } + + public Flowable limitsSetEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getLimitsSetEventFromLog(log)); + } + + public Flowable limitsSetEventFlowable(DefaultBlockParameter startBlock, + DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(LIMITSSET_EVENT)); + return limitsSetEventFlowable(filter); + } + + public static List getOtpStateSetEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(OTPSTATESET_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + OtpStateSetEventResponse typedResponse = new OtpStateSetEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.card = (String) eventValues.getNonIndexedValues().get(0).getValue(); + typedResponse.otpState = (OtpState) eventValues.getNonIndexedValues().get(1); + responses.add(typedResponse); + } + return responses; + } + + public static OtpStateSetEventResponse getOtpStateSetEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(OTPSTATESET_EVENT, log); + OtpStateSetEventResponse typedResponse = new OtpStateSetEventResponse(); + typedResponse.log = log; + typedResponse.card = (String) eventValues.getNonIndexedValues().get(0).getValue(); + typedResponse.otpState = (OtpState) eventValues.getNonIndexedValues().get(1); + return typedResponse; + } + + public Flowable otpStateSetEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getOtpStateSetEventFromLog(log)); + } + + public Flowable otpStateSetEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(OTPSTATESET_EVENT)); + return otpStateSetEventFlowable(filter); + } + + public static List getOwnerRemovedEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(OWNERREMOVED_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + OwnerRemovedEventResponse typedResponse = new OwnerRemovedEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.previousOwner = (String) eventValues.getNonIndexedValues().get(0).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public static OwnerRemovedEventResponse getOwnerRemovedEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(OWNERREMOVED_EVENT, log); + OwnerRemovedEventResponse typedResponse = new OwnerRemovedEventResponse(); + typedResponse.log = log; + typedResponse.previousOwner = (String) eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + + public Flowable ownerRemovedEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getOwnerRemovedEventFromLog(log)); + } + + public Flowable ownerRemovedEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(OWNERREMOVED_EVENT)); + return ownerRemovedEventFlowable(filter); + } + + public static List getOwnerSetEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(OWNERSET_EVENT, transactionReceipt); ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { + for (Contract.EventValuesWithLog eventValues : valueList) { OwnerSetEventResponse typedResponse = new OwnerSetEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.owner = (String) eventValues.getNonIndexedValues().get(0).getValue(); @@ -478,277 +792,29 @@ class TangemPaymentAccount extends Contract { } public static OwnerSetEventResponse getOwnerSetEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(OWNERSET_EVENT, log); + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(OWNERSET_EVENT, log); OwnerSetEventResponse typedResponse = new OwnerSetEventResponse(); typedResponse.log = log; typedResponse.owner = (String) eventValues.getNonIndexedValues().get(0).getValue(); return typedResponse; } - public static PendingRefundSavedEventResponse getPendingRefundSavedEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(PENDINGREFUNDSAVED_EVENT, log); - PendingRefundSavedEventResponse typedResponse = new PendingRefundSavedEventResponse(); - typedResponse.log = log; - typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; + public Flowable ownerSetEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getOwnerSetEventFromLog(log)); } - public static ProcessorSetEventResponse getProcessorSetEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(PROCESSORSET_EVENT, log); - ProcessorSetEventResponse typedResponse = new ProcessorSetEventResponse(); - typedResponse.log = log; - typedResponse.processor = (String) eventValues.getNonIndexedValues().get(0).getValue(); - typedResponse.paymentToken = (String) eventValues.getNonIndexedValues().get(1).getValue(); - return typedResponse; - } - - public static RefundPaidEventResponse getRefundPaidEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(REFUNDPAID_EVENT, log); - RefundPaidEventResponse typedResponse = new RefundPaidEventResponse(); - typedResponse.log = log; - typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; - } - - public static TransactionAmountChangedEventResponse getTransactionAmountChangedEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(TRANSACTIONAMOUNTCHANGED_EVENT, log); - TransactionAmountChangedEventResponse typedResponse = new TransactionAmountChangedEventResponse(); - typedResponse.log = log; - typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.newAmount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; - } - - public static TransactionAuthorizedEventResponse getTransactionAuthorizedEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(TRANSACTIONAUTHORIZED_EVENT, log); - TransactionAuthorizedEventResponse typedResponse = new TransactionAuthorizedEventResponse(); - typedResponse.log = log; - typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - typedResponse.otp = (byte[]) eventValues.getNonIndexedValues().get(1).getValue(); - typedResponse.otpCounter = (BigInteger) eventValues.getNonIndexedValues().get(2).getValue(); - return typedResponse; - } - - public static List getInitializedEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(INITIALIZED_EVENT, transactionReceipt); - ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { - InitializedEventResponse typedResponse = new InitializedEventResponse(); - typedResponse.log = eventValues.getLog(); - typedResponse.version = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - responses.add(typedResponse); - } - return responses; - } - - public static TransactionSettledEventResponse getTransactionSettledEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(TRANSACTIONSETTLED_EVENT, log); - TransactionSettledEventResponse typedResponse = new TransactionSettledEventResponse(); - typedResponse.log = log; - typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.settlementAmount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - typedResponse.paymentAmount = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); - return typedResponse; - } - - public static UnsettledTransactionUnblockedEventResponse getUnsettledTransactionUnblockedEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(UNSETTLEDTRANSACTIONUNBLOCKED_EVENT, log); - UnsettledTransactionUnblockedEventResponse typedResponse = new UnsettledTransactionUnblockedEventResponse(); - typedResponse.log = log; - typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; - } - - public static UpgradedEventResponse getUpgradedEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(UPGRADED_EVENT, log); - UpgradedEventResponse typedResponse = new UpgradedEventResponse(); - typedResponse.log = log; - typedResponse.implementation = (String) eventValues.getIndexedValues().get(0).getValue(); - return typedResponse; - } - - public static List getInsufficientFundsOnForcedAuthEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(INSUFFICIENTFUNDSONFORCEDAUTH_EVENT, transactionReceipt); - ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { - InsufficientFundsOnForcedAuthEventResponse typedResponse = new InsufficientFundsOnForcedAuthEventResponse(); - typedResponse.log = eventValues.getLog(); - typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.insufficientAmount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - responses.add(typedResponse); - } - return responses; - } - - public static VerifiedBalanceIncreasedEventResponse getVerifiedBalanceIncreasedEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(VERIFIEDBALANCEINCREASED_EVENT, log); - VerifiedBalanceIncreasedEventResponse typedResponse = new VerifiedBalanceIncreasedEventResponse(); - typedResponse.log = log; - typedResponse.increase = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - typedResponse.verifiedBalance = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); - return typedResponse; - } - - public static VerifiedBalanceSetEventResponse getVerifiedBalanceSetEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(VERIFIEDBALANCESET_EVENT, log); - VerifiedBalanceSetEventResponse typedResponse = new VerifiedBalanceSetEventResponse(); - typedResponse.log = log; - typedResponse.verifiedBalance = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; - } - - public static WithdrawalCanceledEventResponse getWithdrawalCanceledEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(WITHDRAWALCANCELED_EVENT, log); - WithdrawalCanceledEventResponse typedResponse = new WithdrawalCanceledEventResponse(); - typedResponse.log = log; - return typedResponse; - } - - public static List getLimitsSetEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(LIMITSSET_EVENT, transactionReceipt); - ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { - LimitsSetEventResponse typedResponse = new LimitsSetEventResponse(); - typedResponse.log = eventValues.getLog(); - typedResponse.singleTransactionLimit = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - typedResponse.spendLimit = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); - typedResponse.noOtpSpendLimit = (BigInteger) eventValues.getNonIndexedValues().get(2).getValue(); - typedResponse.spendLimitsPeriod = (BigInteger) eventValues.getNonIndexedValues().get(3).getValue(); - responses.add(typedResponse); - } - return responses; - } - - public static WithdrawalCompleteEventResponse getWithdrawalCompleteEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(WITHDRAWALCOMPLETE_EVENT, log); - WithdrawalCompleteEventResponse typedResponse = new WithdrawalCompleteEventResponse(); - typedResponse.log = log; - typedResponse.to = (String) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - return typedResponse; - } - - @Deprecated - public static TangemPaymentAccount load(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { - return new TangemPaymentAccount(contractAddress, web3j, credentials, gasPrice, gasLimit); - } - - @Deprecated - public static TangemPaymentAccount load(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) { - return new TangemPaymentAccount(contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - public static List getNoOtpTransactionAuthorizedEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(NOOTPTRANSACTIONAUTHORIZED_EVENT, transactionReceipt); - ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { - NoOtpTransactionAuthorizedEventResponse typedResponse = new NoOtpTransactionAuthorizedEventResponse(); - typedResponse.log = eventValues.getLog(); - typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - responses.add(typedResponse); - } - return responses; - } - - public static TangemPaymentAccount load(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { - return new TangemPaymentAccount(contractAddress, web3j, credentials, contractGasProvider); - } - - public static TangemPaymentAccount load(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { - return new TangemPaymentAccount(contractAddress, web3j, transactionManager, contractGasProvider); - } - - public static RemoteCall deploy(Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider, String trustedForwarder) { - String encodedConstructor = FunctionEncoder.encodeConstructor(List.of(new Address(160, trustedForwarder))); - return deployRemoteCall(TangemPaymentAccount.class, web3j, credentials, contractGasProvider, BINARY, encodedConstructor); - } - - public static List getOtpStateSetEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(OTPSTATESET_EVENT, transactionReceipt); - ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { - OtpStateSetEventResponse typedResponse = new OtpStateSetEventResponse(); - typedResponse.log = eventValues.getLog(); - typedResponse.otpRoot = (byte[]) eventValues.getNonIndexedValues().get(0).getValue(); - typedResponse.otpCounter = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); - responses.add(typedResponse); - } - return responses; - } - - public static RemoteCall deploy(Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider, String trustedForwarder) { - String encodedConstructor = FunctionEncoder.encodeConstructor(List.of(new Address(160, trustedForwarder))); - return deployRemoteCall(TangemPaymentAccount.class, web3j, transactionManager, contractGasProvider, BINARY, encodedConstructor); - } - - @Deprecated - public static RemoteCall deploy(Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit, String trustedForwarder) { - String encodedConstructor = FunctionEncoder.encodeConstructor(List.of(new Address(160, trustedForwarder))); - return deployRemoteCall(TangemPaymentAccount.class, web3j, credentials, gasPrice, gasLimit, BINARY, encodedConstructor); - } - - @Deprecated - public static RemoteCall deploy(Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit, String trustedForwarder) { - String encodedConstructor = FunctionEncoder.encodeConstructor(List.of(new Address(160, trustedForwarder))); - return deployRemoteCall(TangemPaymentAccount.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, encodedConstructor); - } - - public Flowable accountStateAfterSettlementEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getAccountStateAfterSettlementEventFromLog(log)); - } - - public Flowable accountStateAfterSettlementEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + public Flowable ownerSetEventFlowable(DefaultBlockParameter startBlock, + DefaultBlockParameter endBlock) { EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(ACCOUNTSTATEAFTERSETTLEMENT_EVENT)); - return accountStateAfterSettlementEventFlowable(filter); + filter.addSingleTopic(EventEncoder.encode(OWNERSET_EVENT)); + return ownerSetEventFlowable(filter); } - public Flowable cardSetEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getCardSetEventFromLog(log)); - } - - public Flowable cardSetEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(CARDSET_EVENT)); - return cardSetEventFlowable(filter); - } - - public static List getPendingRefundSavedEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(PENDINGREFUNDSAVED_EVENT, transactionReceipt); - ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { - PendingRefundSavedEventResponse typedResponse = new PendingRefundSavedEventResponse(); - typedResponse.log = eventValues.getLog(); - typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(0).getValue(); - typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); - responses.add(typedResponse); - } - return responses; - } - - public Flowable debtIncreasedEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getDebtIncreasedEventFromLog(log)); - } - - public Flowable debtIncreasedEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(DEBTINCREASED_EVENT)); - return debtIncreasedEventFlowable(filter); - } - - public Flowable debtPaidEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getDebtPaidEventFromLog(log)); - } - - public static List getProcessorSetEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(PROCESSORSET_EVENT, transactionReceipt); + public static List getProcessorSetEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(PROCESSORSET_EVENT, transactionReceipt); ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { + for (Contract.EventValuesWithLog eventValues : valueList) { ProcessorSetEventResponse typedResponse = new ProcessorSetEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.processor = (String) eventValues.getNonIndexedValues().get(0).getValue(); @@ -758,85 +824,147 @@ class TangemPaymentAccount extends Contract { return responses; } - public Flowable debtPaidEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + public static ProcessorSetEventResponse getProcessorSetEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(PROCESSORSET_EVENT, log); + ProcessorSetEventResponse typedResponse = new ProcessorSetEventResponse(); + typedResponse.log = log; + typedResponse.processor = (String) eventValues.getNonIndexedValues().get(0).getValue(); + typedResponse.paymentToken = (String) eventValues.getNonIndexedValues().get(1).getValue(); + return typedResponse; + } + + public Flowable processorSetEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getProcessorSetEventFromLog(log)); + } + + public Flowable processorSetEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(DEBTPAID_EVENT)); - return debtPaidEventFlowable(filter); + filter.addSingleTopic(EventEncoder.encode(PROCESSORSET_EVENT)); + return processorSetEventFlowable(filter); } - public Flowable debtWrittenOffEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getDebtWrittenOffEventFromLog(log)); - } - - public Flowable debtWrittenOffEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(DEBTWRITTENOFF_EVENT)); - return debtWrittenOffEventFlowable(filter); - } - - public static List getRefundPaidEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(REFUNDPAID_EVENT, transactionReceipt); + public static List getRefundPaidEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(REFUNDPAID_EVENT, transactionReceipt); ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { + for (Contract.EventValuesWithLog eventValues : valueList) { RefundPaidEventResponse typedResponse = new RefundPaidEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); responses.add(typedResponse); } return responses; } - public Flowable eIP712DomainChangedEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getEIP712DomainChangedEventFromLog(log)); + public static RefundPaidEventResponse getRefundPaidEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(REFUNDPAID_EVENT, log); + RefundPaidEventResponse typedResponse = new RefundPaidEventResponse(); + typedResponse.log = log; + typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; } - public Flowable eIP712DomainChangedEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + public Flowable refundPaidEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getRefundPaidEventFromLog(log)); + } + + public Flowable refundPaidEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(EIP712DOMAINCHANGED_EVENT)); - return eIP712DomainChangedEventFlowable(filter); + filter.addSingleTopic(EventEncoder.encode(REFUNDPAID_EVENT)); + return refundPaidEventFlowable(filter); } - public Flowable initializedEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getInitializedEventFromLog(log)); - } - - public static List getTransactionAmountChangedEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(TRANSACTIONAMOUNTCHANGED_EVENT, transactionReceipt); + public static List getTransactionAmountChangedEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(TRANSACTIONAMOUNTCHANGED_EVENT, transactionReceipt); ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { + for (Contract.EventValuesWithLog eventValues : valueList) { TransactionAmountChangedEventResponse typedResponse = new TransactionAmountChangedEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); typedResponse.newAmount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); responses.add(typedResponse); } return responses; } - public Flowable initializedEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + public static TransactionAmountChangedEventResponse getTransactionAmountChangedEventFromLog( + Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(TRANSACTIONAMOUNTCHANGED_EVENT, log); + TransactionAmountChangedEventResponse typedResponse = new TransactionAmountChangedEventResponse(); + typedResponse.log = log; + typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.newAmount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + + public Flowable transactionAmountChangedEventFlowable( + EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getTransactionAmountChangedEventFromLog(log)); + } + + public Flowable transactionAmountChangedEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(INITIALIZED_EVENT)); - return initializedEventFlowable(filter); + filter.addSingleTopic(EventEncoder.encode(TRANSACTIONAMOUNTCHANGED_EVENT)); + return transactionAmountChangedEventFlowable(filter); } - public Flowable insufficientFundsOnForcedAuthEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getInsufficientFundsOnForcedAuthEventFromLog(log)); - } - - public Flowable insufficientFundsOnForcedAuthEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(INSUFFICIENTFUNDSONFORCEDAUTH_EVENT)); - return insufficientFundsOnForcedAuthEventFlowable(filter); - } - - public static List getTransactionAuthorizedEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(TRANSACTIONAUTHORIZED_EVENT, transactionReceipt); - ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { - TransactionAuthorizedEventResponse typedResponse = new TransactionAuthorizedEventResponse(); + public static List getTransactionAuthorizedNoConfirmationEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(TRANSACTIONAUTHORIZEDNOCONFIRMATION_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + TransactionAuthorizedNoConfirmationEventResponse typedResponse = new TransactionAuthorizedNoConfirmationEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public static TransactionAuthorizedNoConfirmationEventResponse getTransactionAuthorizedNoConfirmationEventFromLog( + Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(TRANSACTIONAUTHORIZEDNOCONFIRMATION_EVENT, log); + TransactionAuthorizedNoConfirmationEventResponse typedResponse = new TransactionAuthorizedNoConfirmationEventResponse(); + typedResponse.log = log; + typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + + public Flowable transactionAuthorizedNoConfirmationEventFlowable( + EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getTransactionAuthorizedNoConfirmationEventFromLog(log)); + } + + public Flowable transactionAuthorizedNoConfirmationEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(TRANSACTIONAUTHORIZEDNOCONFIRMATION_EVENT)); + return transactionAuthorizedNoConfirmationEventFlowable(filter); + } + + public static List getTransactionAuthorizedWithOtpEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(TRANSACTIONAUTHORIZEDWITHOTP_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + TransactionAuthorizedWithOtpEventResponse typedResponse = new TransactionAuthorizedWithOtpEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); typedResponse.otp = (byte[]) eventValues.getNonIndexedValues().get(1).getValue(); typedResponse.otpCounter = (BigInteger) eventValues.getNonIndexedValues().get(2).getValue(); @@ -845,27 +973,80 @@ class TangemPaymentAccount extends Contract { return responses; } - public Flowable limitsSetEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getLimitsSetEventFromLog(log)); + public static TransactionAuthorizedWithOtpEventResponse getTransactionAuthorizedWithOtpEventFromLog( + Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(TRANSACTIONAUTHORIZEDWITHOTP_EVENT, log); + TransactionAuthorizedWithOtpEventResponse typedResponse = new TransactionAuthorizedWithOtpEventResponse(); + typedResponse.log = log; + typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + typedResponse.otp = (byte[]) eventValues.getNonIndexedValues().get(1).getValue(); + typedResponse.otpCounter = (BigInteger) eventValues.getNonIndexedValues().get(2).getValue(); + return typedResponse; } - public Flowable limitsSetEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + public Flowable transactionAuthorizedWithOtpEventFlowable( + EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getTransactionAuthorizedWithOtpEventFromLog(log)); + } + + public Flowable transactionAuthorizedWithOtpEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(LIMITSSET_EVENT)); - return limitsSetEventFlowable(filter); + filter.addSingleTopic(EventEncoder.encode(TRANSACTIONAUTHORIZEDWITHOTP_EVENT)); + return transactionAuthorizedWithOtpEventFlowable(filter); } - public Flowable noOtpTransactionAuthorizedEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getNoOtpTransactionAuthorizedEventFromLog(log)); + public static List getTransactionAuthorizedWithSignatureEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(TRANSACTIONAUTHORIZEDWITHSIGNATURE_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + TransactionAuthorizedWithSignatureEventResponse typedResponse = new TransactionAuthorizedWithSignatureEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + typedResponse.signature = (byte[]) eventValues.getNonIndexedValues().get(1).getValue(); + responses.add(typedResponse); + } + return responses; } - public static List getTransactionSettledEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(TRANSACTIONSETTLED_EVENT, transactionReceipt); + public static TransactionAuthorizedWithSignatureEventResponse getTransactionAuthorizedWithSignatureEventFromLog( + Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(TRANSACTIONAUTHORIZEDWITHSIGNATURE_EVENT, log); + TransactionAuthorizedWithSignatureEventResponse typedResponse = new TransactionAuthorizedWithSignatureEventResponse(); + typedResponse.log = log; + typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + typedResponse.signature = (byte[]) eventValues.getNonIndexedValues().get(1).getValue(); + return typedResponse; + } + + public Flowable transactionAuthorizedWithSignatureEventFlowable( + EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getTransactionAuthorizedWithSignatureEventFromLog(log)); + } + + public Flowable transactionAuthorizedWithSignatureEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(TRANSACTIONAUTHORIZEDWITHSIGNATURE_EVENT)); + return transactionAuthorizedWithSignatureEventFlowable(filter); + } + + public static List getTransactionSettledEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(TRANSACTIONSETTLED_EVENT, transactionReceipt); ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { + for (Contract.EventValuesWithLog eventValues : valueList) { TransactionSettledEventResponse typedResponse = new TransactionSettledEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); typedResponse.settlementAmount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); typedResponse.paymentAmount = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); responses.add(typedResponse); @@ -873,53 +1054,72 @@ class TangemPaymentAccount extends Contract { return responses; } - public Flowable noOtpTransactionAuthorizedEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + public static TransactionSettledEventResponse getTransactionSettledEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(TRANSACTIONSETTLED_EVENT, log); + TransactionSettledEventResponse typedResponse = new TransactionSettledEventResponse(); + typedResponse.log = log; + typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.settlementAmount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + typedResponse.paymentAmount = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); + return typedResponse; + } + + public Flowable transactionSettledEventFlowable( + EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getTransactionSettledEventFromLog(log)); + } + + public Flowable transactionSettledEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(NOOTPTRANSACTIONAUTHORIZED_EVENT)); - return noOtpTransactionAuthorizedEventFlowable(filter); + filter.addSingleTopic(EventEncoder.encode(TRANSACTIONSETTLED_EVENT)); + return transactionSettledEventFlowable(filter); } - public Flowable otpStateSetEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getOtpStateSetEventFromLog(log)); - } - - public Flowable otpStateSetEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(OTPSTATESET_EVENT)); - return otpStateSetEventFlowable(filter); - } - - public static List getUnsettledTransactionUnblockedEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(UNSETTLEDTRANSACTIONUNBLOCKED_EVENT, transactionReceipt); + public static List getUnsettledTransactionUnblockedEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(UNSETTLEDTRANSACTIONUNBLOCKED_EVENT, transactionReceipt); ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { + for (Contract.EventValuesWithLog eventValues : valueList) { UnsettledTransactionUnblockedEventResponse typedResponse = new UnsettledTransactionUnblockedEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); responses.add(typedResponse); } return responses; } - public Flowable ownerSetEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getOwnerSetEventFromLog(log)); + public static UnsettledTransactionUnblockedEventResponse getUnsettledTransactionUnblockedEventFromLog( + Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(UNSETTLEDTRANSACTIONUNBLOCKED_EVENT, log); + UnsettledTransactionUnblockedEventResponse typedResponse = new UnsettledTransactionUnblockedEventResponse(); + typedResponse.log = log; + typedResponse.transactionId = (BigInteger) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; } - public Flowable ownerSetEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + public Flowable unsettledTransactionUnblockedEventFlowable( + EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getUnsettledTransactionUnblockedEventFromLog(log)); + } + + public Flowable unsettledTransactionUnblockedEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(OWNERSET_EVENT)); - return ownerSetEventFlowable(filter); + filter.addSingleTopic(EventEncoder.encode(UNSETTLEDTRANSACTIONUNBLOCKED_EVENT)); + return unsettledTransactionUnblockedEventFlowable(filter); } - public Flowable pendingRefundSavedEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getPendingRefundSavedEventFromLog(log)); - } - - public static List getUpgradedEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(UPGRADED_EVENT, transactionReceipt); + public static List getUpgradedEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(UPGRADED_EVENT, transactionReceipt); ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { + for (Contract.EventValuesWithLog eventValues : valueList) { UpgradedEventResponse typedResponse = new UpgradedEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.implementation = (String) eventValues.getIndexedValues().get(0).getValue(); @@ -928,26 +1128,30 @@ class TangemPaymentAccount extends Contract { return responses; } - public Flowable pendingRefundSavedEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + public static UpgradedEventResponse getUpgradedEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(UPGRADED_EVENT, log); + UpgradedEventResponse typedResponse = new UpgradedEventResponse(); + typedResponse.log = log; + typedResponse.implementation = (String) eventValues.getIndexedValues().get(0).getValue(); + return typedResponse; + } + + public Flowable upgradedEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getUpgradedEventFromLog(log)); + } + + public Flowable upgradedEventFlowable(DefaultBlockParameter startBlock, + DefaultBlockParameter endBlock) { EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(PENDINGREFUNDSAVED_EVENT)); - return pendingRefundSavedEventFlowable(filter); + filter.addSingleTopic(EventEncoder.encode(UPGRADED_EVENT)); + return upgradedEventFlowable(filter); } - public Flowable processorSetEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getProcessorSetEventFromLog(log)); - } - - public Flowable processorSetEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(PROCESSORSET_EVENT)); - return processorSetEventFlowable(filter); - } - - public static List getVerifiedBalanceIncreasedEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(VERIFIEDBALANCEINCREASED_EVENT, transactionReceipt); + public static List getVerifiedBalanceIncreasedEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(VERIFIEDBALANCEINCREASED_EVENT, transactionReceipt); ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { + for (Contract.EventValuesWithLog eventValues : valueList) { VerifiedBalanceIncreasedEventResponse typedResponse = new VerifiedBalanceIncreasedEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.increase = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); @@ -957,24 +1161,33 @@ class TangemPaymentAccount extends Contract { return responses; } - public Flowable refundPaidEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getRefundPaidEventFromLog(log)); + public static VerifiedBalanceIncreasedEventResponse getVerifiedBalanceIncreasedEventFromLog( + Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(VERIFIEDBALANCEINCREASED_EVENT, log); + VerifiedBalanceIncreasedEventResponse typedResponse = new VerifiedBalanceIncreasedEventResponse(); + typedResponse.log = log; + typedResponse.increase = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + typedResponse.verifiedBalance = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); + return typedResponse; } - public Flowable refundPaidEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + public Flowable verifiedBalanceIncreasedEventFlowable( + EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getVerifiedBalanceIncreasedEventFromLog(log)); + } + + public Flowable verifiedBalanceIncreasedEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(REFUNDPAID_EVENT)); - return refundPaidEventFlowable(filter); + filter.addSingleTopic(EventEncoder.encode(VERIFIEDBALANCEINCREASED_EVENT)); + return verifiedBalanceIncreasedEventFlowable(filter); } - public Flowable transactionAmountChangedEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getTransactionAmountChangedEventFromLog(log)); - } - - public static List getVerifiedBalanceSetEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(VERIFIEDBALANCESET_EVENT, transactionReceipt); + public static List getVerifiedBalanceSetEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(VERIFIEDBALANCESET_EVENT, transactionReceipt); ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { + for (Contract.EventValuesWithLog eventValues : valueList) { VerifiedBalanceSetEventResponse typedResponse = new VerifiedBalanceSetEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.verifiedBalance = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); @@ -983,51 +1196,66 @@ class TangemPaymentAccount extends Contract { return responses; } - public Flowable transactionAmountChangedEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + public static VerifiedBalanceSetEventResponse getVerifiedBalanceSetEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(VERIFIEDBALANCESET_EVENT, log); + VerifiedBalanceSetEventResponse typedResponse = new VerifiedBalanceSetEventResponse(); + typedResponse.log = log; + typedResponse.verifiedBalance = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + + public Flowable verifiedBalanceSetEventFlowable( + EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getVerifiedBalanceSetEventFromLog(log)); + } + + public Flowable verifiedBalanceSetEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(TRANSACTIONAMOUNTCHANGED_EVENT)); - return transactionAmountChangedEventFlowable(filter); + filter.addSingleTopic(EventEncoder.encode(VERIFIEDBALANCESET_EVENT)); + return verifiedBalanceSetEventFlowable(filter); } - public Flowable transactionAuthorizedEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getTransactionAuthorizedEventFromLog(log)); - } - - public Flowable transactionAuthorizedEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(TRANSACTIONAUTHORIZED_EVENT)); - return transactionAuthorizedEventFlowable(filter); - } - - public static List getWithdrawalCanceledEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(WITHDRAWALCANCELED_EVENT, transactionReceipt); + public static List getWithdrawalCanceledEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(WITHDRAWALCANCELED_EVENT, transactionReceipt); ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { + for (Contract.EventValuesWithLog eventValues : valueList) { WithdrawalCanceledEventResponse typedResponse = new WithdrawalCanceledEventResponse(); typedResponse.log = eventValues.getLog(); + typedResponse.to = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); responses.add(typedResponse); } return responses; } - public Flowable transactionSettledEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getTransactionSettledEventFromLog(log)); + public static WithdrawalCanceledEventResponse getWithdrawalCanceledEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(WITHDRAWALCANCELED_EVENT, log); + WithdrawalCanceledEventResponse typedResponse = new WithdrawalCanceledEventResponse(); + typedResponse.log = log; + typedResponse.to = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; } - public Flowable transactionSettledEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + public Flowable withdrawalCanceledEventFlowable( + EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getWithdrawalCanceledEventFromLog(log)); + } + + public Flowable withdrawalCanceledEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(TRANSACTIONSETTLED_EVENT)); - return transactionSettledEventFlowable(filter); + filter.addSingleTopic(EventEncoder.encode(WITHDRAWALCANCELED_EVENT)); + return withdrawalCanceledEventFlowable(filter); } - public Flowable unsettledTransactionUnblockedEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getUnsettledTransactionUnblockedEventFromLog(log)); - } - - public static List getWithdrawalCompleteEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(WITHDRAWALCOMPLETE_EVENT, transactionReceipt); + public static List getWithdrawalCompleteEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(WITHDRAWALCOMPLETE_EVENT, transactionReceipt); ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { + for (Contract.EventValuesWithLog eventValues : valueList) { WithdrawalCompleteEventResponse typedResponse = new WithdrawalCompleteEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.to = (String) eventValues.getIndexedValues().get(0).getValue(); @@ -1037,28 +1265,35 @@ class TangemPaymentAccount extends Contract { return responses; } - public Flowable unsettledTransactionUnblockedEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + public static WithdrawalCompleteEventResponse getWithdrawalCompleteEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(WITHDRAWALCOMPLETE_EVENT, log); + WithdrawalCompleteEventResponse typedResponse = new WithdrawalCompleteEventResponse(); + typedResponse.log = log; + typedResponse.to = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + + public Flowable withdrawalCompleteEventFlowable( + EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getWithdrawalCompleteEventFromLog(log)); + } + + public Flowable withdrawalCompleteEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(UNSETTLEDTRANSACTIONUNBLOCKED_EVENT)); - return unsettledTransactionUnblockedEventFlowable(filter); + filter.addSingleTopic(EventEncoder.encode(WITHDRAWALCOMPLETE_EVENT)); + return withdrawalCompleteEventFlowable(filter); } - public Flowable upgradedEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getUpgradedEventFromLog(log)); - } - - public Flowable upgradedEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(UPGRADED_EVENT)); - return upgradedEventFlowable(filter); - } - - public static List getWithdrawalInitiatedEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(WITHDRAWALINITIATED_EVENT, transactionReceipt); + public static List getWithdrawalInitiatedEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(WITHDRAWALINITIATED_EVENT, transactionReceipt); ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { + for (Contract.EventValuesWithLog eventValues : valueList) { WithdrawalInitiatedEventResponse typedResponse = new WithdrawalInitiatedEventResponse(); typedResponse.log = eventValues.getLog(); + typedResponse.to = (String) eventValues.getIndexedValues().get(0).getValue(); typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); typedResponse.readyToWithdrawTimestamp = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); responses.add(typedResponse); @@ -1067,175 +1302,176 @@ class TangemPaymentAccount extends Contract { } public static WithdrawalInitiatedEventResponse getWithdrawalInitiatedEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(WITHDRAWALINITIATED_EVENT, log); + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(WITHDRAWALINITIATED_EVENT, log); WithdrawalInitiatedEventResponse typedResponse = new WithdrawalInitiatedEventResponse(); typedResponse.log = log; + typedResponse.to = (String) eventValues.getIndexedValues().get(0).getValue(); typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); typedResponse.readyToWithdrawTimestamp = (BigInteger) eventValues.getNonIndexedValues().get(1).getValue(); return typedResponse; } - public Flowable withdrawalInitiatedEventFlowable(EthFilter filter) { + public Flowable withdrawalInitiatedEventFlowable( + EthFilter filter) { return web3j.ethLogFlowable(filter).map(log -> getWithdrawalInitiatedEventFromLog(log)); } - public Flowable withdrawalInitiatedEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + public Flowable withdrawalInitiatedEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); filter.addSingleTopic(EventEncoder.encode(WITHDRAWALINITIATED_EVENT)); return withdrawalInitiatedEventFlowable(filter); } - public Flowable verifiedBalanceIncreasedEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getVerifiedBalanceIncreasedEventFromLog(log)); - } - - public Flowable verifiedBalanceIncreasedEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(VERIFIEDBALANCEINCREASED_EVENT)); - return verifiedBalanceIncreasedEventFlowable(filter); - } - - public Flowable verifiedBalanceSetEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getVerifiedBalanceSetEventFromLog(log)); - } - - public Flowable verifiedBalanceSetEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(VERIFIEDBALANCESET_EVENT)); - return verifiedBalanceSetEventFlowable(filter); - } - - public Flowable withdrawalCanceledEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getWithdrawalCanceledEventFromLog(log)); - } - - public Flowable withdrawalCanceledEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(WITHDRAWALCANCELED_EVENT)); - return withdrawalCanceledEventFlowable(filter); - } - - public Flowable withdrawalCompleteEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getWithdrawalCompleteEventFromLog(log)); - } - - public Flowable withdrawalCompleteEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(WITHDRAWALCOMPLETE_EVENT)); - return withdrawalCompleteEventFlowable(filter); - } - public RemoteFunctionCall UPGRADE_INTERFACE_VERSION() { final Function function = new Function(FUNC_UPGRADE_INTERFACE_VERSION, - List.of(), - List.of(new TypeReference() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, String.class); } - public RemoteFunctionCall> authorizedTransactions(BigInteger param0) { - final Function function = new Function(FUNC_AUTHORIZEDTRANSACTIONS, - List.of(new Uint256(param0)), - Arrays.asList(new TypeReference() { - }, new TypeReference() { - }, new TypeReference() { - })); - return new RemoteFunctionCall>(function, - new Callable>() { + public RemoteFunctionCall activeCardAddresses() { + final Function function = new Function(FUNC_ACTIVECARDADDRESSES, + Arrays.asList(), + Arrays.>asList(new TypeReference>() {})); + return new RemoteFunctionCall(function, + new Callable() { @Override - public Tuple3 call() throws Exception { + @SuppressWarnings("unchecked") + public List call() throws Exception { + List result = (List) executeCallSingleValueReturn(function, List.class); + return convertToNative(result); + } + }); + } + + public RemoteFunctionCall addCard(String cardAddress, CardParams cardParams, + byte[] ownershipAcceptanceSignature, byte[] cardConfirmationSignature) { + final Function function = new Function( + FUNC_ADDCARD, + Arrays.asList(new org.web3j.abi.datatypes.Address(160, cardAddress), + cardParams, + new org.web3j.abi.datatypes.DynamicBytes(ownershipAcceptanceSignature), + new org.web3j.abi.datatypes.DynamicBytes(cardConfirmationSignature)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteFunctionCall authLimitMargin() { + final Function function = new Function(FUNC_AUTHLIMITMARGIN, + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, BigInteger.class); + } + + public RemoteFunctionCall> authorizedTransactions( + BigInteger param0) { + final Function function = new Function(FUNC_AUTHORIZEDTRANSACTIONS, + Arrays.asList(new org.web3j.abi.datatypes.generated.Uint256(param0)), + Arrays.>asList(new TypeReference() {}, new TypeReference
() {}, new TypeReference() {}, new TypeReference() {})); + return new RemoteFunctionCall>(function, + new Callable>() { + @Override + public Tuple4 call() throws Exception { List results = executeCallMultipleValueReturn(function); - return new Tuple3( + return new Tuple4( (BigInteger) results.get(0).getValue(), - (BigInteger) results.get(1).getValue(), - (Boolean) results.get(2).getValue()); + (String) results.get(1).getValue(), + (BigInteger) results.get(2).getValue(), + (Boolean) results.get(3).getValue()); } }); } public RemoteFunctionCall availableForDebtPayment() { final Function function = new Function(FUNC_AVAILABLEFORDEBTPAYMENT, - List.of(), - List.of(new TypeReference() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, BigInteger.class); } public RemoteFunctionCall availableForPayment() { final Function function = new Function(FUNC_AVAILABLEFORPAYMENT, - List.of(), - List.of(new TypeReference() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, BigInteger.class); } public RemoteFunctionCall availableForWithdrawal() { final Function function = new Function(FUNC_AVAILABLEFORWITHDRAWAL, - List.of(), - List.of(new TypeReference() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, BigInteger.class); } public RemoteFunctionCall blockedAmount() { final Function function = new Function(FUNC_BLOCKEDAMOUNT, - List.of(), - List.of(new TypeReference() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, BigInteger.class); } public RemoteFunctionCall cancelWithdrawal() { final Function function = new Function( FUNC_CANCELWITHDRAWAL, - List.of(), - Collections.emptyList()); + Arrays.asList(), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } - public RemoteFunctionCall> cardWithOtp() { - final Function function = new Function(FUNC_CARDWITHOTP, - List.of(), - Arrays.asList(new TypeReference() { - }, new TypeReference() { - }, new TypeReference() { - })); - return new RemoteFunctionCall>(function, - new Callable>() { + public RemoteFunctionCall cardConfirmationNonce() { + final Function function = new Function(FUNC_CARDCONFIRMATIONNONCE, + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, BigInteger.class); + } + + public RemoteFunctionCall> cards( + String param0) { + final Function function = new Function(FUNC_CARDS, + Arrays.asList(new org.web3j.abi.datatypes.Address(160, param0)), + Arrays.>asList(new TypeReference() {}, new TypeReference() {}, new TypeReference() {}, new TypeReference() {}, new TypeReference() {})); + return new RemoteFunctionCall>(function, + new Callable>() { @Override - public Tuple3 call() throws Exception { + public Tuple5 call( + ) throws Exception { List results = executeCallMultipleValueReturn(function); - return new Tuple3( - (CardWithOtp) results.get(0), - (CardWithOtp) results.get(1), - (BigInteger) results.get(2).getValue()); + return new Tuple5( + (Boolean) results.get(0).getValue(), + (Boolean) results.get(1).getValue(), + (BigInteger) results.get(2).getValue(), + (OtpStateSetting) results.get(3), + (LimitsSetting) results.get(4)); } }); } public RemoteFunctionCall debtAmount() { final Function function = new Function(FUNC_DEBTAMOUNT, - List.of(), - List.of(new TypeReference() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, BigInteger.class); } - public RemoteFunctionCall>> eip712Domain() { + public RemoteFunctionCall disableCard(String card) { + final Function function = new Function( + FUNC_DISABLECARD, + Arrays.asList(new org.web3j.abi.datatypes.Address(160, card)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteFunctionCall>> eip712Domain( + ) { final Function function = new Function(FUNC_EIP712DOMAIN, - List.of(), - Arrays.asList(new TypeReference() { - }, new TypeReference() { - }, new TypeReference() { - }, new TypeReference() { - }, new TypeReference
() { - }, new TypeReference() { - }, new TypeReference>() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference() {}, new TypeReference() {}, new TypeReference() {}, new TypeReference() {}, new TypeReference
() {}, new TypeReference() {}, new TypeReference>() {})); return new RemoteFunctionCall>>(function, new Callable>>() { @Override - public Tuple7> call() throws Exception { + public Tuple7> call( + ) throws Exception { List results = executeCallMultipleValueReturn(function); return new Tuple7>( (byte[]) results.get(0).getValue(), @@ -1249,369 +1485,427 @@ class TangemPaymentAccount extends Contract { }); } + public RemoteFunctionCall enableCard(String card, Boolean isOwner, + byte[] ownershipAcceptanceSignature, byte[] cardConfirmationSignature) { + final Function function = new Function( + FUNC_ENABLECARD, + Arrays.asList(new org.web3j.abi.datatypes.Address(160, card), + new org.web3j.abi.datatypes.Bool(isOwner), + new org.web3j.abi.datatypes.DynamicBytes(ownershipAcceptanceSignature), + new org.web3j.abi.datatypes.DynamicBytes(cardConfirmationSignature)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + public RemoteFunctionCall factory() { final Function function = new Function(FUNC_FACTORY, - List.of(), - List.of(new TypeReference
() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference
() {})); return executeRemoteCallSingleValueReturn(function, String.class); } public RemoteFunctionCall increaseVerifiedBalance(BigInteger increase) { final Function function = new Function( FUNC_INCREASEVERIFIEDBALANCE, - List.of(new Uint256(increase)), - Collections.emptyList()); + Arrays.asList(new org.web3j.abi.datatypes.generated.Uint256(increase)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } - public RemoteFunctionCall initWithdrawal(BigInteger amount) { + public RemoteFunctionCall initWithdrawal(String to, BigInteger amount) { final Function function = new Function( FUNC_INITWITHDRAWAL, - List.of(new Uint256(amount)), - Collections.emptyList()); + Arrays.asList(new org.web3j.abi.datatypes.Address(160, to), + new org.web3j.abi.datatypes.generated.Uint256(amount)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } - public RemoteFunctionCall initialize(String owner_, String registry_, BigInteger singleTransactionLimit, BigInteger spendLimit, BigInteger noOtpSpendLimit, BigInteger spendLimitsPeriod) { + public RemoteFunctionCall initialize(String owner_, String processor_, + String registry_, String cardAddress, CardParams cardParams, + BigInteger authLimitMargin_) { final Function function = new Function( FUNC_INITIALIZE, - Arrays.asList(new Address(160, owner_), - new Address(160, registry_), - new Uint256(singleTransactionLimit), - new Uint256(spendLimit), - new Uint256(noOtpSpendLimit), - new Uint256(spendLimitsPeriod)), - Collections.emptyList()); + Arrays.asList(new org.web3j.abi.datatypes.Address(160, owner_), + new org.web3j.abi.datatypes.Address(160, processor_), + new org.web3j.abi.datatypes.Address(160, registry_), + new org.web3j.abi.datatypes.Address(160, cardAddress), + cardParams, + new org.web3j.abi.datatypes.generated.Uint256(authLimitMargin_)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } public RemoteFunctionCall isTrustedForwarder(String forwarder) { final Function function = new Function(FUNC_ISTRUSTEDFORWARDER, - List.of(new Address(160, forwarder)), - List.of(new TypeReference() { - })); + Arrays.asList(new org.web3j.abi.datatypes.Address(160, forwarder)), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, Boolean.class); } public RemoteFunctionCall isWithdrawalInProgress() { final Function function = new Function(FUNC_ISWITHDRAWALINPROGRESS, - List.of(), - List.of(new TypeReference() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, Boolean.class); } public RemoteFunctionCall isWithdrawalReady() { final Function function = new Function(FUNC_ISWITHDRAWALREADY, - List.of(), - List.of(new TypeReference() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, Boolean.class); } - public RemoteFunctionCall> limits() { - final Function function = new Function(FUNC_LIMITS, - List.of(), - Arrays.asList(new TypeReference() { - }, new TypeReference() { - }, new TypeReference() { - })); - return new RemoteFunctionCall>(function, - new Callable>() { - @Override - public Tuple3 call() throws Exception { - List results = executeCallMultipleValueReturn(function); - return new Tuple3( - (Limits) results.get(0), - (Limits) results.get(1), - (BigInteger) results.get(2).getValue()); - } - }); - } - public RemoteFunctionCall owner() { final Function function = new Function(FUNC_OWNER, - List.of(), - List.of(new TypeReference
() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference
() {})); return executeRemoteCallSingleValueReturn(function, String.class); } public RemoteFunctionCall ownershipAcceptanceNonce() { final Function function = new Function(FUNC_OWNERSHIPACCEPTANCENONCE, - List.of(), - List.of(new TypeReference() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, BigInteger.class); } + public RemoteFunctionCall payDebt(BigInteger amount) { + final Function function = new Function( + FUNC_PAYDEBT, + Arrays.asList(new org.web3j.abi.datatypes.generated.Uint256(amount)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + public RemoteFunctionCall paymentToken() { final Function function = new Function(FUNC_PAYMENTTOKEN, - List.of(), - List.of(new TypeReference
() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference
() {})); return executeRemoteCallSingleValueReturn(function, String.class); } - public RemoteFunctionCall pendingRefundAmount(BigInteger transactionId) { - final Function function = new Function(FUNC_PENDINGREFUNDAMOUNT, - List.of(new Uint256(transactionId)), - List.of(new TypeReference() { - })); - return executeRemoteCallSingleValueReturn(function, BigInteger.class); - } - - public RemoteFunctionCall pendingRefundTotal() { - final Function function = new Function(FUNC_PENDINGREFUNDTOTAL, - List.of(), - List.of(new TypeReference() { - })); - return executeRemoteCallSingleValueReturn(function, BigInteger.class); - } - - public RemoteFunctionCall processAuthorization(BigInteger transactionId, BigInteger amount, byte[] otp, BigInteger otpCounter, Boolean forced) { - final Function function = new Function( - FUNC_PROCESSAUTHORIZATION, - Arrays.asList(new Uint256(transactionId), - new Uint256(amount), - new Bytes16(otp), - new Uint16(otpCounter), - new Bool(forced)), - Collections.emptyList()); - return executeRemoteCallTransaction(function); - } - - public RemoteFunctionCall processAuthorizationChange(BigInteger transactionId, BigInteger newAmount) { + public RemoteFunctionCall processAuthorizationChange(String card, + BigInteger transactionId, BigInteger newAmount) { final Function function = new Function( FUNC_PROCESSAUTHORIZATIONCHANGE, - Arrays.asList(new Uint256(transactionId), - new Uint256(newAmount)), - Collections.emptyList()); + Arrays.asList(new org.web3j.abi.datatypes.Address(160, card), + new org.web3j.abi.datatypes.generated.Uint256(transactionId), + new org.web3j.abi.datatypes.generated.Uint256(newAmount)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } - public RemoteFunctionCall processAuthorizationNoOtp(BigInteger transactionId, BigInteger amount, Boolean forced) { - final Function function = new Function( - FUNC_PROCESSAUTHORIZATIONNOOTP, - Arrays.asList(new Uint256(transactionId), - new Uint256(amount), - new Bool(forced)), - Collections.emptyList()); - return executeRemoteCallTransaction(function); - } - - public RemoteFunctionCall processDebt(BigInteger amount) { + public RemoteFunctionCall processDebt(String card, BigInteger amount) { final Function function = new Function( FUNC_PROCESSDEBT, - List.of(new Uint256(amount)), - Collections.emptyList()); + Arrays.asList(new org.web3j.abi.datatypes.Address(160, card), + new org.web3j.abi.datatypes.generated.Uint256(amount)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } - public RemoteFunctionCall processPendingRefundPayment(BigInteger transactionId) { + public RemoteFunctionCall processNoConfirmationAuthorization(String card, + BigInteger transactionId, BigInteger amount, Boolean forced) { final Function function = new Function( - FUNC_PROCESSPENDINGREFUNDPAYMENT, - List.of(new Uint256(transactionId)), - Collections.emptyList()); + FUNC_PROCESSNOCONFIRMATIONAUTHORIZATION, + Arrays.asList(new org.web3j.abi.datatypes.Address(160, card), + new org.web3j.abi.datatypes.generated.Uint256(transactionId), + new org.web3j.abi.datatypes.generated.Uint256(amount), + new org.web3j.abi.datatypes.Bool(forced)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } - public RemoteFunctionCall processRefundPayment(BigInteger transactionId) { + public RemoteFunctionCall processOtpAuthorization(String card, + BigInteger transactionId, BigInteger amount, byte[] otp, BigInteger otpCounter, + Boolean forced) { + final Function function = new Function( + FUNC_PROCESSOTPAUTHORIZATION, + Arrays.asList(new org.web3j.abi.datatypes.Address(160, card), + new org.web3j.abi.datatypes.generated.Uint256(transactionId), + new org.web3j.abi.datatypes.generated.Uint256(amount), + new org.web3j.abi.datatypes.generated.Bytes16(otp), + new org.web3j.abi.datatypes.generated.Uint16(otpCounter), + new org.web3j.abi.datatypes.Bool(forced)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteFunctionCall processRefundPayment(String card, + BigInteger transactionId) { final Function function = new Function( FUNC_PROCESSREFUNDPAYMENT, - List.of(new Uint256(transactionId)), - Collections.emptyList()); + Arrays.asList(new org.web3j.abi.datatypes.Address(160, card), + new org.web3j.abi.datatypes.generated.Uint256(transactionId)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } - public RemoteFunctionCall processSettlement(BigInteger transactionId, BigInteger amount) { + public RemoteFunctionCall processSettlement(String card, + BigInteger transactionId, BigInteger amount) { final Function function = new Function( FUNC_PROCESSSETTLEMENT, - Arrays.asList(new Uint256(transactionId), - new Uint256(amount)), - Collections.emptyList()); + Arrays.asList(new org.web3j.abi.datatypes.Address(160, card), + new org.web3j.abi.datatypes.generated.Uint256(transactionId), + new org.web3j.abi.datatypes.generated.Uint256(amount)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } - public RemoteFunctionCall processWithdrawal(String to) { + public RemoteFunctionCall processSignatureAuthorization(String card, + BigInteger transactionId, BigInteger amount, byte[] transactionConfirmationSignature, + Boolean forced) { + final Function function = new Function( + FUNC_PROCESSSIGNATUREAUTHORIZATION, + Arrays.asList(new org.web3j.abi.datatypes.Address(160, card), + new org.web3j.abi.datatypes.generated.Uint256(transactionId), + new org.web3j.abi.datatypes.generated.Uint256(amount), + new org.web3j.abi.datatypes.DynamicBytes(transactionConfirmationSignature), + new org.web3j.abi.datatypes.Bool(forced)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteFunctionCall processUnsettledTransaction(String card, + BigInteger transactionId) { + final Function function = new Function( + FUNC_PROCESSUNSETTLEDTRANSACTION, + Arrays.asList(new org.web3j.abi.datatypes.Address(160, card), + new org.web3j.abi.datatypes.generated.Uint256(transactionId)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteFunctionCall processWithdrawal() { final Function function = new Function( FUNC_PROCESSWITHDRAWAL, - List.of(new Address(160, to)), - Collections.emptyList()); + Arrays.asList(), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } public RemoteFunctionCall processor() { final Function function = new Function(FUNC_PROCESSOR, - List.of(), - List.of(new TypeReference
() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference
() {})); return executeRemoteCallSingleValueReturn(function, String.class); } public RemoteFunctionCall proxiableUUID() { final Function function = new Function(FUNC_PROXIABLEUUID, - List.of(), - List.of(new TypeReference() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, byte[].class); } public RemoteFunctionCall registry() { final Function function = new Function(FUNC_REGISTRY, - List.of(), - List.of(new TypeReference
() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference
() {})); return executeRemoteCallSingleValueReturn(function, String.class); } - public RemoteFunctionCall savePendingRefund(BigInteger transactionId, BigInteger amount) { + public RemoteFunctionCall removeOwner() { final Function function = new Function( - FUNC_SAVEPENDINGREFUND, - Arrays.asList(new Uint256(transactionId), - new Uint256(amount)), - Collections.emptyList()); + FUNC_REMOVEOWNER, + Arrays.asList(), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } public RemoteFunctionCall securityDelay() { final Function function = new Function(FUNC_SECURITYDELAY, - List.of(), - List.of(new TypeReference() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, BigInteger.class); } - public RemoteFunctionCall setCard(String card, byte[] otpRoot, BigInteger otpCounter, byte[] ownershipAcceptanceSignature) { + public RemoteFunctionCall setAuthLimitMargin(BigInteger authLimitMargin_) { final Function function = new Function( - FUNC_SETCARD, - Arrays.asList(new Address(160, card), - new Bytes16(otpRoot), - new Uint16(otpCounter), - new org.web3j.abi.datatypes.DynamicBytes(ownershipAcceptanceSignature)), - Collections.emptyList()); + FUNC_SETAUTHLIMITMARGIN, + Arrays.asList(new org.web3j.abi.datatypes.generated.Uint256(authLimitMargin_)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } - public RemoteFunctionCall setLimits(BigInteger singleTransactionLimit, BigInteger spendLimit, BigInteger noOtpSpendLimit, BigInteger spendLimitsPeriod) { + public RemoteFunctionCall setCardIsOwner(String card, Boolean isOwner) { + final Function function = new Function( + FUNC_SETCARDISOWNER, + Arrays.asList(new org.web3j.abi.datatypes.Address(160, card), + new org.web3j.abi.datatypes.Bool(isOwner)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteFunctionCall setLimits(String card, + LimitsParams limitsParams) { final Function function = new Function( FUNC_SETLIMITS, - Arrays.asList(new Uint256(singleTransactionLimit), - new Uint256(spendLimit), - new Uint256(noOtpSpendLimit), - new Uint256(spendLimitsPeriod)), - Collections.emptyList()); + Arrays.asList(new org.web3j.abi.datatypes.Address(160, card), + limitsParams), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } - public RemoteFunctionCall setOtpState(byte[] otp, BigInteger counter) { + public RemoteFunctionCall setOtpState(String card, OtpState otpState) { final Function function = new Function( FUNC_SETOTPSTATE, - Arrays.asList(new Bytes16(otp), - new Uint16(counter)), - Collections.emptyList()); + Arrays.asList(new org.web3j.abi.datatypes.Address(160, card), + otpState), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } - public RemoteFunctionCall setOwner(String owner_, byte[] ownershipAcceptanceSignature) { + public RemoteFunctionCall setOwner(String owner_, + byte[] ownershipAcceptanceSignature) { final Function function = new Function( FUNC_SETOWNER, - Arrays.asList(new Address(160, owner_), + Arrays.asList(new org.web3j.abi.datatypes.Address(160, owner_), new org.web3j.abi.datatypes.DynamicBytes(ownershipAcceptanceSignature)), - Collections.emptyList()); - return executeRemoteCallTransaction(function); - } - - public RemoteFunctionCall setProcessor(String processor_) { - final Function function = new Function( - FUNC_SETPROCESSOR, - List.of(new Address(160, processor_)), - Collections.emptyList()); + Collections.>emptyList()); return executeRemoteCallTransaction(function); } public RemoteFunctionCall setVerifiedBalance(BigInteger verifiedBalance_) { final Function function = new Function( FUNC_SETVERIFIEDBALANCE, - List.of(new Uint256(verifiedBalance_)), - Collections.emptyList()); + Arrays.asList(new org.web3j.abi.datatypes.generated.Uint256(verifiedBalance_)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } - public RemoteFunctionCall settlementPeriod() { - final Function function = new Function(FUNC_SETTLEMENTPERIOD, - List.of(), - List.of(new TypeReference() { - })); + public RemoteFunctionCall transactionConfirmationNonce() { + final Function function = new Function(FUNC_TRANSACTIONCONFIRMATIONNONCE, + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, BigInteger.class); } public RemoteFunctionCall trustedForwarder() { final Function function = new Function(FUNC_TRUSTEDFORWARDER, - List.of(), - List.of(new TypeReference
() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference
() {})); return executeRemoteCallSingleValueReturn(function, String.class); } - public RemoteFunctionCall unblockUnsettledTransaction(BigInteger transactionId) { - final Function function = new Function( - FUNC_UNBLOCKUNSETTLEDTRANSACTION, - List.of(new Uint256(transactionId)), - Collections.emptyList()); - return executeRemoteCallTransaction(function); - } - - public RemoteFunctionCall upgradeToAndCall(String newImplementation, byte[] data, BigInteger weiValue) { + public RemoteFunctionCall upgradeToAndCall(String newImplementation, + byte[] data, BigInteger weiValue) { final Function function = new Function( FUNC_UPGRADETOANDCALL, - Arrays.asList(new Address(160, newImplementation), + Arrays.asList(new org.web3j.abi.datatypes.Address(160, newImplementation), new org.web3j.abi.datatypes.DynamicBytes(data)), - Collections.emptyList()); + Collections.>emptyList()); return executeRemoteCallTransaction(function, weiValue); } public RemoteFunctionCall verifiedBalance() { final Function function = new Function(FUNC_VERIFIEDBALANCE, - List.of(), - List.of(new TypeReference() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, BigInteger.class); } + public RemoteFunctionCall withdrawalAddress() { + final Function function = new Function(FUNC_WITHDRAWALADDRESS, + Arrays.asList(), + Arrays.>asList(new TypeReference
() {})); + return executeRemoteCallSingleValueReturn(function, String.class); + } + public RemoteFunctionCall withdrawalAmount() { final Function function = new Function(FUNC_WITHDRAWALAMOUNT, - List.of(), - List.of(new TypeReference() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, BigInteger.class); } public RemoteFunctionCall withdrawalReadyTimestamp() { final Function function = new Function(FUNC_WITHDRAWALREADYTIMESTAMP, - List.of(), - List.of(new TypeReference() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); return executeRemoteCallSingleValueReturn(function, BigInteger.class); } public RemoteFunctionCall writeOffDebt(BigInteger amount) { final Function function = new Function( FUNC_WRITEOFFDEBT, - List.of(new Uint256(amount)), - Collections.emptyList()); + Arrays.asList(new org.web3j.abi.datatypes.generated.Uint256(amount)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } + @Deprecated + public static TangemPaymentAccount load(String contractAddress, Web3j web3j, + Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + return new TangemPaymentAccount(contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + @Deprecated + public static TangemPaymentAccount load(String contractAddress, Web3j web3j, + TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) { + return new TangemPaymentAccount(contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + public static TangemPaymentAccount load(String contractAddress, Web3j web3j, + Credentials credentials, ContractGasProvider contractGasProvider) { + return new TangemPaymentAccount(contractAddress, web3j, credentials, contractGasProvider); + } + + public static TangemPaymentAccount load(String contractAddress, Web3j web3j, + TransactionManager transactionManager, ContractGasProvider contractGasProvider) { + return new TangemPaymentAccount(contractAddress, web3j, transactionManager, contractGasProvider); + } + + public static RemoteCall deploy(Web3j web3j, Credentials credentials, + ContractGasProvider contractGasProvider, String trustedForwarder) { + String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(new org.web3j.abi.datatypes.Address(160, trustedForwarder))); + return deployRemoteCall(TangemPaymentAccount.class, web3j, credentials, contractGasProvider, getDeploymentBinary(), encodedConstructor); + } + + public static RemoteCall deploy(Web3j web3j, + TransactionManager transactionManager, ContractGasProvider contractGasProvider, + String trustedForwarder) { + String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(new org.web3j.abi.datatypes.Address(160, trustedForwarder))); + return deployRemoteCall(TangemPaymentAccount.class, web3j, transactionManager, contractGasProvider, getDeploymentBinary(), encodedConstructor); + } + + @Deprecated + public static RemoteCall deploy(Web3j web3j, Credentials credentials, + BigInteger gasPrice, BigInteger gasLimit, String trustedForwarder) { + String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(new org.web3j.abi.datatypes.Address(160, trustedForwarder))); + return deployRemoteCall(TangemPaymentAccount.class, web3j, credentials, gasPrice, gasLimit, getDeploymentBinary(), encodedConstructor); + } + + @Deprecated + public static RemoteCall deploy(Web3j web3j, + TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit, + String trustedForwarder) { + String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(new org.web3j.abi.datatypes.Address(160, trustedForwarder))); + return deployRemoteCall(TangemPaymentAccount.class, web3j, transactionManager, gasPrice, gasLimit, getDeploymentBinary(), encodedConstructor); + } + + public static void linkLibraries(List references) { + librariesLinkedBinary = linkBinaryWithReferences(BINARY, references); + } + + private static String getDeploymentBinary() { + if (librariesLinkedBinary != null) { + return librariesLinkedBinary; + } else { + return BINARY; + } + } + public static class OtpState extends StaticStruct { public byte[] otp; public BigInteger counter; public OtpState(byte[] otp, BigInteger counter) { - super(new Bytes16(otp), - new Uint16(counter)); + super(new org.web3j.abi.datatypes.generated.Bytes16(otp), + new org.web3j.abi.datatypes.generated.Uint16(counter)); this.otp = otp; this.counter = counter; } @@ -1623,22 +1917,53 @@ class TangemPaymentAccount extends Contract { } } - public static class Limit extends StaticStruct { - public BigInteger _00_limit; + public static class LimitsParams extends StaticStruct { + public BigInteger singleTransactionLimit; - public BigInteger _01_spent; + public BigInteger spendLimit; + + public BigInteger noConfirmationSpendLimit; + + public BigInteger spendLimitsPeriod; + + public LimitsParams(BigInteger singleTransactionLimit, BigInteger spendLimit, + BigInteger noConfirmationSpendLimit, BigInteger spendLimitsPeriod) { + super(new org.web3j.abi.datatypes.generated.Uint256(singleTransactionLimit), + new org.web3j.abi.datatypes.generated.Uint256(spendLimit), + new org.web3j.abi.datatypes.generated.Uint256(noConfirmationSpendLimit), + new org.web3j.abi.datatypes.generated.Uint256(spendLimitsPeriod)); + this.singleTransactionLimit = singleTransactionLimit; + this.spendLimit = spendLimit; + this.noConfirmationSpendLimit = noConfirmationSpendLimit; + this.spendLimitsPeriod = spendLimitsPeriod; + } + + public LimitsParams(Uint256 singleTransactionLimit, Uint256 spendLimit, + Uint256 noConfirmationSpendLimit, Uint256 spendLimitsPeriod) { + super(singleTransactionLimit, spendLimit, noConfirmationSpendLimit, spendLimitsPeriod); + this.singleTransactionLimit = singleTransactionLimit.getValue(); + this.spendLimit = spendLimit.getValue(); + this.noConfirmationSpendLimit = noConfirmationSpendLimit.getValue(); + this.spendLimitsPeriod = spendLimitsPeriod.getValue(); + } + } + + public static class Limit extends StaticStruct { + public BigInteger limit; + + public BigInteger spent; public Limit(BigInteger limit, BigInteger spent) { - super(new Uint256(limit), - new Uint256(spent)); - this._00_limit = limit; - this._01_spent = spent; + super(new org.web3j.abi.datatypes.generated.Uint256(limit), + new org.web3j.abi.datatypes.generated.Uint256(spent)); + this.limit = limit; + this.spent = spent; } public Limit(Uint256 limit, Uint256 spent) { super(limit, spent); - this._00_limit = limit.getValue(); - this._01_spent = spent.getValue(); + this.limit = limit.getValue(); + this.spent = spent.getValue(); } } @@ -1646,7 +1971,7 @@ class TangemPaymentAccount extends Contract { public BigInteger expireTimestamp; public Timer(BigInteger expireTimestamp) { - super(new Uint256(expireTimestamp)); + super(new org.web3j.abi.datatypes.generated.Uint256(expireTimestamp)); this.expireTimestamp = expireTimestamp; } @@ -1656,56 +1981,112 @@ class TangemPaymentAccount extends Contract { } } - public static class CardWithOtp extends StaticStruct { - public String card; + public static class CardParams extends StaticStruct { + public Boolean isOwner; public OtpState otpState; - public CardWithOtp(String card, OtpState otpState) { - super(new Address(160, card), - otpState); - this.card = card; + public LimitsParams limitsParams; + + public CardParams(Boolean isOwner, OtpState otpState, LimitsParams limitsParams) { + super(new org.web3j.abi.datatypes.Bool(isOwner), + otpState, + limitsParams); + this.isOwner = isOwner; this.otpState = otpState; + this.limitsParams = limitsParams; } - public CardWithOtp(Address card, OtpState otpState) { - super(card, otpState); - this.card = card.getValue(); + public CardParams(Bool isOwner, OtpState otpState, LimitsParams limitsParams) { + super(isOwner, otpState, limitsParams); + this.isOwner = isOwner.getValue(); this.otpState = otpState; + this.limitsParams = limitsParams; + } + } + + public static class OtpStateSetting extends StaticStruct { + public OtpState oldValue; + + public OtpState newValue; + + public BigInteger changeTimestamp; + + public OtpStateSetting(OtpState oldValue, OtpState newValue, BigInteger changeTimestamp) { + super(oldValue, + newValue, + new org.web3j.abi.datatypes.generated.Uint256(changeTimestamp)); + this.oldValue = oldValue; + this.newValue = newValue; + this.changeTimestamp = changeTimestamp; + } + + public OtpStateSetting(OtpState oldValue, OtpState newValue, Uint256 changeTimestamp) { + super(oldValue, newValue, changeTimestamp); + this.oldValue = oldValue; + this.newValue = newValue; + this.changeTimestamp = changeTimestamp.getValue(); } } public static class Limits extends StaticStruct { - public BigInteger _00_singleTransactionLimit; + public BigInteger singleTransactionLimit; - public Limit _01_spendLimit; + public Limit spendLimit; - public Limit _02_noOtpSpendLimit; + public Limit noConfirmationSpendLimit; - public Timer _03_spendLimitsTimer; + public Timer spendLimitsTimer; - public BigInteger _04_spendLimitsPeriod; + public BigInteger spendLimitsPeriod; - public Limits(BigInteger singleTransactionLimit, Limit spendLimit, Limit noOtpSpendLimit, Timer spendLimitsTimer, BigInteger spendLimitsPeriod) { - super(new Uint256(singleTransactionLimit), + public Limits(BigInteger singleTransactionLimit, Limit spendLimit, + Limit noConfirmationSpendLimit, Timer spendLimitsTimer, + BigInteger spendLimitsPeriod) { + super(new org.web3j.abi.datatypes.generated.Uint256(singleTransactionLimit), spendLimit, - noOtpSpendLimit, - spendLimitsTimer, - new Uint256(spendLimitsPeriod)); - this._00_singleTransactionLimit = singleTransactionLimit; - this._01_spendLimit = spendLimit; - this._02_noOtpSpendLimit = noOtpSpendLimit; - this._03_spendLimitsTimer = spendLimitsTimer; - this._04_spendLimitsPeriod = spendLimitsPeriod; + noConfirmationSpendLimit, + spendLimitsTimer, + new org.web3j.abi.datatypes.generated.Uint256(spendLimitsPeriod)); + this.singleTransactionLimit = singleTransactionLimit; + this.spendLimit = spendLimit; + this.noConfirmationSpendLimit = noConfirmationSpendLimit; + this.spendLimitsTimer = spendLimitsTimer; + this.spendLimitsPeriod = spendLimitsPeriod; } - public Limits(Uint256 singleTransactionLimit, Limit spendLimit, Limit noOtpSpendLimit, Timer spendLimitsTimer, Uint256 spendLimitsPeriod) { - super(singleTransactionLimit, spendLimit, noOtpSpendLimit, spendLimitsTimer, spendLimitsPeriod); - this._00_singleTransactionLimit = singleTransactionLimit.getValue(); - this._01_spendLimit = spendLimit; - this._02_noOtpSpendLimit = noOtpSpendLimit; - this._03_spendLimitsTimer = spendLimitsTimer; - this._04_spendLimitsPeriod = spendLimitsPeriod.getValue(); + public Limits(Uint256 singleTransactionLimit, Limit spendLimit, + Limit noConfirmationSpendLimit, Timer spendLimitsTimer, Uint256 spendLimitsPeriod) { + super(singleTransactionLimit, spendLimit, noConfirmationSpendLimit, spendLimitsTimer, spendLimitsPeriod); + this.singleTransactionLimit = singleTransactionLimit.getValue(); + this.spendLimit = spendLimit; + this.noConfirmationSpendLimit = noConfirmationSpendLimit; + this.spendLimitsTimer = spendLimitsTimer; + this.spendLimitsPeriod = spendLimitsPeriod.getValue(); + } + } + + public static class LimitsSetting extends StaticStruct { + public Limits oldValue; + + public Limits newValue; + + public BigInteger changeTimestamp; + + public LimitsSetting(Limits oldValue, Limits newValue, BigInteger changeTimestamp) { + super(oldValue, + newValue, + new org.web3j.abi.datatypes.generated.Uint256(changeTimestamp)); + this.oldValue = oldValue; + this.newValue = newValue; + this.changeTimestamp = changeTimestamp; + } + + public LimitsSetting(Limits oldValue, Limits newValue, Uint256 changeTimestamp) { + super(oldValue, newValue, changeTimestamp); + this.oldValue = oldValue; + this.newValue = newValue; + this.changeTimestamp = changeTimestamp.getValue(); } } @@ -1715,16 +2096,26 @@ class TangemPaymentAccount extends Contract { public BigInteger blockedAmount; public BigInteger debtTotal; - - public BigInteger pendingRefundTotal; } - public static class CardSetEventResponse extends BaseEventResponse { + public static class AuthLimitMarginSetEventResponse extends BaseEventResponse { + public BigInteger authLimitMargin; + } + + public static class CardAddedEventResponse extends BaseEventResponse { + public String cardAddress; + + public CardParams cardData; + } + + public static class CardDisabledEventResponse extends BaseEventResponse { + public String card; + } + + public static class CardEnabledEventResponse extends BaseEventResponse { public String card; - public byte[] otpRoot; - - public BigInteger otpCounter; + public Boolean isOwner; } public static class DebtIncreasedEventResponse extends BaseEventResponse { @@ -1755,41 +2146,31 @@ class TangemPaymentAccount extends Contract { public static class InsufficientFundsOnForcedAuthEventResponse extends BaseEventResponse { public BigInteger transactionId; + public String card; + public BigInteger insufficientAmount; } public static class LimitsSetEventResponse extends BaseEventResponse { - public BigInteger singleTransactionLimit; + public String card; - public BigInteger spendLimit; - - public BigInteger noOtpSpendLimit; - - public BigInteger spendLimitsPeriod; - } - - public static class NoOtpTransactionAuthorizedEventResponse extends BaseEventResponse { - public BigInteger transactionId; - - public BigInteger amount; + public LimitsParams limitsParams; } public static class OtpStateSetEventResponse extends BaseEventResponse { - public byte[] otpRoot; + public String card; - public BigInteger otpCounter; + public OtpState otpState; + } + + public static class OwnerRemovedEventResponse extends BaseEventResponse { + public String previousOwner; } public static class OwnerSetEventResponse extends BaseEventResponse { public String owner; } - public static class PendingRefundSavedEventResponse extends BaseEventResponse { - public BigInteger transactionId; - - public BigInteger amount; - } - public static class ProcessorSetEventResponse extends BaseEventResponse { public String processor; @@ -1799,18 +2180,32 @@ class TangemPaymentAccount extends Contract { public static class RefundPaidEventResponse extends BaseEventResponse { public BigInteger transactionId; + public String card; + public BigInteger amount; } public static class TransactionAmountChangedEventResponse extends BaseEventResponse { public BigInteger transactionId; + public String card; + public BigInteger newAmount; } - public static class TransactionAuthorizedEventResponse extends BaseEventResponse { + public static class TransactionAuthorizedNoConfirmationEventResponse extends BaseEventResponse { public BigInteger transactionId; + public String card; + + public BigInteger amount; + } + + public static class TransactionAuthorizedWithOtpEventResponse extends BaseEventResponse { + public BigInteger transactionId; + + public String card; + public BigInteger amount; public byte[] otp; @@ -1818,9 +2213,21 @@ class TangemPaymentAccount extends Contract { public BigInteger otpCounter; } + public static class TransactionAuthorizedWithSignatureEventResponse extends BaseEventResponse { + public BigInteger transactionId; + + public String card; + + public BigInteger amount; + + public byte[] signature; + } + public static class TransactionSettledEventResponse extends BaseEventResponse { public BigInteger transactionId; + public String card; + public BigInteger settlementAmount; public BigInteger paymentAmount; @@ -1829,6 +2236,8 @@ class TangemPaymentAccount extends Contract { public static class UnsettledTransactionUnblockedEventResponse extends BaseEventResponse { public BigInteger transactionId; + public String card; + public BigInteger amount; } @@ -1847,6 +2256,9 @@ class TangemPaymentAccount extends Contract { } public static class WithdrawalCanceledEventResponse extends BaseEventResponse { + public String to; + + public BigInteger amount; } public static class WithdrawalCompleteEventResponse extends BaseEventResponse { @@ -1856,8 +2268,10 @@ class TangemPaymentAccount extends Contract { } public static class WithdrawalInitiatedEventResponse extends BaseEventResponse { + public String to; + public BigInteger amount; public BigInteger readyToWithdrawTimestamp; } -} +} \ No newline at end of file diff --git a/libs/visa/src/main/java/com/tangem/lib/visa/TangemPaymentAccountRegistry.java b/libs/visa/src/main/java/com/tangem/lib/visa/TangemPaymentAccountRegistry.java index bcf93417f6..a5107bee89 100644 --- a/libs/visa/src/main/java/com/tangem/lib/visa/TangemPaymentAccountRegistry.java +++ b/libs/visa/src/main/java/com/tangem/lib/visa/TangemPaymentAccountRegistry.java @@ -1,9 +1,20 @@ package com.tangem.lib.visa; +import io.reactivex.Flowable; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.Callable; import org.web3j.abi.EventEncoder; import org.web3j.abi.FunctionEncoder; import org.web3j.abi.TypeReference; -import org.web3j.abi.datatypes.*; +import org.web3j.abi.datatypes.Address; +import org.web3j.abi.datatypes.DynamicArray; +import org.web3j.abi.datatypes.Event; +import org.web3j.abi.datatypes.Function; +import org.web3j.abi.datatypes.Type; import org.web3j.crypto.Credentials; import org.web3j.protocol.Web3j; import org.web3j.protocol.core.DefaultBlockParameter; @@ -17,111 +28,89 @@ import org.web3j.tx.Contract; import org.web3j.tx.TransactionManager; import org.web3j.tx.gas.ContractGasProvider; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.Callable; - -import io.reactivex.Flowable; - /** *

Auto generated code. *

Do not modify! *

Please use the web3j command line tools, * or the org.web3j.codegen.SolidityFunctionWrapperGenerator in the - * codegen module to update. + * codegen module to update. * - *

Generated with web3j version 1.5.2. + *

Generated with web3j version 1.6.1. */ @SuppressWarnings("rawtypes") -class TangemPaymentAccountRegistry extends Contract { - public static final String BINARY = "608060405234801561001057600080fd5b50604051610c47380380610c4783398101604081905261002f91610054565b600080546001600160a01b0319166001600160a01b0392909216919091179055610084565b60006020828403121561006657600080fd5b81516001600160a01b038116811461007d57600080fd5b9392505050565b610bb4806100936000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c806368d7111a1161005b57806368d7111a146100f0578063747fc3701461010357806379da564f14610116578063c45a01551461013657600080fd5b80630cef7172146100825780633509c7c5146100c85780635cd26737146100dd575b600080fd5b6100ab6100903660046108fd565b6002602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6100db6100d6366004610918565b610149565b005b6100db6100eb366004610918565b610201565b6100db6100fe3660046108fd565b6103b0565b6100db610111366004610918565b610506565b6101296101243660046108fd565b6106db565b6040516100bf919061094b565b6000546100ab906001600160a01b031681565b600054604080516080810190915260428082526001600160a01b03909216331491610a576020830139906101995760405162461bcd60e51b81526004016101909190610998565b60405180910390fd5b506001600160a01b03811660009081526001602052604090206101bc9083610705565b50806001600160a01b0316826001600160a01b03167f65b303fd420aefd0541d9300bb10190bb8e3320a0e7c2ce4dec6b6bfb953027f60405160405180910390a35050565b6000546040516385bb392360e01b81523360048201526001600160a01b03909116906385bb392390602401602060405180830381865afa158015610249573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061026d91906109e7565b6040518060600160405280603a8152602001610b45603a9139906102a45760405162461bcd60e51b81526004016101909190610998565b506001600160a01b038216600090815260016020526040902033906102c99082610721565b6040518060600160405280603b8152602001610ad0603b9139906103005760405162461bcd60e51b81526004016101909190610998565b506001600160a01b03821660009081526001602052604090206103239082610705565b6040518060600160405280603b8152602001610ad0603b91399061035a5760405162461bcd60e51b81526004016101909190610998565b50604080516001600160a01b03808416825280861660208301528416918101919091527ffba993cae385d1da628b11b1b150a27262bca00bb2674980516b45ad7d331eaa906060015b60405180910390a1505050565b6000546040516385bb392360e01b81523360048201526001600160a01b03909116906385bb392390602401602060405180830381865afa1580156103f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061041c91906109e7565b6040518060600160405280603a8152602001610b45603a9139906104535760405162461bcd60e51b81526004016101909190610998565b506001600160a01b0381811660009081526002602090815260409182902054825160608101909352603a8084529316159290610b0b90830139906104aa5760405162461bcd60e51b81526004016101909190610998565b506001600160a01b03811660008181526002602052604080822080546001600160a01b03191633908117909155905190929183917f02e4debb2ab36299bfcc998345f66f73428adbbda9ef5efef399d75a67a4b78a9190a35050565b6000546040516385bb392360e01b81523360048201526001600160a01b03909116906385bb392390602401602060405180830381865afa15801561054e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061057291906109e7565b6040518060600160405280603a8152602001610b45603a9139906105a95760405162461bcd60e51b81526004016101909190610998565b506001600160a01b0382811660009081526002602090815260409182902054825160608101909352603780845233949190911684149291610a9990830139906106055760405162461bcd60e51b81526004016101909190610998565b506001600160a01b0382811660009081526002602090815260409182902054825160608101909352603a8084529316159290610b0b908301399061065c5760405162461bcd60e51b81526004016101909190610998565b506001600160a01b03838116600081815260026020908152604080832080546001600160a01b03199081169091558786168085529382902080549091169587169586179055805194855290840192909252908201527f362e9cf018894fbf5dfe9c5cbfb25c3e3ac8c4d5beed564352f1af2e2712dfc8906060016103a3565b6001600160a01b03811660009081526001602052604090206060906106ff90610736565b92915050565b600061071a836001600160a01b038416610743565b9392505050565b600061071a836001600160a01b038416610792565b6060600061071a83610885565b600081815260018301602052604081205461078a575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556106ff565b5060006106ff565b6000818152600183016020526040812054801561087b5760006107b6600183610a09565b85549091506000906107ca90600190610a09565b905080821461082f5760008660000182815481106107ea576107ea610a2a565b906000526020600020015490508087600001848154811061080d5761080d610a2a565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061084057610840610a40565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506106ff565b60009150506106ff565b6060816000018054806020026020016040519081016040528092919081815260200182805480156108d557602002820191906000526020600020905b8154815260200190600101908083116108c1575b50505050509050919050565b80356001600160a01b03811681146108f857600080fd5b919050565b60006020828403121561090f57600080fd5b61071a826108e1565b6000806040838503121561092b57600080fd5b610934836108e1565b9150610942602084016108e1565b90509250929050565b6020808252825182820181905260009190848201906040850190845b8181101561098c5783516001600160a01b031683529284019291840191600101610967565b50909695505050505050565b60006020808352835180602085015260005b818110156109c6578581018301518582016040015282016109aa565b506000604082860101526040601f19601f8301168501019250505092915050565b6000602082840312156109f957600080fd5b8151801515811461071a57600080fd5b818103818111156106ff57634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fdfe353630307c52656769737472793a206f6e6c79207061796d656e74206163636f756e7420666163746f72792063616e2063616c6c20746869732066756e6374696f6e353630347c52656769737472793a2070726576696f757320636172642773207061796d656e74206163636f756e74206d69736d61746368353630327c52656769737472793a207061796d656e74206163636f756e74206265696e672072656d6f766564206e6f7420696e2074686520736574353630347c52656769737472793a207061796d656e74206163636f756e7420697320616c72656164792073657420666f72207468652063617264353630317c52656769737472793a206f6e6c79207061796d656e74206163636f756e742063616e2063616c6c20746869732066756e6374696f6ea26469706673582212203c97923f6f14a45f904087dcdced3b09f33cd32821438cd9cbf0add5824acaf064736f6c63430008160033"; +public class TangemPaymentAccountRegistry extends Contract { + public static final String BINARY = "60806040523462000030576200001e62000018620000d3565b62000156565b6040516110ab6200016e82396110ab90f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b90601f01601f191681019081106001600160401b038211176200006d57604052565b62000035565b906200008a6200008260405190565b92836200004b565b565b6001600160a01b031690565b90565b6001600160a01b038116036200003057565b905051906200008a826200009b565b9060208282031262000030576200009891620000ad565b620000986200121980380380620000ea8162000073565b928339810190620000bc565b62000098906200008c906001600160a01b031682565b6200009890620000f6565b62000098906200010c565b906200013662000098620001529262000117565b82546001600160a01b0319166001600160a01b03919091161790565b9055565b620001656200008a9162000117565b60006200012256fe6080604052600436101561001257600080fd5b60003560e01c80630cef7172146100b25780630d009297146100ad578063173825d9146100a85780633dc50952146100a35780634149177b1461009e57806379da564f14610099578063a727bc9014610094578063c45a01551461008f578063f00d4b5d1461008a5763f72a1107036100d857610353565b61033a565b610313565b6102cb565b610281565b6101f5565b6101dd565b6101c5565b6101a8565b61016f565b6001600160a01b031690565b90565b6001600160a01b0381165b036100d857565b600080fd5b905035906100ea826100c6565b565b906020828203126100d8576100c3916100dd565b6100c3906100b7906001600160a01b031682565b6100c390610100565b6100c390610114565b906101309061011d565b600052602052604060002090565b6100c3916008021c6100b7565b906100c3915461013e565b60006101666100c3926002610126565b61014b565b9052565b346100d8576101a461018a6101853660046100ec565b610156565b604051918291826001600160a01b03909116815260200190565b0390f35b346100d8576101c06101bb3660046100ec565b6105da565b604051005b346100d8576101c06101d83660046100ec565b610709565b346100d8576101c06101f03660046100ec565b61076f565b346100d8576101c06102083660046100ec565b6108f0565b0190565b9061023161022a610220845190565b8084529260200190565b9260200190565b9060005b8181106102425750505090565b90919261026861026160019286516001600160a01b0316815260200190565b9460200190565b929101610235565b60208082526100c392910190610211565b346100d8576101a461029c6102973660046100ec565b6108f9565b60405191829182610270565b91906040838203126100d8576100c39060206102c482866100dd565b94016100dd565b346100d8576101c06102de3660046102a8565b906109b8565b60009103126100d857565b6100c360008061014b565b61016b9061011d565b6020810192916100ea91906102fa565b346100d8576103233660046102e4565b6101a461032e6102ef565b60405191829182610303565b346100d8576101c061034d3660046102a8565b90610b01565b346100d8576101c06103663660046102a8565b90610b2d565b6100c3906100b7565b6100c3905461036c565b634e487b7160e01b600052604160045260246000fd5b90601f01601f1916810190811067ffffffffffffffff8211176103b757604052565b61037f565b8015156100d1565b905051906100ea826103bc565b906020828203126100d8576100c3916103c4565b6040513d6000823e3d90fd5b906100ea6103fe60405190565b9283610395565b67ffffffffffffffff81116103b757602090601f01601f19160190565b9061043461042f83610405565b6103f1565b918252565b610443603a610422565b7f353630317c52656769737472793a206f6e6c79207061796d656e74206163636f60208201527f756e742063616e2063616c6c20746869732066756e6374696f6e000000000000604082015290565b6100c3610439565b6100c3610492565b60005b8381106104b55750506000910152565b81810151838201526020016104a5565b6104e66104ef60209361020d936104da815190565b80835293849260200190565b958691016104a2565b601f01601f191690565b60208082526100c3929101906104c5565b156105125750565b6105349061051f60405190565b62461bcd60e51b8152918291600483016104f9565b0390fd5b61054a6105456000610375565b61011d565b90602061055660405190565b6385bb392360e01b815233600482015292839060249082905afa9182156105ca576100ea926105969160009161059b575b5061059061049a565b9061050a565b6105cf565b6105bd915060203d6020116105c3575b6105b58183610395565b8101906103d1565b38610587565b503d6105ab565b6103e5565b6100ea903390610b37565b6100ea90610538565b6105f06105456000610375565b9060206105fc60405190565b6385bb392360e01b815233600482015292839060249082905afa9182156105ca576100ea926106359160009161059b575061059061049a565b6106a3565b610644603b610422565b7f353630327c52656769737472793a207061796d656e74206163636f756e74206260208201527f65696e672072656d6f766564206e6f7420696e20746865207365740000000000604082015290565b6100c361063a565b6100c3610693565b6106c66106be6106b76100c3846001610126565b3390610ba3565b61059061069b565b6106d86106d23361011d565b9161011d565b907fe594d081b4382713733fe631966432c9cea5199afb2db5c3c1931f9f9300367961070360405190565b600090a3565b6100ea906105e3565b61071f6105456000610375565b90602061072b60405190565b6385bb392360e01b815233600482015292839060249082905afa9182156105ca576100ea926107649160009161059b575061059061049a565b6100ea903390610c7e565b6100ea90610712565b6107856105456000610375565b90602061079160405190565b6385bb392360e01b815233600482015292839060249082905afa9182156105ca576100ea926107ca9160009161059b575061059061049a565b610873565b6107d96030610422565b7f353630357c52656769737472793a2063617264206265696e672072656d6f766560208201526f19081b9bdd081a5b881d1a19481cd95d60821b604082015290565b6100c36107cf565b6100c361081b565b916001600160a01b0360089290920291821b911b5b9181191691161790565b919061085b6100c36108639361011d565b90835461082b565b9055565b6100ea9160009161084a565b6108a4610889610884836002610126565b610375565b61089b335b916001600160a01b031690565b14610590610823565b6108b960006108b4836002610126565b610867565b6108c56106d23361011d565b907f5f8ec0a3d11bc25dab3cc6b87b3add8f1797a221531def932c4d242f561abf2561070360405190565b6100ea90610778565b6109136100c36100c39261090b606090565b506001610126565b610cef565b6109226042610422565b7f353630307c52656769737472793a206f6e6c79207061796d656e74206163636f60208201527f756e7420666163746f72792063616e2063616c6c20746869732066756e63746960408201526137b760f11b606082015290565b6100c3610918565b6100c361097c565b906100ea916109ae6109a46100b76105456000610375565b3314610590610984565b906100ea91610c7e565b906100ea9161098c565b906109d06105456000610375565b9160206109dc60405190565b6385bb392360e01b815233600482015293849060249082905afa9283156105ca576100ea93610a159160009161059b575061059061049a565b610a83565b610a246040610422565b7f353630337c52656769737472793a207061796d656e74206163636f756e74206260208201527f65696e6720616464656420697320616c726561647920696e2074686520736574604082015290565b6100c3610a1a565b6100c3610a73565b90610a986106be6106b76100c3856001610126565b610abb610ab3610aac6100c3846001610126565b3390610d00565b610590610a7b565b610ad06106d2610aca3361011d565b9361011d565b917f381c0d11398486654573703c51ee8210ce9461764d133f9f0e53b6a539705331610afb60405190565b600090a4565b906100ea916109c2565b906100ea91610b236109a46100b76105456000610375565b906100ea91610b37565b906100ea91610b0b565b906106d2610b5991610545610ab382610b546100c3886001610126565b610d00565b907fa5e1f8b4009110f5525798d04ae2125421a12d0590aa52c13682ff1bd3c492ca61070360405190565b6100c39081906001600160a01b031681565b6100c36100c36100c39290565b90610bd4610bd0610bcb610bc660006100c396610bbe600090565b500194610114565b610b84565b610b96565b9190565b610e66565b6100b76100c36100c39290565b6100c390610bd9565b610bf9603a610422565b7f353630347c52656769737472793a207061796d656e74206163636f756e74206960208201527f7320616c72656164792073657420666f72207468652063617264000000000000604082015290565b6100c3610bef565b6100c3610c48565b906001600160a01b0390610840565b90610c776100c36108639261011d565b8254610c58565b906106d2610cc491610cb0610c97610884866002610126565b610ca761088e6100b76000610be6565b14610590610c50565b61054581610cbf866002610126565b610c67565b907fc063fc300750e8c5649c6b3779f6c4b05e7b38b170ee5c4a4b222ede9a28808361070360405190565b606090610cfb90610fc8565b905090565b90610d1b610bd0610bcb610bc660006100c396610bbe600090565b611005565b90610130565b6100c39081565b6100c39054610d26565b634e487b7160e01b600052601160045260246000fd5b91908203918211610d5a57565b610d37565b634e487b7160e01b600052603260045260246000fd5b8054821015610d9857610d8f600191600052602060002090565b91020190600090565b610d5f565b6100c3916008021c81565b906100c39154610d9d565b9160001960089290920291821b911b610840565b9190610dd66100c36108639390565b908354610db3565b9060001990610840565b90610df86100c361086392610b96565b8254610dde565b634e487b7160e01b600052603160045260246000fd5b6100ea91600091610dc7565b80548015610e44576000190190610e41610e3b8383610d75565b90610e15565b55565b610dff565b9190610dd66100c361086393610b96565b6100ea91600091610e49565b90610e7c610e778260018501610d20565b610d2d565b610e866000610b96565b8114610f3457610eeb6100c392600092610ee095610ee56001978893610eb4610eae86610b96565b82610d4d565b88850191610ed2610ec3845490565b610ecc89610b96565b90610d4d565b808303610ef0575b50505090565b610e21565b01610d20565b610e5a565b610f19610f1f610f2c94610f10610f0a610f279589610d75565b90610da8565b92839188610d75565b90610dc7565b888801610d20565b610de8565b388080610eda565b505050600090565b90610f57610f4b610220845490565b92600052602060002090565b9060005b818110610f685750505090565b909192610f8c610f85600192610f7d87610d2d565b815260200190565b9460010190565b929101610f5b565b906100c391610f3c565b906100ea610fb892610faf60405190565b93848092610f94565b0383610395565b6100c390610f9e565b60006100c391610fd6606090565b5001610fbf565b90815491680100000000000000008310156103b75782610f199160016100ea95018155610d75565b611016611012838361104a565b1590565b156110435761103e91610f27906001611037846110338482610fdd565b5490565b9301610d20565b600190565b5050600090565b611063916001610e779261105c600090565b5001610d20565b611070610bd06000610b96565b14159056fea26469706673582212205e9abf37b9af5365c966f2cb4bdb949d15aac5e8ec856dbc6a6c8fc7e9de783764736f6c63430008160033"; - public static final String FUNC_CHANGEPAYMENTACCOUNTCARD = "changePaymentAccountCard"; + private static String librariesLinkedBinary; - public static final String FUNC_CHANGEPAYMENTACCOUNTOWNER = "changePaymentAccountOwner"; + public static final String FUNC_ADDCARD = "addCard"; + + public static final String FUNC_ADDCARDONDEPLOY = "addCardOnDeploy"; + + public static final String FUNC_CHANGEOWNER = "changeOwner"; public static final String FUNC_FACTORY = "factory"; - public static final String FUNC_INITPAYMENTACCOUNTCARD = "initPaymentAccountCard"; + public static final String FUNC_INITOWNER = "initOwner"; - public static final String FUNC_INITPAYMENTACCOUNTOWNER = "initPaymentAccountOwner"; + public static final String FUNC_INITOWNERONDEPLOY = "initOwnerOnDeploy"; public static final String FUNC_PAYMENTACCOUNTBYCARD = "paymentAccountByCard"; public static final String FUNC_PAYMENTACCOUNTSBYOWNER = "paymentAccountsByOwner"; - public static final Event PAYMENTACCOUNTCARDCHANGED_EVENT = new Event("PaymentAccountCardChanged", - Arrays.asList(new TypeReference

() { - }, new TypeReference
() { - }, new TypeReference
() { - })); + public static final String FUNC_REMOVECARD = "removeCard"; - public static final Event PAYMENTACCOUNTCARDREGISTERED_EVENT = new Event("PaymentAccountCardRegistered", - Arrays.asList(new TypeReference
(true) { - }, new TypeReference
(true) { - })); + public static final String FUNC_REMOVEOWNER = "removeOwner"; - public static final Event PAYMENTACCOUNTOWNERCHANGED_EVENT = new Event("PaymentAccountOwnerChanged", - Arrays.asList(new TypeReference
() { - }, new TypeReference
() { - }, new TypeReference
() { - })); + public static final Event CARDREGISTERED_EVENT = new Event("CardRegistered", + Arrays.>asList(new TypeReference
(true) {}, new TypeReference
(true) {})); + ; - public static final Event PAYMENTACCOUNTOWNERREGISTERED_EVENT = new Event("PaymentAccountOwnerRegistered", - Arrays.asList(new TypeReference
(true) { - }, new TypeReference
(true) { - })); + public static final Event CARDREMOVED_EVENT = new Event("CardRemoved", + Arrays.>asList(new TypeReference
(true) {}, new TypeReference
(true) {})); + ; + + public static final Event OWNERCHANGED_EVENT = new Event("OwnerChanged", + Arrays.>asList(new TypeReference
(true) {}, new TypeReference
(true) {}, new TypeReference
(true) {})); + ; + + public static final Event OWNERREGISTERED_EVENT = new Event("OwnerRegistered", + Arrays.>asList(new TypeReference
(true) {}, new TypeReference
(true) {})); + ; + + public static final Event OWNERREMOVED_EVENT = new Event("OwnerRemoved", + Arrays.>asList(new TypeReference
(true) {}, new TypeReference
(true) {})); + ; @Deprecated - protected TangemPaymentAccountRegistry(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + protected TangemPaymentAccountRegistry(String contractAddress, Web3j web3j, + Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); } - protected TangemPaymentAccountRegistry(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { + protected TangemPaymentAccountRegistry(String contractAddress, Web3j web3j, + Credentials credentials, ContractGasProvider contractGasProvider) { super(BINARY, contractAddress, web3j, credentials, contractGasProvider); } @Deprecated - protected TangemPaymentAccountRegistry(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) { + protected TangemPaymentAccountRegistry(String contractAddress, Web3j web3j, + TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) { super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); } - protected TangemPaymentAccountRegistry(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { + protected TangemPaymentAccountRegistry(String contractAddress, Web3j web3j, + TransactionManager transactionManager, ContractGasProvider contractGasProvider) { super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); } - public static List getPaymentAccountCardChangedEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(PAYMENTACCOUNTCARDCHANGED_EVENT, transactionReceipt); - ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { - PaymentAccountCardChangedEventResponse typedResponse = new PaymentAccountCardChangedEventResponse(); - typedResponse.log = eventValues.getLog(); - typedResponse.paymentAccount = (String) eventValues.getNonIndexedValues().get(0).getValue(); - typedResponse.previousCard = (String) eventValues.getNonIndexedValues().get(1).getValue(); - typedResponse.newCard = (String) eventValues.getNonIndexedValues().get(2).getValue(); - responses.add(typedResponse); - } - return responses; - } - - public static PaymentAccountCardChangedEventResponse getPaymentAccountCardChangedEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(PAYMENTACCOUNTCARDCHANGED_EVENT, log); - PaymentAccountCardChangedEventResponse typedResponse = new PaymentAccountCardChangedEventResponse(); - typedResponse.log = log; - typedResponse.paymentAccount = (String) eventValues.getNonIndexedValues().get(0).getValue(); - typedResponse.previousCard = (String) eventValues.getNonIndexedValues().get(1).getValue(); - typedResponse.newCard = (String) eventValues.getNonIndexedValues().get(2).getValue(); - return typedResponse; - } - - public static List getPaymentAccountCardRegisteredEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(PAYMENTACCOUNTCARDREGISTERED_EVENT, transactionReceipt); - ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { - PaymentAccountCardRegisteredEventResponse typedResponse = new PaymentAccountCardRegisteredEventResponse(); + public static List getCardRegisteredEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(CARDREGISTERED_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + CardRegisteredEventResponse typedResponse = new CardRegisteredEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); @@ -130,44 +119,102 @@ class TangemPaymentAccountRegistry extends Contract { return responses; } - public static PaymentAccountCardRegisteredEventResponse getPaymentAccountCardRegisteredEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(PAYMENTACCOUNTCARDREGISTERED_EVENT, log); - PaymentAccountCardRegisteredEventResponse typedResponse = new PaymentAccountCardRegisteredEventResponse(); + public static CardRegisteredEventResponse getCardRegisteredEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(CARDREGISTERED_EVENT, log); + CardRegisteredEventResponse typedResponse = new CardRegisteredEventResponse(); typedResponse.log = log; typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); return typedResponse; } - public static List getPaymentAccountOwnerChangedEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(PAYMENTACCOUNTOWNERCHANGED_EVENT, transactionReceipt); - ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { - PaymentAccountOwnerChangedEventResponse typedResponse = new PaymentAccountOwnerChangedEventResponse(); + public Flowable cardRegisteredEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getCardRegisteredEventFromLog(log)); + } + + public Flowable cardRegisteredEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(CARDREGISTERED_EVENT)); + return cardRegisteredEventFlowable(filter); + } + + public static List getCardRemovedEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(CARDREMOVED_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + CardRemovedEventResponse typedResponse = new CardRemovedEventResponse(); typedResponse.log = eventValues.getLog(); - typedResponse.paymentAccount = (String) eventValues.getNonIndexedValues().get(0).getValue(); - typedResponse.previousOwner = (String) eventValues.getNonIndexedValues().get(1).getValue(); - typedResponse.newOwner = (String) eventValues.getNonIndexedValues().get(2).getValue(); + typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); responses.add(typedResponse); } return responses; } - public static PaymentAccountOwnerChangedEventResponse getPaymentAccountOwnerChangedEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(PAYMENTACCOUNTOWNERCHANGED_EVENT, log); - PaymentAccountOwnerChangedEventResponse typedResponse = new PaymentAccountOwnerChangedEventResponse(); + public static CardRemovedEventResponse getCardRemovedEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(CARDREMOVED_EVENT, log); + CardRemovedEventResponse typedResponse = new CardRemovedEventResponse(); typedResponse.log = log; - typedResponse.paymentAccount = (String) eventValues.getNonIndexedValues().get(0).getValue(); - typedResponse.previousOwner = (String) eventValues.getNonIndexedValues().get(1).getValue(); - typedResponse.newOwner = (String) eventValues.getNonIndexedValues().get(2).getValue(); + typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.card = (String) eventValues.getIndexedValues().get(1).getValue(); return typedResponse; } - public static List getPaymentAccountOwnerRegisteredEvents(TransactionReceipt transactionReceipt) { - List valueList = staticExtractEventParametersWithLog(PAYMENTACCOUNTOWNERREGISTERED_EVENT, transactionReceipt); - ArrayList responses = new ArrayList(valueList.size()); - for (EventValuesWithLog eventValues : valueList) { - PaymentAccountOwnerRegisteredEventResponse typedResponse = new PaymentAccountOwnerRegisteredEventResponse(); + public Flowable cardRemovedEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getCardRemovedEventFromLog(log)); + } + + public Flowable cardRemovedEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(CARDREMOVED_EVENT)); + return cardRemovedEventFlowable(filter); + } + + public static List getOwnerChangedEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(OWNERCHANGED_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + OwnerChangedEventResponse typedResponse = new OwnerChangedEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.previousOwner = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.newOwner = (String) eventValues.getIndexedValues().get(2).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public static OwnerChangedEventResponse getOwnerChangedEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(OWNERCHANGED_EVENT, log); + OwnerChangedEventResponse typedResponse = new OwnerChangedEventResponse(); + typedResponse.log = log; + typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.previousOwner = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.newOwner = (String) eventValues.getIndexedValues().get(2).getValue(); + return typedResponse; + } + + public Flowable ownerChangedEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getOwnerChangedEventFromLog(log)); + } + + public Flowable ownerChangedEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(OWNERCHANGED_EVENT)); + return ownerChangedEventFlowable(filter); + } + + public static List getOwnerRegisteredEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(OWNERREGISTERED_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + OwnerRegisteredEventResponse typedResponse = new OwnerRegisteredEventResponse(); typedResponse.log = eventValues.getLog(); typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); typedResponse.owner = (String) eventValues.getIndexedValues().get(1).getValue(); @@ -176,151 +223,124 @@ class TangemPaymentAccountRegistry extends Contract { return responses; } - public static PaymentAccountOwnerRegisteredEventResponse getPaymentAccountOwnerRegisteredEventFromLog(Log log) { - EventValuesWithLog eventValues = staticExtractEventParametersWithLog(PAYMENTACCOUNTOWNERREGISTERED_EVENT, log); - PaymentAccountOwnerRegisteredEventResponse typedResponse = new PaymentAccountOwnerRegisteredEventResponse(); + public static OwnerRegisteredEventResponse getOwnerRegisteredEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(OWNERREGISTERED_EVENT, log); + OwnerRegisteredEventResponse typedResponse = new OwnerRegisteredEventResponse(); typedResponse.log = log; typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); typedResponse.owner = (String) eventValues.getIndexedValues().get(1).getValue(); return typedResponse; } - @Deprecated - public static TangemPaymentAccountRegistry load(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { - return new TangemPaymentAccountRegistry(contractAddress, web3j, credentials, gasPrice, gasLimit); + public Flowable ownerRegisteredEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getOwnerRegisteredEventFromLog(log)); } - @Deprecated - public static TangemPaymentAccountRegistry load(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) { - return new TangemPaymentAccountRegistry(contractAddress, web3j, transactionManager, gasPrice, gasLimit); - } - - public static TangemPaymentAccountRegistry load(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { - return new TangemPaymentAccountRegistry(contractAddress, web3j, credentials, contractGasProvider); - } - - public static TangemPaymentAccountRegistry load(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { - return new TangemPaymentAccountRegistry(contractAddress, web3j, transactionManager, contractGasProvider); - } - - public static RemoteCall deploy(Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider, String factory_) { - String encodedConstructor = FunctionEncoder.encodeConstructor(List.of(new Address(160, factory_))); - return deployRemoteCall(TangemPaymentAccountRegistry.class, web3j, credentials, contractGasProvider, BINARY, encodedConstructor); - } - - public static RemoteCall deploy(Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider, String factory_) { - String encodedConstructor = FunctionEncoder.encodeConstructor(List.of(new Address(160, factory_))); - return deployRemoteCall(TangemPaymentAccountRegistry.class, web3j, transactionManager, contractGasProvider, BINARY, encodedConstructor); - } - - @Deprecated - public static RemoteCall deploy(Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit, String factory_) { - String encodedConstructor = FunctionEncoder.encodeConstructor(List.of(new Address(160, factory_))); - return deployRemoteCall(TangemPaymentAccountRegistry.class, web3j, credentials, gasPrice, gasLimit, BINARY, encodedConstructor); - } - - @Deprecated - public static RemoteCall deploy(Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit, String factory_) { - String encodedConstructor = FunctionEncoder.encodeConstructor(List.of(new Address(160, factory_))); - return deployRemoteCall(TangemPaymentAccountRegistry.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, encodedConstructor); - } - - public Flowable paymentAccountCardChangedEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getPaymentAccountCardChangedEventFromLog(log)); - } - - public Flowable paymentAccountCardChangedEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + public Flowable ownerRegisteredEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(PAYMENTACCOUNTCARDCHANGED_EVENT)); - return paymentAccountCardChangedEventFlowable(filter); + filter.addSingleTopic(EventEncoder.encode(OWNERREGISTERED_EVENT)); + return ownerRegisteredEventFlowable(filter); } - public Flowable paymentAccountCardRegisteredEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getPaymentAccountCardRegisteredEventFromLog(log)); + public static List getOwnerRemovedEvents( + TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(OWNERREMOVED_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (Contract.EventValuesWithLog eventValues : valueList) { + OwnerRemovedEventResponse typedResponse = new OwnerRemovedEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.owner = (String) eventValues.getIndexedValues().get(1).getValue(); + responses.add(typedResponse); + } + return responses; } - public Flowable paymentAccountCardRegisteredEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + public static OwnerRemovedEventResponse getOwnerRemovedEventFromLog(Log log) { + Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(OWNERREMOVED_EVENT, log); + OwnerRemovedEventResponse typedResponse = new OwnerRemovedEventResponse(); + typedResponse.log = log; + typedResponse.paymentAccount = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.owner = (String) eventValues.getIndexedValues().get(1).getValue(); + return typedResponse; + } + + public Flowable ownerRemovedEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(log -> getOwnerRemovedEventFromLog(log)); + } + + public Flowable ownerRemovedEventFlowable( + DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(PAYMENTACCOUNTCARDREGISTERED_EVENT)); - return paymentAccountCardRegisteredEventFlowable(filter); + filter.addSingleTopic(EventEncoder.encode(OWNERREMOVED_EVENT)); + return ownerRemovedEventFlowable(filter); } - public Flowable paymentAccountOwnerChangedEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getPaymentAccountOwnerChangedEventFromLog(log)); - } - - public Flowable paymentAccountOwnerChangedEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(PAYMENTACCOUNTOWNERCHANGED_EVENT)); - return paymentAccountOwnerChangedEventFlowable(filter); - } - - public Flowable paymentAccountOwnerRegisteredEventFlowable(EthFilter filter) { - return web3j.ethLogFlowable(filter).map(log -> getPaymentAccountOwnerRegisteredEventFromLog(log)); - } - - public Flowable paymentAccountOwnerRegisteredEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { - EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); - filter.addSingleTopic(EventEncoder.encode(PAYMENTACCOUNTOWNERREGISTERED_EVENT)); - return paymentAccountOwnerRegisteredEventFlowable(filter); - } - - public RemoteFunctionCall changePaymentAccountCard(String previousCard, String newCard) { + public RemoteFunctionCall addCard(String card) { final Function function = new Function( - FUNC_CHANGEPAYMENTACCOUNTCARD, - Arrays.asList(new Address(160, previousCard), - new Address(160, newCard)), - Collections.emptyList()); + FUNC_ADDCARD, + Arrays.asList(new org.web3j.abi.datatypes.Address(160, card)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } - public RemoteFunctionCall changePaymentAccountOwner(String previousOwner, String newOwner) { + public RemoteFunctionCall addCardOnDeploy(String card, + String paymentAccount) { final Function function = new Function( - FUNC_CHANGEPAYMENTACCOUNTOWNER, - Arrays.asList(new Address(160, previousOwner), - new Address(160, newOwner)), - Collections.emptyList()); + FUNC_ADDCARDONDEPLOY, + Arrays.asList(new org.web3j.abi.datatypes.Address(160, card), + new org.web3j.abi.datatypes.Address(160, paymentAccount)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteFunctionCall changeOwner(String previousOwner, + String newOwner) { + final Function function = new Function( + FUNC_CHANGEOWNER, + Arrays.asList(new org.web3j.abi.datatypes.Address(160, previousOwner), + new org.web3j.abi.datatypes.Address(160, newOwner)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } public RemoteFunctionCall factory() { final Function function = new Function(FUNC_FACTORY, - List.of(), - List.of(new TypeReference
() { - })); + Arrays.asList(), + Arrays.>asList(new TypeReference
() {})); return executeRemoteCallSingleValueReturn(function, String.class); } - public RemoteFunctionCall initPaymentAccountCard(String card) { + public RemoteFunctionCall initOwner(String owner) { final Function function = new Function( - FUNC_INITPAYMENTACCOUNTCARD, - List.of(new Address(160, card)), - Collections.emptyList()); + FUNC_INITOWNER, + Arrays.asList(new org.web3j.abi.datatypes.Address(160, owner)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } - public RemoteFunctionCall initPaymentAccountOwner(String paymentAccount, String owner) { + public RemoteFunctionCall initOwnerOnDeploy(String owner, + String paymentAccount) { final Function function = new Function( - FUNC_INITPAYMENTACCOUNTOWNER, - Arrays.asList(new Address(160, paymentAccount), - new Address(160, owner)), - Collections.emptyList()); + FUNC_INITOWNERONDEPLOY, + Arrays.asList(new org.web3j.abi.datatypes.Address(160, owner), + new org.web3j.abi.datatypes.Address(160, paymentAccount)), + Collections.>emptyList()); return executeRemoteCallTransaction(function); } public RemoteFunctionCall paymentAccountByCard(String param0) { final Function function = new Function(FUNC_PAYMENTACCOUNTBYCARD, - List.of(new Address(160, param0)), - List.of(new TypeReference
() { - })); + Arrays.asList(new org.web3j.abi.datatypes.Address(160, param0)), + Arrays.>asList(new TypeReference
() {})); return executeRemoteCallSingleValueReturn(function, String.class); } public RemoteFunctionCall paymentAccountsByOwner(String owner) { final Function function = new Function(FUNC_PAYMENTACCOUNTSBYOWNER, - List.of(new Address(160, owner)), - List.of(new TypeReference>() { - })); + Arrays.asList(new org.web3j.abi.datatypes.Address(160, owner)), + Arrays.>asList(new TypeReference>() {})); return new RemoteFunctionCall(function, new Callable() { @Override @@ -332,21 +352,97 @@ class TangemPaymentAccountRegistry extends Contract { }); } - public static class PaymentAccountCardChangedEventResponse extends BaseEventResponse { - public String paymentAccount; - - public String previousCard; - - public String newCard; + public RemoteFunctionCall removeCard(String card) { + final Function function = new Function( + FUNC_REMOVECARD, + Arrays.asList(new org.web3j.abi.datatypes.Address(160, card)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); } - public static class PaymentAccountCardRegisteredEventResponse extends BaseEventResponse { + public RemoteFunctionCall removeOwner(String owner) { + final Function function = new Function( + FUNC_REMOVEOWNER, + Arrays.asList(new org.web3j.abi.datatypes.Address(160, owner)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + @Deprecated + public static TangemPaymentAccountRegistry load(String contractAddress, Web3j web3j, + Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + return new TangemPaymentAccountRegistry(contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + @Deprecated + public static TangemPaymentAccountRegistry load(String contractAddress, Web3j web3j, + TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) { + return new TangemPaymentAccountRegistry(contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + public static TangemPaymentAccountRegistry load(String contractAddress, Web3j web3j, + Credentials credentials, ContractGasProvider contractGasProvider) { + return new TangemPaymentAccountRegistry(contractAddress, web3j, credentials, contractGasProvider); + } + + public static TangemPaymentAccountRegistry load(String contractAddress, Web3j web3j, + TransactionManager transactionManager, ContractGasProvider contractGasProvider) { + return new TangemPaymentAccountRegistry(contractAddress, web3j, transactionManager, contractGasProvider); + } + + public static RemoteCall deploy(Web3j web3j, + Credentials credentials, ContractGasProvider contractGasProvider, String factory_) { + String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(new org.web3j.abi.datatypes.Address(160, factory_))); + return deployRemoteCall(TangemPaymentAccountRegistry.class, web3j, credentials, contractGasProvider, getDeploymentBinary(), encodedConstructor); + } + + public static RemoteCall deploy(Web3j web3j, + TransactionManager transactionManager, ContractGasProvider contractGasProvider, + String factory_) { + String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(new org.web3j.abi.datatypes.Address(160, factory_))); + return deployRemoteCall(TangemPaymentAccountRegistry.class, web3j, transactionManager, contractGasProvider, getDeploymentBinary(), encodedConstructor); + } + + @Deprecated + public static RemoteCall deploy(Web3j web3j, + Credentials credentials, BigInteger gasPrice, BigInteger gasLimit, String factory_) { + String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(new org.web3j.abi.datatypes.Address(160, factory_))); + return deployRemoteCall(TangemPaymentAccountRegistry.class, web3j, credentials, gasPrice, gasLimit, getDeploymentBinary(), encodedConstructor); + } + + @Deprecated + public static RemoteCall deploy(Web3j web3j, + TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit, + String factory_) { + String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(new org.web3j.abi.datatypes.Address(160, factory_))); + return deployRemoteCall(TangemPaymentAccountRegistry.class, web3j, transactionManager, gasPrice, gasLimit, getDeploymentBinary(), encodedConstructor); + } + + public static void linkLibraries(List references) { + librariesLinkedBinary = linkBinaryWithReferences(BINARY, references); + } + + private static String getDeploymentBinary() { + if (librariesLinkedBinary != null) { + return librariesLinkedBinary; + } else { + return BINARY; + } + } + + public static class CardRegisteredEventResponse extends BaseEventResponse { public String paymentAccount; public String card; } - public static class PaymentAccountOwnerChangedEventResponse extends BaseEventResponse { + public static class CardRemovedEventResponse extends BaseEventResponse { + public String paymentAccount; + + public String card; + } + + public static class OwnerChangedEventResponse extends BaseEventResponse { public String paymentAccount; public String previousOwner; @@ -354,9 +450,15 @@ class TangemPaymentAccountRegistry extends Contract { public String newOwner; } - public static class PaymentAccountOwnerRegisteredEventResponse extends BaseEventResponse { + public static class OwnerRegisteredEventResponse extends BaseEventResponse { public String paymentAccount; public String owner; } -} + + public static class OwnerRemovedEventResponse extends BaseEventResponse { + public String paymentAccount; + + public String owner; + } +} \ No newline at end of file diff --git a/libs/visa/src/main/kotlin/com/tangem/lib/visa/DefaultVisaContractInfoProvider.kt b/libs/visa/src/main/kotlin/com/tangem/lib/visa/DefaultVisaContractInfoProvider.kt index 312f708435..2265f6258f 100644 --- a/libs/visa/src/main/kotlin/com/tangem/lib/visa/DefaultVisaContractInfoProvider.kt +++ b/libs/visa/src/main/kotlin/com/tangem/lib/visa/DefaultVisaContractInfoProvider.kt @@ -102,8 +102,7 @@ internal class DefaultVisaContractInfoProvider( { paymentAccount.availableForDebtPayment().send() }, { paymentAccount.blockedAmount().send() }, { paymentAccount.debtAmount().send() }, - { paymentAccount.pendingRefundTotal().send() }, - ) { total, verified, payment, withdrawal, debtPayment, blocked, debt, refund -> + ) { total, verified, payment, withdrawal, debtPayment, blocked, debt -> val decimals = paymentToken.decimals Balances( @@ -116,40 +115,42 @@ internal class DefaultVisaContractInfoProvider( ), blocked = blocked.toBigDecimal(decimals), debt = debt.toBigDecimal(decimals), - pendingRefund = refund.toBigDecimal(decimals), ) } } + @Suppress("UnusedPrivateMember") private fun fetchLimits( paymentAccount: TangemPaymentAccount, paymentToken: PaymentTokenInfo, ): Triple { - val ( - oldLimit, - newLimit, - changeDateSeconds, - ) = paymentAccount.limits().send() - - return Triple( - first = getLimits(oldLimit, paymentToken), - second = getLimits(newLimit, paymentToken), - third = changeDateSeconds.toInstant(), - ) + TODO() // TODO: [REDACTED_TASK_KEY] + // val ( + // oldLimit, + // newLimit, + // changeDateSeconds, + // ) = paymentAccount.cards("").send().component5() + // + // return Triple( + // first = getLimits(oldLimit, paymentToken), + // second = getLimits(newLimit, paymentToken), + // third = changeDateSeconds.toInstant(), + // ) } + @Suppress("UnusedPrivateMember") private fun getLimits(limit: TangemPaymentAccount.Limits, paymentToken: PaymentTokenInfo): Limits = Limits( - spendLimit = limit._01_spendLimit.toLimit(paymentToken.decimals), - noOtpLimit = limit._02_noOtpSpendLimit.toLimit(paymentToken.decimals), - singleTransactionLimit = limit._00_singleTransactionLimit.toBigDecimal(paymentToken.decimals), - expirationDate = limit._03_spendLimitsTimer.expireTimestamp.toInstant(), - spendPeriodSeconds = limit._04_spendLimitsPeriod, + spendLimit = limit.spendLimit.toLimit(paymentToken.decimals), + noOtpLimit = limit.noConfirmationSpendLimit.toLimit(paymentToken.decimals), + singleTransactionLimit = limit.singleTransactionLimit.toBigDecimal(paymentToken.decimals), + expirationDate = limit.spendLimitsTimer.expireTimestamp.toInstant(), + spendPeriodSeconds = limit.spendLimitsPeriod, ) private fun TangemPaymentAccount.Limit.toLimit(decimals: Int): Limits.Limit { return Limits.Limit( - limit = _00_limit.toBigDecimal(decimals), - spent = _01_spent.toBigDecimal(decimals), + limit = limit.toBigDecimal(decimals), + spent = spent.toBigDecimal(decimals), ) } diff --git a/libs/visa/src/main/kotlin/com/tangem/lib/visa/model/VisaContractInfo.kt b/libs/visa/src/main/kotlin/com/tangem/lib/visa/model/VisaContractInfo.kt index e2e6f98d58..e50c6e3c89 100644 --- a/libs/visa/src/main/kotlin/com/tangem/lib/visa/model/VisaContractInfo.kt +++ b/libs/visa/src/main/kotlin/com/tangem/lib/visa/model/VisaContractInfo.kt @@ -25,7 +25,6 @@ data class VisaContractInfo( val available: Available, val blocked: BigDecimal, val debt: BigDecimal, - val pendingRefund: BigDecimal, ) { data class Available( diff --git a/settings.gradle.kts b/settings.gradle.kts index 1ad6153ba0..b89a9482f9 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -106,6 +106,17 @@ dependencyResolutionManagement { includeGroupAndSubgroups("com.tangem.ic4j") } } + maven { + // setting any repository from tangem project allows maven search all packages in the project + url = uri("https://maven.pkg.github.com/tangem/web3j") + credentials { + username = properties.getProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR") + password = properties.getProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN") + } + content { + includeGroupAndSubgroups("org.web3j") + } + } maven("https://jitpack.io") } From 06e132ba04fa9e73c3fd18e7c8bbbb7ff1449d5b Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 18 Feb 2025 20:10:42 +0300 Subject: [PATCH 07/33] Updated on 2026-08-14 --- .../DefaultWalletConnectComponent.kt | 71 +++++++++++++++++++ .../ui/walletconnect/WalletConnectFragment.kt | 68 ------------------ ...nectViewModel.kt => WalletConnectModel.kt} | 19 ++--- .../api/WalletConnectComponent.kt | 8 +++ .../di/WalletConnectFeatureModule.kt | 25 +++++++ .../tangem/tap/routing/utils/ChildFactory.kt | 17 ++++- 6 files changed, 129 insertions(+), 79 deletions(-) create mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/DefaultWalletConnectComponent.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectFragment.kt rename app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/{WalletConnectViewModel.kt => WalletConnectModel.kt} (82%) create mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/api/WalletConnectComponent.kt create mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/di/WalletConnectFeatureModule.kt diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/DefaultWalletConnectComponent.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/DefaultWalletConnectComponent.kt new file mode 100644 index 0000000000..5fadd6a1e8 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/DefaultWalletConnectComponent.kt @@ -0,0 +1,71 @@ +package com.tangem.tap.features.details.ui.walletconnect + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.ui.Modifier +import com.arkivanov.essenty.lifecycle.subscribe +import com.tangem.common.routing.AppRouter +import com.tangem.core.analytics.Analytics +import com.tangem.core.decompose.context.AppComponentContext +import com.tangem.core.decompose.model.getOrCreateModel +import com.tangem.tap.common.analytics.events.WalletConnect +import com.tangem.tap.common.extensions.dispatchNavigationAction +import com.tangem.tap.features.details.redux.walletconnect.WalletConnectState +import com.tangem.tap.features.details.ui.walletconnect.api.WalletConnectComponent +import com.tangem.tap.store +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import org.rekotlin.StoreSubscriber + +@Suppress("UnusedPrivateMember") +internal class DefaultWalletConnectComponent @AssistedInject constructor( + @Assisted appComponentContext: AppComponentContext, + @Assisted params: Unit, +) : WalletConnectComponent, AppComponentContext by appComponentContext, StoreSubscriber { + + private val model: WalletConnectModel = getOrCreateModel() + + private var screenState: MutableState? = null + + init { + lifecycle.subscribe( + onCreate = { + Analytics.send(WalletConnect.ScreenOpened()) + screenState = mutableStateOf(model.updateState(store.state.walletConnectState)) + }, + onStart = { + store.subscribe(this) { state -> + state.skipRepeats { oldState, newState -> + oldState.walletConnectState == newState.walletConnectState + }.select { it.walletConnectState } + } + }, + onStop = { + store.unsubscribe(this) + }, + ) + } + + override fun newState(state: WalletConnectState) { + screenState?.value = model.updateState(state) + } + + @Composable + override fun Content(modifier: Modifier) { + val state = screenState?.value ?: return + WalletConnectScreen( + modifier = modifier, + state = state, + onBackClick = { + store.dispatchNavigationAction(AppRouter::pop) + }, + ) + } + + @AssistedFactory + interface Factory : WalletConnectComponent.Factory { + override fun create(context: AppComponentContext, params: Unit): DefaultWalletConnectComponent + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectFragment.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectFragment.kt deleted file mode 100644 index d720c10ec7..0000000000 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectFragment.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.tangem.tap.features.details.ui.walletconnect - -import android.os.Bundle -import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.mutableStateOf -import androidx.compose.ui.Modifier -import androidx.fragment.app.viewModels -import com.tangem.common.routing.AppRouter -import com.tangem.core.analytics.Analytics -import com.tangem.core.ui.UiDependencies -import com.tangem.core.ui.screen.ComposeFragment -import com.tangem.tap.common.analytics.events.WalletConnect -import com.tangem.tap.common.extensions.dispatchNavigationAction -import com.tangem.tap.features.details.redux.walletconnect.WalletConnectState -import com.tangem.tap.store -import dagger.hilt.android.AndroidEntryPoint -import org.rekotlin.StoreSubscriber -import javax.inject.Inject - -@AndroidEntryPoint -internal class WalletConnectFragment : ComposeFragment(), StoreSubscriber { - - @Inject - override lateinit var uiDependencies: UiDependencies - - private val viewModel: WalletConnectViewModel by viewModels() - - private var screenState: MutableState? = null - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - Analytics.send(WalletConnect.ScreenOpened()) - lifecycle.addObserver(viewModel) - screenState = mutableStateOf(viewModel.updateState(store.state.walletConnectState)) - } - - @Composable - override fun ScreenContent(modifier: Modifier) { - val state = screenState?.value ?: return - WalletConnectScreen( - modifier = modifier, - state = state, - onBackClick = { - store.dispatchNavigationAction(AppRouter::pop) - }, - ) - } - - override fun onStart() { - super.onStart() - store.subscribe(this) { state -> - state.skipRepeats { oldState, newState -> - oldState.walletConnectState == newState.walletConnectState - }.select { it.walletConnectState } - } - } - - override fun onStop() { - super.onStop() - store.unsubscribe(this) - } - - override fun newState(state: WalletConnectState) { - if (activity == null || view == null) return - screenState?.value = viewModel.updateState(state) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectViewModel.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectModel.kt similarity index 82% rename from app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectViewModel.kt rename to app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectModel.kt index 2ee11076ee..6372c2f648 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectModel.kt @@ -1,31 +1,34 @@ package com.tangem.tap.features.details.ui.walletconnect -import androidx.lifecycle.* +import androidx.compose.runtime.Stable import arrow.core.getOrElse +import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.model.Model import com.tangem.core.ui.clipboard.ClipboardManager import com.tangem.domain.qrscanning.models.SourceType import com.tangem.domain.qrscanning.usecases.ListenToQrScanningUseCase import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction import com.tangem.tap.features.details.redux.walletconnect.WalletConnectState import com.tangem.tap.store -import dagger.hilt.android.lifecycle.HiltViewModel +import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.launch import timber.log.Timber import javax.inject.Inject -@HiltViewModel -internal class WalletConnectViewModel @Inject constructor( +@Stable +@ComponentScoped +internal class WalletConnectModel @Inject constructor( + override val dispatchers: CoroutineDispatcherProvider, private val listenToQrScanningUseCase: ListenToQrScanningUseCase, private val clipboardManager: ClipboardManager, -) : ViewModel(), DefaultLifecycleObserver { +) : Model() { - override fun onCreate(owner: LifecycleOwner) { - viewModelScope.launch { + init { + modelScope.launch { listenToQrScanningUseCase(SourceType.WALLET_CONNECT) .getOrElse { emptyFlow() } - .flowWithLifecycle(owner.lifecycle, minActiveState = Lifecycle.State.CREATED) .collect { store.dispatch(WalletConnectAction.OpenSession(it)) } } } diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/api/WalletConnectComponent.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/api/WalletConnectComponent.kt new file mode 100644 index 0000000000..4e1f4ab3fb --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/api/WalletConnectComponent.kt @@ -0,0 +1,8 @@ +package com.tangem.tap.features.details.ui.walletconnect.api + +import com.tangem.core.decompose.factory.ComponentFactory +import com.tangem.core.ui.decompose.ComposableContentComponent + +interface WalletConnectComponent : ComposableContentComponent { + interface Factory : ComponentFactory +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/di/WalletConnectFeatureModule.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/di/WalletConnectFeatureModule.kt new file mode 100644 index 0000000000..20a85d18be --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/di/WalletConnectFeatureModule.kt @@ -0,0 +1,25 @@ +package com.tangem.tap.features.details.ui.walletconnect.di + +import com.tangem.core.decompose.model.Model +import com.tangem.tap.features.details.ui.walletconnect.DefaultWalletConnectComponent +import com.tangem.tap.features.details.ui.walletconnect.WalletConnectModel +import com.tangem.tap.features.details.ui.walletconnect.api.WalletConnectComponent +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import dagger.multibindings.ClassKey +import dagger.multibindings.IntoMap + +@Module +@InstallIn(SingletonComponent::class) +internal interface WalletConnectFeatureModule { + + @Binds + fun bindFactory(impl: DefaultWalletConnectComponent.Factory): WalletConnectComponent.Factory + + @Binds + @IntoMap + @ClassKey(WalletConnectModel::class) + fun bindModel(model: WalletConnectModel): Model +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt index 09e825ea06..970abaae15 100644 --- a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt +++ b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt @@ -26,7 +26,7 @@ import com.tangem.tap.features.details.ui.cardsettings.CardSettingsFragment import com.tangem.tap.features.details.ui.cardsettings.coderecovery.AccessCodeRecoveryFragment import com.tangem.tap.features.details.ui.resetcard.ResetCardFragment import com.tangem.tap.features.details.ui.securitymode.SecurityModeFragment -import com.tangem.tap.features.details.ui.walletconnect.WalletConnectFragment +import com.tangem.tap.features.details.ui.walletconnect.api.WalletConnectComponent import com.tangem.tap.features.home.api.HomeComponent import com.tangem.tap.features.onboarding.products.note.OnboardingNoteFragment import com.tangem.tap.features.onboarding.products.otherCards.OnboardingOtherCardsFragment @@ -63,6 +63,7 @@ internal class ChildFactory @Inject constructor( private val swapComponentFactory: SwapComponent.Factory, private val homeComponentFactory: HomeComponent.Factory, private val tokenDetailsComponentFactory: TokenDetailsComponent.Factory, + private val walletConnectComponentFactory: WalletConnectComponent.Factory, private val walletRouter: WalletRouter, private val qrScanningRouter: QrScanningRouter, private val testerRouter: TesterRouter, @@ -267,6 +268,13 @@ internal class ChildFactory @Inject constructor( componentFactory = homeComponentFactory, ) } + is AppRoute.WalletConnectSessions -> { + createComponentChild( + contextProvider = contextProvider(route, contextFactory), + params = Unit, + componentFactory = walletConnectComponentFactory, + ) + } is AppRoute.AccessCodeRecovery, is AppRoute.AppCurrencySelector, is AppRoute.SaveWallet, @@ -281,7 +289,6 @@ internal class ChildFactory @Inject constructor( is AppRoute.ReferralProgram, is AppRoute.ResetToFactory, is AppRoute.Wallet, - is AppRoute.WalletConnectSessions, is AppRoute.PushNotification, -> error("Unsupported route: $route") } @@ -400,7 +407,11 @@ internal class ChildFactory @Inject constructor( route.asFragmentChild(Provider { walletRouter.getEntryFragment() }) } is AppRoute.WalletConnectSessions -> { - route.asFragmentChild(Provider { WalletConnectFragment() }) + route.asComponentChild( + contextProvider = contextProvider(route, contextFactory), + params = Unit, + componentFactory = walletConnectComponentFactory, + ) } is AppRoute.CurrencyDetails -> { route.asComponentChild( From cf38933188e49ee43f996aeed99bec1239249375 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 18 Feb 2025 20:13:14 +0300 Subject: [PATCH 08/33] Updated on 2026-08-14 --- .../ui/walletconnect/DefaultWalletConnectComponent.kt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/DefaultWalletConnectComponent.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/DefaultWalletConnectComponent.kt index 5fadd6a1e8..02357ff195 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/DefaultWalletConnectComponent.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/DefaultWalletConnectComponent.kt @@ -27,13 +27,13 @@ internal class DefaultWalletConnectComponent @AssistedInject constructor( private val model: WalletConnectModel = getOrCreateModel() - private var screenState: MutableState? = null + private var screenState: MutableState = + mutableStateOf(model.updateState(store.state.walletConnectState)) init { lifecycle.subscribe( onCreate = { Analytics.send(WalletConnect.ScreenOpened()) - screenState = mutableStateOf(model.updateState(store.state.walletConnectState)) }, onStart = { store.subscribe(this) { state -> @@ -54,10 +54,9 @@ internal class DefaultWalletConnectComponent @AssistedInject constructor( @Composable override fun Content(modifier: Modifier) { - val state = screenState?.value ?: return WalletConnectScreen( modifier = modifier, - state = state, + state = screenState.value, onBackClick = { store.dispatchNavigationAction(AppRouter::pop) }, From 886dc6ee322ae893aa4e4ee067d0c721026f0d2a Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 19 Feb 2025 19:51:21 +0700 Subject: [PATCH 09/33] Updated on 2026-08-14 --- app/src/main/assets/tangem-app-config | 2 +- gradle/tangem_dependencies.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/assets/tangem-app-config b/app/src/main/assets/tangem-app-config index 89dac3cd1e..a3549d3e15 160000 --- a/app/src/main/assets/tangem-app-config +++ b/app/src/main/assets/tangem-app-config @@ -1 +1 @@ -Subproject commit 89dac3cd1e171d5801596ad151aa3af3fbc6c140 +Subproject commit a3549d3e156d3e1929649605798bf0239b4a29a0 diff --git a/gradle/tangem_dependencies.toml b/gradle/tangem_dependencies.toml index f9edc59dd5..967701e091 100644 --- a/gradle/tangem_dependencies.toml +++ b/gradle/tangem_dependencies.toml @@ -1,5 +1,5 @@ [versions] -tangemBlockchainSdk = "develop-952" +tangemBlockchainSdk = "develop-957" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "develop-434" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ From 4697ca6584e7b7090ff7be0c2a447cfa3ef9b687 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 20 Feb 2025 13:32:25 +0300 Subject: [PATCH 10/33] Updated on 2026-08-14 --- .../main/java/com/tangem/tap/MainActivity.kt | 4 - .../tangem/tap/routing/utils/ChildFactory.kt | 24 ++- .../com/tangem/common/routing/AppRoute.kt | 38 +---- .../com/tangem/core/decompose/model/Model.kt | 2 + features/qr-scanning/api/build.gradle.kts | 6 + .../feature/qrscanning/QrScanningComponent.kt | 15 ++ .../feature/qrscanning/QrScanningRouter.kt | 8 - features/qr-scanning/impl/build.gradle.kts | 1 + .../qrscanning/DefaultQrScanningComponent.kt | 142 ++++++++++++++++ .../feature/qrscanning/QrScanningFragment.kt | 158 ------------------ .../qrscanning/di/QrScanningFeatureModule.kt | 25 +++ .../qrscanning/di/QrScanningRouterModule.kt | 21 --- .../model/QrScanningClickIntents.kt | 16 ++ .../qrscanning/model/QrScanningModel.kt | 91 ++++++++++ .../navigation/DefaultQrScanningRouter.kt | 16 -- .../navigation/QrScanningInnerRouter.kt | 8 - .../InitializeQrScanningStateTransformer.kt | 2 +- .../ShowCameraDeniedBottomSheetTransformer.kt | 2 +- .../viewmodel/BaseQrScanningClickIntents.kt | 23 --- .../viewmodel/QrScanningClickIntents.kt | 67 -------- .../viewmodel/QrScanningViewModel.kt | 66 -------- 21 files changed, 323 insertions(+), 412 deletions(-) create mode 100644 features/qr-scanning/api/src/main/java/com/tangem/feature/qrscanning/QrScanningComponent.kt delete mode 100644 features/qr-scanning/api/src/main/java/com/tangem/feature/qrscanning/QrScanningRouter.kt create mode 100644 features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/DefaultQrScanningComponent.kt delete mode 100644 features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/QrScanningFragment.kt create mode 100644 features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/di/QrScanningFeatureModule.kt delete mode 100644 features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/di/QrScanningRouterModule.kt create mode 100644 features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/model/QrScanningClickIntents.kt create mode 100644 features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/model/QrScanningModel.kt delete mode 100644 features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/navigation/DefaultQrScanningRouter.kt delete mode 100644 features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/navigation/QrScanningInnerRouter.kt delete mode 100644 features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/viewmodel/BaseQrScanningClickIntents.kt delete mode 100644 features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/viewmodel/QrScanningClickIntents.kt delete mode 100644 features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/viewmodel/QrScanningViewModel.kt diff --git a/app/src/main/java/com/tangem/tap/MainActivity.kt b/app/src/main/java/com/tangem/tap/MainActivity.kt index 72b9f67d82..9b8c16a128 100644 --- a/app/src/main/java/com/tangem/tap/MainActivity.kt +++ b/app/src/main/java/com/tangem/tap/MainActivity.kt @@ -59,7 +59,6 @@ import com.tangem.domain.staking.SendUnsubmittedHashesUseCase import com.tangem.domain.tokens.GetPolkadotCheckHasImmortalUseCase import com.tangem.domain.tokens.GetPolkadotCheckHasResetUseCase import com.tangem.domain.wallets.legacy.UserWalletsListManager -import com.tangem.feature.qrscanning.QrScanningRouter import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent import com.tangem.features.onboarding.v2.OnboardingV2FeatureToggles import com.tangem.features.pushnotifications.api.navigation.PushNotificationsRouter @@ -142,9 +141,6 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac @Inject lateinit var walletConnectInteractor: WalletConnectInteractor - @Inject - lateinit var qrScanningRouter: QrScanningRouter - @Inject lateinit var deepLinksRegistry: DeepLinksRegistry diff --git a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt index 970abaae15..2342a80e63 100644 --- a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt +++ b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt @@ -2,7 +2,7 @@ package com.tangem.tap.routing.utils import com.tangem.common.routing.AppRoute import com.tangem.core.decompose.context.AppComponentContext -import com.tangem.feature.qrscanning.QrScanningRouter +import com.tangem.feature.qrscanning.QrScanningComponent import com.tangem.feature.referral.ReferralFragment import com.tangem.feature.stories.api.StoriesComponent import com.tangem.feature.walletsettings.component.WalletSettingsComponent @@ -64,8 +64,8 @@ internal class ChildFactory @Inject constructor( private val homeComponentFactory: HomeComponent.Factory, private val tokenDetailsComponentFactory: TokenDetailsComponent.Factory, private val walletConnectComponentFactory: WalletConnectComponent.Factory, + private val qrScanningComponentFactory: QrScanningComponent.Factory, private val walletRouter: WalletRouter, - private val qrScanningRouter: QrScanningRouter, private val testerRouter: TesterRouter, private val pushNotificationRouter: PushNotificationsRouter, private val routingFeatureToggles: RoutingFeatureToggles, @@ -275,6 +275,16 @@ internal class ChildFactory @Inject constructor( componentFactory = walletConnectComponentFactory, ) } + is AppRoute.QrScanning -> { + createComponentChild( + contextProvider = contextProvider(route, contextFactory), + params = QrScanningComponent.Params( + source = route.source, + networkName = route.networkName, + ), + componentFactory = qrScanningComponentFactory, + ) + } is AppRoute.AccessCodeRecovery, is AppRoute.AppCurrencySelector, is AppRoute.SaveWallet, @@ -285,7 +295,6 @@ internal class ChildFactory @Inject constructor( is AppRoute.OnboardingOther, is AppRoute.OnboardingTwins, is AppRoute.OnboardingWallet, - is AppRoute.QrScanning, is AppRoute.ReferralProgram, is AppRoute.ResetToFactory, is AppRoute.Wallet, @@ -383,7 +392,14 @@ internal class ChildFactory @Inject constructor( route.asFragmentChild(Provider { OnboardingWalletFragment() }) } is AppRoute.QrScanning -> { - route.asFragmentChild(Provider { qrScanningRouter.getEntryFragment() }) + route.asComponentChild( + contextProvider = contextProvider(route, contextFactory), + params = QrScanningComponent.Params( + source = route.source, + networkName = route.networkName, + ), + componentFactory = qrScanningComponentFactory, + ) } is AppRoute.ReferralProgram -> { route.asFragmentChild(Provider { ReferralFragment() }) diff --git a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt index f2c6c70148..62df97b518 100644 --- a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt +++ b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt @@ -93,20 +93,7 @@ sealed class AppRoute(val path: String) : Route { "&$amount" + "&$tag" + "&$destinationAddress", - ), - RouteBundleParams { - - override fun getBundle(): Bundle = bundle(serializer()) - - companion object { - const val USER_WALLET_ID_KEY = "userWalletId" - const val CRYPTO_CURRENCY_KEY = "currency" - const val TRANSACTION_ID_KEY = "transactionId" - const val AMOUNT_KEY = "amount" - const val TAG_KEY = "tag" - const val DESTINATION_ADDRESS_KEY = "destinationAddress" - } - } + ) @Serializable data class Details( @@ -196,15 +183,7 @@ sealed class AppRoute(val path: String) : Route { data class QrScanning( val source: SourceType, val networkName: String? = null, - ) : AppRoute(path = "/$source/qr_scanning${if (networkName != null) "/$networkName" else ""}"), RouteBundleParams { - - override fun getBundle(): Bundle = bundle(serializer()) - - companion object { - const val SOURCE_KEY = "source" - const val NETWORK_KEY = "networkName" - } - } + ) : AppRoute(path = "/$source/qr_scanning${if (networkName != null) "/$networkName" else ""}") @Serializable data class ReferralProgram( @@ -230,18 +209,7 @@ sealed class AppRoute(val path: String) : Route { "/${currencyTo?.id?.value}" + "/${userWalletId.stringValue}" + "/$isInitialReverseOrder", - ), - RouteBundleParams { - - override fun getBundle(): Bundle = bundle(serializer()) - - companion object { - const val CURRENCY_FROM_KEY = "currencyFrom" - const val CURRENCY_TO_KEY = "currencyTo" - const val USER_WALLET_ID_KEY = "userWalletId" - const val IS_INITIAL_REVERSE_ORDER = "isInitialReverseOrder" - } - } + ) @Serializable data object TesterMenu : AppRoute(path = "/tester_menu") diff --git a/core/decompose/src/main/kotlin/com/tangem/core/decompose/model/Model.kt b/core/decompose/src/main/kotlin/com/tangem/core/decompose/model/Model.kt index b1337c72f9..79ce712b57 100644 --- a/core/decompose/src/main/kotlin/com/tangem/core/decompose/model/Model.kt +++ b/core/decompose/src/main/kotlin/com/tangem/core/decompose/model/Model.kt @@ -6,6 +6,7 @@ import com.tangem.core.decompose.ui.UiMessageSender import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.* import kotlinx.coroutines.flow.* +import javax.annotation.OverridingMethodsMustInvokeSuper /** * Abstract class for a component's model. @@ -29,6 +30,7 @@ abstract class Model : InstanceKeeper.Instance { CoroutineScope(context = dispatchers.mainImmediate + SupervisorJob()) } + @OverridingMethodsMustInvokeSuper override fun onDestroy() { runCatching { modelScope.cancel() } } diff --git a/features/qr-scanning/api/build.gradle.kts b/features/qr-scanning/api/build.gradle.kts index d88f0c6f03..5508ff8910 100644 --- a/features/qr-scanning/api/build.gradle.kts +++ b/features/qr-scanning/api/build.gradle.kts @@ -9,6 +9,12 @@ android { } dependencies { + /** Domain models */ + implementation(projects.domain.qrScanning.models) + + /** Core */ + implementation(projects.core.decompose) + implementation(projects.core.ui) /** AndroidX */ implementation(deps.androidx.fragment.ktx) diff --git a/features/qr-scanning/api/src/main/java/com/tangem/feature/qrscanning/QrScanningComponent.kt b/features/qr-scanning/api/src/main/java/com/tangem/feature/qrscanning/QrScanningComponent.kt new file mode 100644 index 0000000000..4789912572 --- /dev/null +++ b/features/qr-scanning/api/src/main/java/com/tangem/feature/qrscanning/QrScanningComponent.kt @@ -0,0 +1,15 @@ +package com.tangem.feature.qrscanning + +import com.tangem.core.decompose.factory.ComponentFactory +import com.tangem.core.ui.decompose.ComposableContentComponent +import com.tangem.domain.qrscanning.models.SourceType + +interface QrScanningComponent : ComposableContentComponent { + + data class Params( + val source: SourceType, + val networkName: String? = null, + ) + + interface Factory : ComponentFactory +} \ No newline at end of file diff --git a/features/qr-scanning/api/src/main/java/com/tangem/feature/qrscanning/QrScanningRouter.kt b/features/qr-scanning/api/src/main/java/com/tangem/feature/qrscanning/QrScanningRouter.kt deleted file mode 100644 index 049e039209..0000000000 --- a/features/qr-scanning/api/src/main/java/com/tangem/feature/qrscanning/QrScanningRouter.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.tangem.feature.qrscanning - -import androidx.fragment.app.Fragment - -interface QrScanningRouter { - - fun getEntryFragment(): Fragment -} \ No newline at end of file diff --git a/features/qr-scanning/impl/build.gradle.kts b/features/qr-scanning/impl/build.gradle.kts index f8bb506a61..5e1a8a4c8f 100644 --- a/features/qr-scanning/impl/build.gradle.kts +++ b/features/qr-scanning/impl/build.gradle.kts @@ -14,6 +14,7 @@ dependencies { /** Core */ implementation(projects.core.ui) + implementation(projects.core.decompose) implementation(projects.core.utils) implementation(projects.core.navigation) implementation(projects.common.routing) diff --git a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/DefaultQrScanningComponent.kt b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/DefaultQrScanningComponent.kt new file mode 100644 index 0000000000..2e00a6910d --- /dev/null +++ b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/DefaultQrScanningComponent.kt @@ -0,0 +1,142 @@ +package com.tangem.feature.qrscanning + +import android.Manifest +import android.content.pm.PackageManager +import android.net.Uri +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.contract.ActivityResultContracts +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.core.content.ContextCompat +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.compose.LifecycleEventEffect +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.arkivanov.essenty.lifecycle.doOnDestroy +import com.google.mlkit.vision.common.InputImage +import com.tangem.core.decompose.context.AppComponentContext +import com.tangem.core.decompose.model.getOrCreateModel +import com.tangem.core.ui.components.SystemBarsIconsDisposable +import com.tangem.feature.qrscanning.inner.MLKitBarcodeAnalyzer +import com.tangem.feature.qrscanning.model.QrScanningModel +import com.tangem.feature.qrscanning.presentation.QrScanningContent +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import kotlinx.coroutines.delay +import timber.log.Timber +import java.io.IOException +import java.util.concurrent.ExecutorService +import java.util.concurrent.Executors + +class DefaultQrScanningComponent @AssistedInject constructor( + @Assisted appComponentContext: AppComponentContext, + @Assisted params: QrScanningComponent.Params, +) : QrScanningComponent, AppComponentContext by appComponentContext { + + private val model: QrScanningModel = getOrCreateModel(params) + + private val cameraExecutor: ExecutorService = Executors.newSingleThreadExecutor() + // Camera requires its own analyzer instance due to flow of frames needed to be analyzed. + // Each new frame can cancel previous analysis e.i. image from the gallery can be skipped. + private val cameraAnalyzer: MLKitBarcodeAnalyzer by lazy(LazyThreadSafetyMode.NONE) { + MLKitBarcodeAnalyzer(model::onQrScanned) + } + private val analyzer: MLKitBarcodeAnalyzer by lazy(LazyThreadSafetyMode.NONE) { + MLKitBarcodeAnalyzer(model::onQrScanned) + } + + init { + lifecycle.doOnDestroy { cameraExecutor.shutdown() } + } + + @Composable + override fun Content(modifier: Modifier) { + val context = LocalContext.current + + val cameraPermissionLauncher = + rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted -> + if (isGranted.not()) { + model.onCameraDeniedState() + } + } + + val galleryLauncher = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) { + val selectedImage = it ?: Uri.EMPTY + if (selectedImage != Uri.EMPTY) { + val mimeType = context.contentResolver.getType(selectedImage) + if (mimeType.isImageMimeType()) { + try { + val image = InputImage.fromFilePath(context, selectedImage) + analyzer.analyze(image) + } catch (e: IOException) { + Timber.e(e, "Unable to get image $selectedImage from gallery") + } + } + } + } + + LaunchedEffect(Unit) { + model.launchGallery.collect { + galleryLauncher.launch(GALLERY_IMAGE_FILTER) + delay(timeMillis = 2000) + } + } + + LifecycleEventEffect( + event = Lifecycle.Event.ON_CREATE, + ) { + if ( + ContextCompat.checkSelfPermission( + context, + Manifest.permission.CAMERA, + ) == PackageManager.PERMISSION_DENIED + ) { + cameraPermissionLauncher.launch(Manifest.permission.CAMERA) + } + } + + LifecycleEventEffect( + event = Lifecycle.Event.ON_RESUME, + ) { + if (ContextCompat.checkSelfPermission( + context, + Manifest.permission.CAMERA, + ) == PackageManager.PERMISSION_GRANTED + ) { + model.onDismissBottomSheetState() + } + } + + ScreenContent(modifier) + } + + @Suppress("UnusedPrivateMember") + @Composable + private fun ScreenContent(modifier: Modifier = Modifier) { + SystemBarsIconsDisposable(darkIcons = false) + + QrScanningContent( + executor = { cameraExecutor }, + analyzer = { cameraAnalyzer }, + uiState = model.uiState.collectAsStateWithLifecycle().value, + ) + } + + private fun String?.isImageMimeType() = this?.startsWith(prefix = "$IMAGE_MIME_TYPE/") == true + + @AssistedFactory + interface Factory : QrScanningComponent.Factory { + override fun create( + context: AppComponentContext, + params: QrScanningComponent.Params, + ): DefaultQrScanningComponent + } + + companion object { + + private const val IMAGE_MIME_TYPE = "image" + private const val GALLERY_IMAGE_FILTER = "$IMAGE_MIME_TYPE/*" + } +} \ No newline at end of file diff --git a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/QrScanningFragment.kt b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/QrScanningFragment.kt deleted file mode 100644 index 787c7bdfe9..0000000000 --- a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/QrScanningFragment.kt +++ /dev/null @@ -1,158 +0,0 @@ -package com.tangem.feature.qrscanning - -import android.Manifest -import android.content.pm.PackageManager -import android.net.Uri -import android.os.Bundle -import android.view.View -import androidx.activity.result.contract.ActivityResultContracts -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.core.content.ContextCompat -import androidx.fragment.app.viewModels -import androidx.lifecycle.Lifecycle -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import androidx.lifecycle.lifecycleScope -import androidx.lifecycle.repeatOnLifecycle -import com.google.mlkit.vision.common.InputImage -import com.tangem.core.ui.UiDependencies -import com.tangem.core.ui.components.SystemBarsIconsDisposable -import com.tangem.core.ui.screen.ComposeFragment -import com.tangem.feature.qrscanning.inner.MLKitBarcodeAnalyzer -import com.tangem.feature.qrscanning.navigation.QrScanningInnerRouter -import com.tangem.feature.qrscanning.presentation.QrScanningContent -import com.tangem.feature.qrscanning.viewmodel.QrScanningViewModel -import dagger.hilt.android.AndroidEntryPoint -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import timber.log.Timber -import java.io.IOException -import java.util.concurrent.ExecutorService -import java.util.concurrent.Executors -import javax.inject.Inject -import kotlin.properties.Delegates - -@AndroidEntryPoint -internal class QrScanningFragment : ComposeFragment() { - - @Inject - override lateinit var uiDependencies: UiDependencies - - @Inject - lateinit var router: QrScanningRouter - - private val innerRouter: QrScanningInnerRouter - get() = requireNotNull(router as? QrScanningInnerRouter) { - "innerRouter should be instance of QrScanningInnerRouter" - } - - private val viewModel by viewModels() - - private var cameraExecutor: ExecutorService by Delegates.notNull() - // Camera requires its own analyzer instance due to flow of frames needed to be analyzed. - // Each new frame can cancel previous analysis e.i. image from the gallery can be skipped. - private val cameraAnalyzer: MLKitBarcodeAnalyzer by lazy(LazyThreadSafetyMode.NONE) { - MLKitBarcodeAnalyzer(viewModel::onQrScanned) - } - private val analyzer: MLKitBarcodeAnalyzer by lazy(LazyThreadSafetyMode.NONE) { - MLKitBarcodeAnalyzer(viewModel::onQrScanned) - } - - private val cameraPermissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission()) { - if (!it) viewModel.onCameraDeniedState() - } - private val galleryLauncher = registerForActivityResult(ActivityResultContracts.GetContent()) { - val selectedImage = it ?: Uri.EMPTY - if (selectedImage != Uri.EMPTY) { - val mimeType = requireContext().contentResolver.getType(selectedImage) - if (mimeType.isImageMimeType()) { - try { - val image = InputImage.fromFilePath(requireContext(), selectedImage) - analyzer.analyze(image) - } catch (e: IOException) { - Timber.e(e, "Unable to get image $selectedImage from gallery") - } - } - } - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - viewModel.setRouter(innerRouter) - cameraExecutor = Executors.newSingleThreadExecutor() - requestCameraPermission() - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - viewLifecycleOwner.lifecycleScope.launch { - repeatOnLifecycle(Lifecycle.State.STARTED) { - viewModel.launchGalleryEvent - .collect { - galleryLauncher.launch(GALLERY_IMAGE_FILTER) - delay(timeMillis = 2000) - } - } - } - } - - override fun onResume() { - super.onResume() - checkPermissionGranted() - } - - override fun onDestroy() { - super.onDestroy() - cameraPermissionLauncher.unregister() - cameraExecutor.shutdown() - } - - @Composable - override fun ScreenContent(modifier: Modifier) { - SystemBarsIconsDisposable(darkIcons = false) - - QrScanningContent( - executor = { cameraExecutor }, - analyzer = { cameraAnalyzer }, - uiState = viewModel.uiState.collectAsStateWithLifecycle().value, - ) - } - - /** - * Method for requesting permission if there isn't one. - */ - private fun requestCameraPermission() { - if ( - ContextCompat.checkSelfPermission( - requireContext(), - Manifest.permission.CAMERA, - ) == PackageManager.PERMISSION_DENIED - ) { - cameraPermissionLauncher.launch(Manifest.permission.CAMERA) - } - } - - /** - * Method for checking if permission was granted after user opened Settings screen. - * If permission was granted dismiss bottom sheet. - */ - private fun checkPermissionGranted() { - if (ContextCompat.checkSelfPermission( - requireContext(), - Manifest.permission.CAMERA, - ) == PackageManager.PERMISSION_GRANTED - ) { - viewModel.onDismissBottomSheetState() - } - } - - private fun String?.isImageMimeType() = this?.startsWith(prefix = "$IMAGE_MIME_TYPE/") == true - - companion object { - - private const val IMAGE_MIME_TYPE = "image" - private const val GALLERY_IMAGE_FILTER = "$IMAGE_MIME_TYPE/*" - - fun create() = QrScanningFragment() - } -} \ No newline at end of file diff --git a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/di/QrScanningFeatureModule.kt b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/di/QrScanningFeatureModule.kt new file mode 100644 index 0000000000..b623deb575 --- /dev/null +++ b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/di/QrScanningFeatureModule.kt @@ -0,0 +1,25 @@ +package com.tangem.feature.qrscanning.di + +import com.tangem.core.decompose.model.Model +import com.tangem.feature.qrscanning.DefaultQrScanningComponent +import com.tangem.feature.qrscanning.QrScanningComponent +import com.tangem.feature.qrscanning.model.QrScanningModel +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import dagger.multibindings.ClassKey +import dagger.multibindings.IntoMap + +@Module +@InstallIn(SingletonComponent::class) +internal interface QrScanningFeatureModule { + + @Binds + fun bindComponentFactory(impl: DefaultQrScanningComponent.Factory): QrScanningComponent.Factory + + @Binds + @IntoMap + @ClassKey(QrScanningModel::class) + fun bindModel(model: QrScanningModel): Model +} \ No newline at end of file diff --git a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/di/QrScanningRouterModule.kt b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/di/QrScanningRouterModule.kt deleted file mode 100644 index b22a6c713f..0000000000 --- a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/di/QrScanningRouterModule.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.tangem.feature.qrscanning.di - -import com.tangem.common.routing.AppRouter -import com.tangem.feature.qrscanning.QrScanningRouter -import com.tangem.feature.qrscanning.navigation.DefaultQrScanningRouter -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.android.components.ActivityComponent -import dagger.hilt.android.scopes.ActivityScoped - -@Module -@InstallIn(ActivityComponent::class) -internal object QrScanningRouterModule { - - @Provides - @ActivityScoped - fun provideQrScanRouter(appRouter: AppRouter): QrScanningRouter { - return DefaultQrScanningRouter(appRouter) - } -} \ No newline at end of file diff --git a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/model/QrScanningClickIntents.kt b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/model/QrScanningClickIntents.kt new file mode 100644 index 0000000000..b0702b0d62 --- /dev/null +++ b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/model/QrScanningClickIntents.kt @@ -0,0 +1,16 @@ +package com.tangem.feature.qrscanning.model + +import kotlinx.coroutines.flow.SharedFlow + +internal interface QrScanningClickIntents { + + val launchGallery: SharedFlow + + fun onBackClick() + + fun onQrScanned(qrCode: String) + + fun onGalleryClicked() + + fun onSettingsClick() +} \ No newline at end of file diff --git a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/model/QrScanningModel.kt b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/model/QrScanningModel.kt new file mode 100644 index 0000000000..1ba92657ba --- /dev/null +++ b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/model/QrScanningModel.kt @@ -0,0 +1,91 @@ +package com.tangem.feature.qrscanning.model + +import androidx.compose.runtime.Stable +import com.tangem.common.routing.AppRouter +import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.model.Model +import com.tangem.core.decompose.model.ParamsContainer +import com.tangem.core.navigation.settings.SettingsManager +import com.tangem.data.card.sdk.CardSdkProvider +import com.tangem.domain.qrscanning.usecases.EmitQrScannedEventUseCase +import com.tangem.feature.qrscanning.QrScanningComponent +import com.tangem.feature.qrscanning.presentation.QrScanningState +import com.tangem.feature.qrscanning.presentation.QrScanningStateController +import com.tangem.feature.qrscanning.presentation.transformers.DismissBottomSheetTransformer +import com.tangem.feature.qrscanning.presentation.transformers.InitializeQrScanningStateTransformer +import com.tangem.feature.qrscanning.presentation.transformers.ShowCameraDeniedBottomSheetTransformer +import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import kotlinx.coroutines.channels.BufferOverflow +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.launch +import javax.inject.Inject + +@Suppress("LongParameterList") +@Stable +@ComponentScoped +internal class QrScanningModel @Inject constructor( + override val dispatchers: CoroutineDispatcherProvider, + paramsContainer: ParamsContainer, + private val stateHolder: QrScanningStateController, + private val cardSdkProvider: CardSdkProvider, + private val emitQrScannedEventUseCase: EmitQrScannedEventUseCase, + private val settingsManager: SettingsManager, + private val appRouter: AppRouter, +) : Model(), QrScanningClickIntents { + + private val params = paramsContainer.require() + val uiState: StateFlow = stateHolder.uiState + private var isScanned = false + + override val launchGallery = MutableSharedFlow( + extraBufferCapacity = 1, + onBufferOverflow = BufferOverflow.DROP_LATEST, + ) + + init { + // samsung for some reason disables reader mode, and then it works unstable + // to prevent this disable ir manually before scan QR + cardSdkProvider.sdk.forceDisableReaderMode() + stateHolder.update(InitializeQrScanningStateTransformer(this, params.source, params.networkName)) + } + + fun onCameraDeniedState() { + stateHolder.update(ShowCameraDeniedBottomSheetTransformer(this)) + } + + fun onDismissBottomSheetState() { + stateHolder.update(DismissBottomSheetTransformer()) + } + + override fun onBackClick() = appRouter.pop() + + override fun onQrScanned(qrCode: String) { + if (qrCode.isNotBlank()) { + modelScope.launch(dispatchers.mainImmediate) { + emitQrScannedEventUseCase.invoke(params.source, qrCode) + } + if (!isScanned) { + appRouter.pop() + isScanned = true + } + } + } + + override fun onGalleryClicked() { + launchGallery.tryEmit(Unit) + if (stateHolder.value.bottomSheetConfig != null) { + stateHolder.update(DismissBottomSheetTransformer()) + } + } + + override fun onSettingsClick() { + settingsManager.openAppSettings() + } + + override fun onDestroy() { + super.onDestroy() + // don't forget enable reader mode after scan complete + cardSdkProvider.sdk.forceEnableReaderMode() + } +} \ No newline at end of file diff --git a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/navigation/DefaultQrScanningRouter.kt b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/navigation/DefaultQrScanningRouter.kt deleted file mode 100644 index 3813274b68..0000000000 --- a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/navigation/DefaultQrScanningRouter.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.tangem.feature.qrscanning.navigation - -import androidx.fragment.app.Fragment -import com.tangem.common.routing.AppRouter - -import com.tangem.feature.qrscanning.QrScanningFragment - -class DefaultQrScanningRouter( - private val router: AppRouter, -) : QrScanningInnerRouter { - override fun getEntryFragment(): Fragment = QrScanningFragment.create() - - override fun popBackStack() { - router.pop() - } -} \ No newline at end of file diff --git a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/navigation/QrScanningInnerRouter.kt b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/navigation/QrScanningInnerRouter.kt deleted file mode 100644 index cdfb4cf247..0000000000 --- a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/navigation/QrScanningInnerRouter.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.tangem.feature.qrscanning.navigation - -import com.tangem.feature.qrscanning.QrScanningRouter - -interface QrScanningInnerRouter : QrScanningRouter { - - fun popBackStack() -} \ No newline at end of file diff --git a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/presentation/transformers/InitializeQrScanningStateTransformer.kt b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/presentation/transformers/InitializeQrScanningStateTransformer.kt index 2f38d3e545..7c6d08b333 100644 --- a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/presentation/transformers/InitializeQrScanningStateTransformer.kt +++ b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/presentation/transformers/InitializeQrScanningStateTransformer.kt @@ -5,7 +5,7 @@ import com.tangem.core.ui.extensions.wrappedList import com.tangem.domain.qrscanning.models.SourceType import com.tangem.feature.qrscanning.impl.R import com.tangem.feature.qrscanning.presentation.QrScanningState -import com.tangem.feature.qrscanning.viewmodel.QrScanningClickIntents +import com.tangem.feature.qrscanning.model.QrScanningClickIntents internal class InitializeQrScanningStateTransformer( private val clickIntents: QrScanningClickIntents, diff --git a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/presentation/transformers/ShowCameraDeniedBottomSheetTransformer.kt b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/presentation/transformers/ShowCameraDeniedBottomSheetTransformer.kt index 5dedeffebc..dfd650019f 100644 --- a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/presentation/transformers/ShowCameraDeniedBottomSheetTransformer.kt +++ b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/presentation/transformers/ShowCameraDeniedBottomSheetTransformer.kt @@ -3,7 +3,7 @@ package com.tangem.feature.qrscanning.presentation.transformers import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig import com.tangem.feature.qrscanning.presentation.CameraDeniedBottomSheetConfig import com.tangem.feature.qrscanning.presentation.QrScanningState -import com.tangem.feature.qrscanning.viewmodel.QrScanningClickIntents +import com.tangem.feature.qrscanning.model.QrScanningClickIntents internal class ShowCameraDeniedBottomSheetTransformer( private val clickIntents: QrScanningClickIntents, diff --git a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/viewmodel/BaseQrScanningClickIntents.kt b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/viewmodel/BaseQrScanningClickIntents.kt deleted file mode 100644 index 2ff968422a..0000000000 --- a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/viewmodel/BaseQrScanningClickIntents.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.tangem.feature.qrscanning.viewmodel - -import com.tangem.domain.qrscanning.models.SourceType -import com.tangem.feature.qrscanning.navigation.QrScanningInnerRouter -import kotlinx.coroutines.CoroutineScope -import kotlin.properties.Delegates - -internal open class BaseQrScanningClickIntents { - - protected val router: QrScanningInnerRouter get() = _router - protected val viewModelScope: CoroutineScope get() = _viewModelScope - protected val source: SourceType get() = _source - - private var _router: QrScanningInnerRouter by Delegates.notNull() - private var _viewModelScope: CoroutineScope by Delegates.notNull() - private var _source: SourceType by Delegates.notNull() - - open fun initialize(router: QrScanningInnerRouter, source: SourceType, coroutineScope: CoroutineScope) { - _router = router - _viewModelScope = coroutineScope - _source = source - } -} \ No newline at end of file diff --git a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/viewmodel/QrScanningClickIntents.kt b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/viewmodel/QrScanningClickIntents.kt deleted file mode 100644 index adfaf8bcff..0000000000 --- a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/viewmodel/QrScanningClickIntents.kt +++ /dev/null @@ -1,67 +0,0 @@ -package com.tangem.feature.qrscanning.viewmodel - -import com.tangem.core.navigation.settings.SettingsManager -import com.tangem.domain.qrscanning.usecases.EmitQrScannedEventUseCase -import com.tangem.feature.qrscanning.presentation.QrScanningStateController -import com.tangem.feature.qrscanning.presentation.transformers.DismissBottomSheetTransformer -import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import dagger.hilt.android.scopes.ViewModelScoped -import kotlinx.coroutines.channels.BufferOverflow -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.SharedFlow -import kotlinx.coroutines.launch -import javax.inject.Inject - -internal interface QrScanningClickIntents { - - val launchGallery: SharedFlow - - fun onBackClick() - - fun onQrScanned(qrCode: String) - - fun onGalleryClicked() - - fun onSettingsClick() -} - -@ViewModelScoped -internal class QrScanningClickIntentsImplementor @Inject constructor( - private val stateHolder: QrScanningStateController, - private val emitQrScannedEventUseCase: EmitQrScannedEventUseCase, - private val settingsManager: SettingsManager, - private val dispatcher: CoroutineDispatcherProvider, -) : BaseQrScanningClickIntents(), QrScanningClickIntents { - - private var isScanned = false - - override val launchGallery = MutableSharedFlow( - extraBufferCapacity = 1, - onBufferOverflow = BufferOverflow.DROP_LATEST, - ) - - override fun onBackClick() = router.popBackStack() - - override fun onQrScanned(qrCode: String) { - if (qrCode.isNotBlank()) { - viewModelScope.launch(dispatcher.mainImmediate) { - emitQrScannedEventUseCase.invoke(source, qrCode) - } - if (!isScanned) { - router.popBackStack() - isScanned = true - } - } - } - - override fun onGalleryClicked() { - launchGallery.tryEmit(Unit) - if (stateHolder.value.bottomSheetConfig != null) { - stateHolder.update(DismissBottomSheetTransformer()) - } - } - - override fun onSettingsClick() { - settingsManager.openAppSettings() - } -} \ No newline at end of file diff --git a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/viewmodel/QrScanningViewModel.kt b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/viewmodel/QrScanningViewModel.kt deleted file mode 100644 index ceff5566d6..0000000000 --- a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/viewmodel/QrScanningViewModel.kt +++ /dev/null @@ -1,66 +0,0 @@ -package com.tangem.feature.qrscanning.viewmodel - -import androidx.lifecycle.SavedStateHandle -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.tangem.common.routing.AppRoute -import com.tangem.data.card.sdk.CardSdkProvider -import com.tangem.domain.qrscanning.models.SourceType -import com.tangem.feature.qrscanning.navigation.QrScanningInnerRouter -import com.tangem.feature.qrscanning.presentation.QrScanningState -import com.tangem.feature.qrscanning.presentation.QrScanningStateController -import com.tangem.feature.qrscanning.presentation.transformers.DismissBottomSheetTransformer -import com.tangem.feature.qrscanning.presentation.transformers.InitializeQrScanningStateTransformer -import com.tangem.feature.qrscanning.presentation.transformers.ShowCameraDeniedBottomSheetTransformer -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.SharedFlow -import kotlinx.coroutines.flow.StateFlow -import javax.inject.Inject - -@HiltViewModel -internal class QrScanningViewModel @Inject constructor( - private val stateHolder: QrScanningStateController, - private val clickIntents: QrScanningClickIntentsImplementor, - private val cardSdkProvider: CardSdkProvider, - savedStateHandle: SavedStateHandle, -) : ViewModel() { - - private val source: SourceType = savedStateHandle.get(AppRoute.QrScanning.SOURCE_KEY) - ?.let { SourceType.entries[it] } - ?: error("Source is mandatory") - private val network: String? = savedStateHandle[AppRoute.QrScanning.NETWORK_KEY] - - val uiState: StateFlow = stateHolder.uiState - val launchGalleryEvent: SharedFlow = clickIntents.launchGallery - - init { - // samsung for some reason disables reader mode, and then it works unstable - // to prevent this disable ir manually before scan QR - cardSdkProvider.sdk.forceDisableReaderMode() - } - - fun setRouter(router: QrScanningInnerRouter) { - clickIntents.initialize( - router = router, - source = source, - coroutineScope = viewModelScope, - ) - stateHolder.update(InitializeQrScanningStateTransformer(clickIntents, source, network)) - } - - fun onQrScanned(qrCode: String) = clickIntents.onQrScanned(qrCode) - - fun onCameraDeniedState() { - stateHolder.update(ShowCameraDeniedBottomSheetTransformer(clickIntents)) - } - - fun onDismissBottomSheetState() { - stateHolder.update(DismissBottomSheetTransformer()) - } - - override fun onCleared() { - super.onCleared() - // don't forget enable reader mode after scan complete - cardSdkProvider.sdk.forceEnableReaderMode() - } -} \ No newline at end of file From 68e752b57041f288df58ea5863def63968a55c4f Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 20 Feb 2025 11:03:22 +0000 Subject: [PATCH 11/33] Updated on 2026-08-14 --- gradle/tangem_dependencies.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/tangem_dependencies.toml b/gradle/tangem_dependencies.toml index d49f7f2f1d..967701e091 100644 --- a/gradle/tangem_dependencies.toml +++ b/gradle/tangem_dependencies.toml @@ -1,7 +1,7 @@ [versions] -tangemBlockchainSdk = "release-app_5.21-955" +tangemBlockchainSdk = "develop-957" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds -tangemCardSdk = "release-app_5.21-435" +tangemCardSdk = "develop-434" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ tangemVico = "2.0.0-alpha.25-tangem-developments8" #tangemVico = "0.0.1" # Keep it! - used for local builds ^ From 111dea42be5f1abcca5f6b5356f5e9c9e02ad64b Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 20 Feb 2025 14:50:16 +0400 Subject: [PATCH 12/33] Updated on 2026-08-14 --- .../network/DefaultNetworksStatusesStore.kt | 37 +++++++++++++++---- .../local/network/NetworksStatusesStore.kt | 2 + .../local/quote/DefaultQuotesStore.kt | 29 ++++++++++----- .../datasource/local/quote/QuotesStore.kt | 2 + .../local/token/DefaultStakingBalanceStore.kt | 32 +++++++++++----- .../local/token/StakingBalanceStore.kt | 2 + .../data/staking/DefaultStakingRepository.kt | 4 ++ .../repository/DefaultNetworksRepository.kt | 13 +------ .../repository/DefaultQuotesRepository.kt | 4 ++ .../domain/tokens/model/NetworkStatus.kt | 15 +++++--- .../operations/CurrencyStatusOperations.kt | 1 - 11 files changed, 97 insertions(+), 44 deletions(-) diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/network/DefaultNetworksStatusesStore.kt b/core/datasource/src/main/java/com/tangem/datasource/local/network/DefaultNetworksStatusesStore.kt index f3e3d06f65..8a2e170bb9 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/network/DefaultNetworksStatusesStore.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/network/DefaultNetworksStatusesStore.kt @@ -72,14 +72,26 @@ internal class DefaultNetworksStatusesStore( override suspend fun storeAll(key: UserWalletId, values: Set) { coroutineScope { - val updatedValues = getSyncOrNull(key).orEmpty() - .addOrReplace(items = values) { prev, new -> prev.network == new.network } - - launch { runtimeDataStore.store(key = provideStringKey(key), value = updatedValues) } - launch { storeNetworkStatusInPersistence(userWalletId = key, statuses = updatedValues) } + launch { storeInRuntimeStore(key = key, statuses = values) } + launch { storeInPersistenceStore(userWalletId = key, statuses = values) } } } + override suspend fun refresh(key: UserWalletId, networks: Set) { + val currentStatuses = getSyncOrNull(key).orEmpty() + + storeInRuntimeStore( + key = key, + statuses = networks.mapNotNullTo(hashSetOf()) { network -> + val status = currentStatuses.firstOrNull { it.network.id == network.id } ?: return@mapNotNullTo null + + status.copy( + value = status.value.copySealed(source = StatusSource.CACHE), + ) + }, + ) + } + /** * Merge [cachedStatuses] with [runtimeStatuses] * The resulting set contains statuses from both sets. @@ -108,7 +120,6 @@ internal class DefaultNetworksStatusesStore( val updatedCachedStatus = when (val status = cached.value) { is NetworkStatus.NoAccount -> status.copy(source = StatusSource.ONLY_CACHE) is NetworkStatus.Verified -> status.copy(source = StatusSource.ONLY_CACHE) - is NetworkStatus.Refreshing, is NetworkStatus.Unreachable, is NetworkStatus.MissedDerivation, -> null @@ -121,13 +132,23 @@ internal class DefaultNetworksStatusesStore( } } - private suspend fun storeNetworkStatusInPersistence(userWalletId: UserWalletId, statuses: Set) { + private suspend fun storeInRuntimeStore(key: UserWalletId, statuses: Set) { + val updatedValues = getSyncOrNull(key).orEmpty() + .addOrReplace(items = statuses) { prev, new -> prev.network == new.network } + + runtimeDataStore.store(key = provideStringKey(key), value = updatedValues) + } + + private suspend fun storeInPersistenceStore(userWalletId: UserWalletId, statuses: Set) { // Converter will return null if the network status is not supported val newStatuses = NetworkStatusDataModelConverter.convertSet(input = statuses).filterNotNull().toSet() persistenceDataStore.updateData { storedStatuses -> storedStatuses.toMutableMap().apply { - this[userWalletId.stringValue] = newStatuses + val updatedValues = this[userWalletId.stringValue].orEmpty() + .addOrReplace(newStatuses) { prev, new -> prev.networkId == new.networkId } + + this[userWalletId.stringValue] = updatedValues } } } diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/network/NetworksStatusesStore.kt b/core/datasource/src/main/java/com/tangem/datasource/local/network/NetworksStatusesStore.kt index 81838f97aa..a1d92c60cc 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/network/NetworksStatusesStore.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/network/NetworksStatusesStore.kt @@ -16,4 +16,6 @@ interface NetworksStatusesStore { suspend fun store(key: UserWalletId, value: NetworkStatus) suspend fun storeAll(key: UserWalletId, values: Set) + + suspend fun refresh(key: UserWalletId, networks: Set) } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/quote/DefaultQuotesStore.kt b/core/datasource/src/main/java/com/tangem/datasource/local/quote/DefaultQuotesStore.kt index d7e5299c72..8cc69f2fda 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/quote/DefaultQuotesStore.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/quote/DefaultQuotesStore.kt @@ -52,17 +52,30 @@ internal class DefaultQuotesStore( override suspend fun store(response: QuotesResponse) { coroutineScope { - launch { storeInRuntimeStore(response = response) } + launch { + storeInRuntimeStore( + values = QuoteConverter(isCached = false).convertSet(input = response.quotes.entries), + ) + } launch { storeInPersistenceStore(response = response) } } } override suspend fun storeEmptyQuotes(currenciesIds: Set) { - runtimeStore.update(default = emptySet()) { saved -> - val new = currenciesIds.map { Quote.Empty(it) } + storeInRuntimeStore(values = currenciesIds.map(Quote::Empty).toSet()) + } - (saved + new).distinctBy { it.rawCurrencyId }.toSet() - } + override suspend fun refresh(currenciesIds: Set) { + val currentStatuses = getSync(currenciesIds) + + storeInRuntimeStore( + values = currentStatuses.mapTo(hashSetOf()) { quote -> + when (quote) { + is Quote.Empty -> quote + is Quote.Value -> quote.copy(source = StatusSource.CACHE) + } + }, + ) } private suspend fun getCachedQuotes(currenciesIds: Set): Set { @@ -95,11 +108,9 @@ internal class DefaultQuotesStore( ?: Quote.Empty(currencyId) } - private suspend fun storeInRuntimeStore(response: QuotesResponse) { - val new = QuoteConverter(isCached = false).convertSet(input = response.quotes.entries) - + private suspend fun storeInRuntimeStore(values: Set) { runtimeStore.update(default = emptySet()) { saved -> - (saved + new).distinctBy { it.rawCurrencyId }.toSet() + (saved + values).distinctBy { it.rawCurrencyId }.toSet() } } diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/quote/QuotesStore.kt b/core/datasource/src/main/java/com/tangem/datasource/local/quote/QuotesStore.kt index 4d632c3558..69b76b154b 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/quote/QuotesStore.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/quote/QuotesStore.kt @@ -19,4 +19,6 @@ interface QuotesStore { /** Store [Quote.Empty] for [currenciesIds] */ suspend fun storeEmptyQuotes(currenciesIds: Set) + + suspend fun refresh(currenciesIds: Set) } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/token/DefaultStakingBalanceStore.kt b/core/datasource/src/main/java/com/tangem/datasource/local/token/DefaultStakingBalanceStore.kt index 50de014b59..aaadb1d435 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/token/DefaultStakingBalanceStore.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/token/DefaultStakingBalanceStore.kt @@ -72,15 +72,26 @@ internal class DefaultStakingBalanceStore( override suspend fun store(userWalletId: UserWalletId, items: Set) { coroutineScope { launch { - storeInRuntimeStore( - userWalletId = userWalletId, - items = YieldBalanceConverter(isCached = false).convertSet(input = items), - ) + updateRuntimeStore(userWalletId = userWalletId) { + YieldBalanceConverter(isCached = false).convertSet(input = items) + } } launch { storeInPersistenceStore(userWalletId = userWalletId, items = items) } } } + override suspend fun refresh(userWalletId: UserWalletId) { + updateRuntimeStore(userWalletId = userWalletId) { saved -> + saved.mapTo(hashSetOf()) { + when (it) { + is YieldBalance.Data -> it.copy(source = StatusSource.CACHE) + is YieldBalance.Empty -> it.copy(source = StatusSource.CACHE) + is YieldBalance.Error -> it + } + } + } + } + override suspend fun store( userWalletId: UserWalletId, integrationId: String, @@ -107,13 +118,16 @@ internal class DefaultStakingBalanceStore( ?.addOrReplace(newBalance) { it.integrationId == integrationId && it.address == address } ?: setOf(newBalance) - storeInRuntimeStore(userWalletId = userWalletId, items = balances) + updateRuntimeStore(userWalletId = userWalletId) { balances } } - private suspend fun storeInRuntimeStore(userWalletId: UserWalletId, items: Set) { - runtimeStore.update(default = emptyMap()) { - it.toMutableMap().apply { - this[userWalletId] = items + private suspend fun updateRuntimeStore( + userWalletId: UserWalletId, + function: (Set) -> Set, + ) { + runtimeStore.update(default = emptyMap()) { saved -> + saved.toMutableMap().apply { + this[userWalletId] = function(this[userWalletId].orEmpty()) } } } diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/token/StakingBalanceStore.kt b/core/datasource/src/main/java/com/tangem/datasource/local/token/StakingBalanceStore.kt index 0638d1ac9f..c09987f7f4 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/token/StakingBalanceStore.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/token/StakingBalanceStore.kt @@ -26,4 +26,6 @@ interface StakingBalanceStore { /** Store [item] by [userWalletId], [integrationId] and [address] */ suspend fun store(userWalletId: UserWalletId, integrationId: String, address: String, item: YieldBalanceWrapperDTO) + + suspend fun refresh(userWalletId: UserWalletId) } \ No newline at end of file diff --git a/data/staking/src/main/java/com/tangem/data/staking/DefaultStakingRepository.kt b/data/staking/src/main/java/com/tangem/data/staking/DefaultStakingRepository.kt index 4e4c6e7833..620bad0ce9 100644 --- a/data/staking/src/main/java/com/tangem/data/staking/DefaultStakingRepository.kt +++ b/data/staking/src/main/java/com/tangem/data/staking/DefaultStakingRepository.kt @@ -402,6 +402,10 @@ internal class DefaultStakingRepository( cryptoCurrencies: List, refresh: Boolean, ) = withContext(dispatchers.io) { + if (refresh) { + stakingBalanceStore.refresh(userWalletId = userWalletId) + } + cacheRegistry.invokeOnExpire( key = getYieldBalancesKey(userWalletId), skipCache = refresh, diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultNetworksRepository.kt b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultNetworksRepository.kt index 0760786a7d..85fce53032 100644 --- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultNetworksRepository.kt +++ b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultNetworksRepository.kt @@ -50,6 +50,7 @@ internal class DefaultNetworksRepository( networks: Set, ): Flow> { return networksStatusesStore.get(userWalletId, networks) + .distinctUntilChanged() .flowOn(dispatchers.io) } @@ -120,17 +121,7 @@ internal class DefaultNetworksRepository( refresh: Boolean, ) = coroutineScope { if (refresh) { - val statusesToRefresh = networksStatusesStore.getSyncOrNull(userWalletId)?.mapNotNull { - if (it.network in networks) { - it.copy(value = NetworkStatus.Refreshing) - } else { - null - } - } - - if (statusesToRefresh != null) { - networksStatusesStore.storeAll(key = userWalletId, values = statusesToRefresh.toSet()) - } + networksStatusesStore.refresh(key = userWalletId, networks = networks) } val currencies = getCurrencies(userWalletId, networks) diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultQuotesRepository.kt b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultQuotesRepository.kt index 8c7ce6b8bf..0874594282 100644 --- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultQuotesRepository.kt +++ b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultQuotesRepository.kt @@ -100,6 +100,10 @@ internal class DefaultQuotesRepository( // it changes after filterExpiredCurrenciesIds // calls with different coroutines and lead to fetchQuotes mutex.withLock { + if (refresh) { + quotesStore.refresh(currenciesIds) + } + val expiredCurrenciesIds = filterExpiredCurrenciesIds( currenciesIds = currenciesIds, refresh = refresh || quotesFetchedForAppCurrency != appCurrencyId, diff --git a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/NetworkStatus.kt b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/NetworkStatus.kt index 1f9bd66e11..6bacb5067b 100644 --- a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/NetworkStatus.kt +++ b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/NetworkStatus.kt @@ -23,13 +23,16 @@ data class NetworkStatus( sealed class Value { abstract val source: StatusSource - } - /** - * Represents the state where the network is refreshing. - */ - data object Refreshing : Value() { - override val source: StatusSource = StatusSource.ACTUAL + fun copySealed(source: StatusSource): Value { + return when (this) { + is NoAccount -> copy(source = source) + is Verified -> copy(source = source) + is Unreachable, + is MissedDerivation, + -> this + } + } } /** diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CurrencyStatusOperations.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CurrencyStatusOperations.kt index 7e2dc0db71..d160103afe 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CurrencyStatusOperations.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CurrencyStatusOperations.kt @@ -30,7 +30,6 @@ internal class CurrencyStatusOperations( private fun createStatus(): CryptoCurrencyStatus.Value { return when (val status = networkStatus?.value) { null, - is NetworkStatus.Refreshing, -> CryptoCurrencyStatus.Loading is NetworkStatus.MissedDerivation -> createMissedDerivationStatus() is NetworkStatus.Unreachable -> createUnreachableStatus(status) From 1e5e55009c53314061495e37645c1f84bb6e63a6 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 19 Feb 2025 18:03:27 +0700 Subject: [PATCH 13/33] Updated on 2026-08-14 --- app/src/main/assets/tangem-app-config | 2 +- .../mercuryo/MercuryoBlockchainMapping.kt | 2 ++ .../moonpay/MoonpayBlockchainMapping.kt | 2 ++ .../configs/excluded_blockchains_config.json | 8 +++++++ .../core/ui/extensions/BlockchainIcons.kt | 9 +++++++ core/ui/src/main/res/drawable/ic_vanar_22.xml | 9 +++++++ .../ui/src/main/res/drawable/ic_zklink_22.xml | 14 +++++++++++ .../ui/src/main/res/drawable/img_vanar_22.xml | 19 +++++++++++++++ .../src/main/res/drawable/img_zklink_22.xml | 24 +++++++++++++++++++ .../data/common/currency/NetworkOperations.kt | 2 ++ .../common/configs/Wallet2CardConfig.kt | 4 ++++ .../common/configs/Wallet2CardConfigTest.kt | 4 ++++ .../feature/swap/domain/SwapInteractorImpl.kt | 2 ++ gradle/tangem_dependencies.toml | 2 +- .../tangem/blockchainsdk/utils/Blockchain.kt | 10 ++++++++ 15 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 core/ui/src/main/res/drawable/ic_vanar_22.xml create mode 100644 core/ui/src/main/res/drawable/ic_zklink_22.xml create mode 100644 core/ui/src/main/res/drawable/img_vanar_22.xml create mode 100644 core/ui/src/main/res/drawable/img_zklink_22.xml diff --git a/app/src/main/assets/tangem-app-config b/app/src/main/assets/tangem-app-config index a3549d3e15..af8b453fd2 160000 --- a/app/src/main/assets/tangem-app-config +++ b/app/src/main/assets/tangem-app-config @@ -1 +1 @@ -Subproject commit a3549d3e156d3e1929649605798bf0239b4a29a0 +Subproject commit af8b453fd25b29d949c05302ec282511dc2614b8 diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoBlockchainMapping.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoBlockchainMapping.kt index 8a647aeee9..3c20cb9f8e 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoBlockchainMapping.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoBlockchainMapping.kt @@ -153,6 +153,8 @@ internal val Blockchain.mercuryoNetwork: String? Blockchain.Bitrock, Blockchain.BitrockTestnet -> null Blockchain.Sonic, Blockchain.SonicTestnet -> null Blockchain.ApeChain, Blockchain.ApeChainTestnet -> null + Blockchain.Scroll, Blockchain.ScrollTestnet -> null + Blockchain.ZkLinkNova, Blockchain.ZkLinkNovaTestnet -> null Blockchain.KaspaTestnet -> null } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/moonpay/MoonpayBlockchainMapping.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/moonpay/MoonpayBlockchainMapping.kt index aa3442e13d..a0f0c7f157 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/moonpay/MoonpayBlockchainMapping.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/moonpay/MoonpayBlockchainMapping.kt @@ -154,5 +154,7 @@ internal val Blockchain.moonPaySupportedCurrency: MoonPaySupportedCurrency? Bitrock, BitrockTestnet -> null Sonic, SonicTestnet -> null ApeChain, ApeChainTestnet -> null + Scroll, ScrollTestnet -> null + ZkLinkNova, ZkLinkNovaTestnet -> null KaspaTestnet -> null } \ No newline at end of file diff --git a/core/config-toggles/src/main/assets/configs/excluded_blockchains_config.json b/core/config-toggles/src/main/assets/configs/excluded_blockchains_config.json index f3fc207299..11acf26497 100644 --- a/core/config-toggles/src/main/assets/configs/excluded_blockchains_config.json +++ b/core/config-toggles/src/main/assets/configs/excluded_blockchains_config.json @@ -26,5 +26,13 @@ { "name": "alephium", "version": "5.21.0" + }, + { + "name": "scroll", + "version": "undefined" + }, + { + "name": "zklink", + "version": "undefined" } ] \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/extensions/BlockchainIcons.kt b/core/ui/src/main/java/com/tangem/core/ui/extensions/BlockchainIcons.kt index f3a42975bc..44c9a4dd6d 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/extensions/BlockchainIcons.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/extensions/BlockchainIcons.kt @@ -90,6 +90,9 @@ fun getActiveIconRes(blockchainId: String): Int { "bitrock", "bitrock/test" -> R.drawable.img_bitrock_22 "sonic", "sonic/test" -> R.drawable.img_sonic_22 "apechain", "apechain/test" -> R.drawable.img_apecoin_22 + "scroll", "scroll/test" -> R.drawable.ic_alert_24 // FIXME: add icon during full integration + "zklink", "zklink/test" -> R.drawable.img_zklink_22 + "vanar-chain", "vanar-chain/test" -> R.drawable.img_vanar_22 else -> R.drawable.ic_alert_24 } } @@ -178,6 +181,9 @@ fun getActiveIconResByCoinId(coinId: String): Int { "bitrock", "bitrock/test" -> R.drawable.img_bitrock_22 "sonic", "sonic/test" -> R.drawable.img_sonic_22 "apechain", "apechain/test" -> R.drawable.img_apecoin_22 + "scroll", "scroll/test" -> R.drawable.ic_alert_24 // FIXME: add icon during full integration + "zklink", "zklink/test" -> R.drawable.img_zklink_22 + "vanar-chain", "vanar-chain/test" -> R.drawable.img_vanar_22 else -> R.drawable.ic_alert_24 } } @@ -269,6 +275,9 @@ fun getGreyedOutIconRes(blockchainId: String): Int { "bitrock", "bitrock/test" -> R.drawable.ic_bitrock_22 "sonic", "sonic/test" -> R.drawable.ic_sonic_22 "apechain", "apechain/test" -> R.drawable.ic_apecoin_22 + "scroll", "scroll/test" -> R.drawable.ic_alert_24 // FIXME: add icon during full integration + "zklink", "zklink/test" -> R.drawable.ic_zklink_22 + "vanar-chain", "vanar-chain/test" -> R.drawable.ic_vanar_22 else -> R.drawable.ic_alert_24 } } \ No newline at end of file diff --git a/core/ui/src/main/res/drawable/ic_vanar_22.xml b/core/ui/src/main/res/drawable/ic_vanar_22.xml new file mode 100644 index 0000000000..3ddb0cea23 --- /dev/null +++ b/core/ui/src/main/res/drawable/ic_vanar_22.xml @@ -0,0 +1,9 @@ + + + diff --git a/core/ui/src/main/res/drawable/ic_zklink_22.xml b/core/ui/src/main/res/drawable/ic_zklink_22.xml new file mode 100644 index 0000000000..70fb36416d --- /dev/null +++ b/core/ui/src/main/res/drawable/ic_zklink_22.xml @@ -0,0 +1,14 @@ + + + + diff --git a/core/ui/src/main/res/drawable/img_vanar_22.xml b/core/ui/src/main/res/drawable/img_vanar_22.xml new file mode 100644 index 0000000000..7fc4405bcb --- /dev/null +++ b/core/ui/src/main/res/drawable/img_vanar_22.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/core/ui/src/main/res/drawable/img_zklink_22.xml b/core/ui/src/main/res/drawable/img_zklink_22.xml new file mode 100644 index 0000000000..91405830fc --- /dev/null +++ b/core/ui/src/main/res/drawable/img_zklink_22.xml @@ -0,0 +1,24 @@ + + + + + + + + + diff --git a/data/common/src/main/kotlin/com/tangem/data/common/currency/NetworkOperations.kt b/data/common/src/main/kotlin/com/tangem/data/common/currency/NetworkOperations.kt index 31d90fac3f..a0fde030cc 100644 --- a/data/common/src/main/kotlin/com/tangem/data/common/currency/NetworkOperations.kt +++ b/data/common/src/main/kotlin/com/tangem/data/common/currency/NetworkOperations.kt @@ -299,6 +299,8 @@ private fun Blockchain.getSupportedTransactionExtras(): Network.TransactionExtra Blockchain.Bitrock, Blockchain.BitrockTestnet, Blockchain.Sonic, Blockchain.SonicTestnet, Blockchain.ApeChain, Blockchain.ApeChainTestnet, + Blockchain.Scroll, Blockchain.ScrollTestnet, + Blockchain.ZkLinkNova, Blockchain.ZkLinkNovaTestnet, -> Network.TransactionExtrasType.NONE // endregion } diff --git a/domain/legacy/src/main/java/com/tangem/domain/common/configs/Wallet2CardConfig.kt b/domain/legacy/src/main/java/com/tangem/domain/common/configs/Wallet2CardConfig.kt index 79355cd5c6..aa0a5e23e6 100644 --- a/domain/legacy/src/main/java/com/tangem/domain/common/configs/Wallet2CardConfig.kt +++ b/domain/legacy/src/main/java/com/tangem/domain/common/configs/Wallet2CardConfig.kt @@ -201,6 +201,10 @@ data object Wallet2CardConfig : CardConfig { Blockchain.KaspaTestnet -> EllipticCurve.Secp256k1 Blockchain.Alephium -> EllipticCurve.Secp256k1 Blockchain.AlephiumTestnet -> EllipticCurve.Secp256k1 + Blockchain.Scroll -> EllipticCurve.Secp256k1 + Blockchain.ScrollTestnet -> EllipticCurve.Secp256k1 + Blockchain.ZkLinkNova -> EllipticCurve.Secp256k1 + Blockchain.ZkLinkNovaTestnet -> EllipticCurve.Secp256k1 } } } \ No newline at end of file diff --git a/domain/legacy/src/test/java/com/tangem/domain/common/configs/Wallet2CardConfigTest.kt b/domain/legacy/src/test/java/com/tangem/domain/common/configs/Wallet2CardConfigTest.kt index 3faea63878..d80b9be554 100644 --- a/domain/legacy/src/test/java/com/tangem/domain/common/configs/Wallet2CardConfigTest.kt +++ b/domain/legacy/src/test/java/com/tangem/domain/common/configs/Wallet2CardConfigTest.kt @@ -158,6 +158,10 @@ class Wallet2CardConfigTest { Blockchain.KaspaTestnet to EllipticCurve.Secp256k1, Blockchain.Alephium to EllipticCurve.Secp256k1, Blockchain.AlephiumTestnet to EllipticCurve.Secp256k1, + Blockchain.Scroll to EllipticCurve.Secp256k1, + Blockchain.ScrollTestnet to EllipticCurve.Secp256k1, + Blockchain.ZkLinkNova to EllipticCurve.Secp256k1, + Blockchain.ZkLinkNovaTestnet to EllipticCurve.Secp256k1, ) @Test diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt index 7cc9ebc2f2..a36223d839 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt @@ -989,6 +989,8 @@ internal class SwapInteractorImpl @AssistedInject constructor( Bitrock, BitrockTestnet, Sonic, SonicTestnet, ApeChain, ApeChainTestnet, + Scroll, ScrollTestnet, + ZkLinkNova, ZkLinkNovaTestnet, -> Fee.Common(feeAmount) // endregion } diff --git a/gradle/tangem_dependencies.toml b/gradle/tangem_dependencies.toml index 967701e091..b58666bdd9 100644 --- a/gradle/tangem_dependencies.toml +++ b/gradle/tangem_dependencies.toml @@ -1,5 +1,5 @@ [versions] -tangemBlockchainSdk = "develop-957" +tangemBlockchainSdk = "develop-959" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "develop-434" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ diff --git a/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/utils/Blockchain.kt b/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/utils/Blockchain.kt index 866170f4c5..dc2f9b8a81 100644 --- a/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/utils/Blockchain.kt +++ b/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/utils/Blockchain.kt @@ -159,6 +159,10 @@ fun Blockchain.Companion.fromNetworkId(networkId: String): Blockchain? { "apechain" -> Blockchain.ApeChain "apechain/test" -> Blockchain.ApeChainTestnet "kaspa/test" -> Blockchain.KaspaTestnet + "scroll" -> Blockchain.Scroll + "scroll/test" -> Blockchain.ScrollTestnet + "zklink" -> Blockchain.ZkLinkNova + "zklink/test" -> Blockchain.ZkLinkNovaTestnet else -> null } } @@ -315,6 +319,10 @@ fun Blockchain.toNetworkId(): String { Blockchain.SonicTestnet -> "sonic/test" Blockchain.ApeChain -> "apechain" Blockchain.ApeChainTestnet -> "apechain/test" + Blockchain.Scroll -> "scroll" + Blockchain.ScrollTestnet -> "scroll/test" + Blockchain.ZkLinkNova -> "zklink" + Blockchain.ZkLinkNovaTestnet -> "zklink/test" } } @@ -415,6 +423,8 @@ fun Blockchain.toCoinId(): String { Blockchain.Bitrock, Blockchain.BitrockTestnet -> "bitrock" Blockchain.Sonic, Blockchain.SonicTestnet -> "sonic-3" Blockchain.ApeChain, Blockchain.ApeChainTestnet -> "apecoin" + Blockchain.Scroll, Blockchain.ScrollTestnet -> "scroll" + Blockchain.ZkLinkNova, Blockchain.ZkLinkNovaTestnet -> "zklink" } } From 08a78738cb2d6821064a56e0179a45ccf2335f7a Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 21 Feb 2025 12:07:39 +0300 Subject: [PATCH 14/33] Updated on 2026-08-14 --- .../impl/child/seedphrase/ui/MultiWalletSeedPhraseWords.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/ui/MultiWalletSeedPhraseWords.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/ui/MultiWalletSeedPhraseWords.kt index f5ac73fd97..1099d8bcc1 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/ui/MultiWalletSeedPhraseWords.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/ui/MultiWalletSeedPhraseWords.kt @@ -84,8 +84,8 @@ private fun SegmentSeedBlock(state: MultiWalletSeedPhraseUM.GenerateSeedPhrase, Text( text = pluralStringResourceSafe( id = R.plurals.onboarding_seed_generate_words_count, - count = state.option.length, - state.option.length, + count = it.length, + it.length, ), modifier = Modifier .padding(vertical = TangemTheme.dimens.spacing10) From 3477c8f5911b94b7114d03a2d29f8295a4ed7d35 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 21 Feb 2025 12:07:59 +0300 Subject: [PATCH 15/33] Updated on 2026-08-14 --- .../ui/cardsettings/CardSettingsFragment.kt | 27 ------------ .../DefaultCardSettingsComponent.kt | 36 ++++++++++++++++ .../cardsettings/api/CardSettingsComponent.kt | 14 +++++++ .../AccessCodeRecoveryFragment.kt | 33 --------------- .../DefaultAccessCodeRecoveryComponent.kt | 40 ++++++++++++++++++ .../api/AccessCodeRecoveryComponent.kt | 9 ++++ .../di/AccessCodeRecoveryFeatureModule.kt | 25 +++++++++++ .../AccessCodeRecoveryModel.kt} | 20 +++++---- .../di/CardSettingsFeatureModule.kt | 25 +++++++++++ .../CardSettingsModel.kt} | 42 ++++++++++--------- .../tangem/tap/routing/utils/ChildFactory.kt | 34 ++++++++++++--- .../com/tangem/common/routing/AppRoute.kt | 9 +--- .../visa/model/VisaActivationOrderInfo.kt | 2 + 13 files changed, 215 insertions(+), 101 deletions(-) delete mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsFragment.kt create mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/DefaultCardSettingsComponent.kt create mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/api/CardSettingsComponent.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/coderecovery/AccessCodeRecoveryFragment.kt create mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/coderecovery/DefaultAccessCodeRecoveryComponent.kt create mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/coderecovery/api/AccessCodeRecoveryComponent.kt create mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/coderecovery/di/AccessCodeRecoveryFeatureModule.kt rename app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/coderecovery/{AccessCodeRecoveryViewModel.kt => model/AccessCodeRecoveryModel.kt} (84%) create mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/di/CardSettingsFeatureModule.kt rename app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/{CardSettingsViewModel.kt => model/CardSettingsModel.kt} (89%) diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsFragment.kt b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsFragment.kt deleted file mode 100644 index 328815f377..0000000000 --- a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsFragment.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.tangem.tap.features.details.ui.cardsettings - -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.ui.Modifier -import androidx.fragment.app.viewModels -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.tangem.core.ui.UiDependencies -import com.tangem.core.ui.screen.ComposeFragment -import dagger.hilt.android.AndroidEntryPoint -import javax.inject.Inject - -@AndroidEntryPoint -internal class CardSettingsFragment : ComposeFragment() { - - @Inject - override lateinit var uiDependencies: UiDependencies - - private val viewModel: CardSettingsViewModel by viewModels() - - @Composable - override fun ScreenContent(modifier: Modifier) { - val state by viewModel.screenState.collectAsStateWithLifecycle() - - CardSettingsScreen(modifier = modifier, state = state) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/DefaultCardSettingsComponent.kt b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/DefaultCardSettingsComponent.kt new file mode 100644 index 0000000000..bb92d1a9a1 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/DefaultCardSettingsComponent.kt @@ -0,0 +1,36 @@ +package com.tangem.tap.features.details.ui.cardsettings + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.tangem.core.decompose.context.AppComponentContext +import com.tangem.core.decompose.model.getOrCreateModel +import com.tangem.tap.features.details.ui.cardsettings.api.CardSettingsComponent +import com.tangem.tap.features.details.ui.cardsettings.model.CardSettingsModel +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject + +internal class DefaultCardSettingsComponent @AssistedInject constructor( + @Assisted appComponentContext: AppComponentContext, + @Assisted params: CardSettingsComponent.Params, +) : CardSettingsComponent, AppComponentContext by appComponentContext { + + private val model: CardSettingsModel = getOrCreateModel(params) + + @Composable + override fun Content(modifier: Modifier) { + val state by model.screenState.collectAsStateWithLifecycle() + + CardSettingsScreen(modifier = modifier, state = state) + } + + @AssistedFactory + interface Factory : CardSettingsComponent.Factory { + override fun create( + context: AppComponentContext, + params: CardSettingsComponent.Params, + ): DefaultCardSettingsComponent + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/api/CardSettingsComponent.kt b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/api/CardSettingsComponent.kt new file mode 100644 index 0000000000..608362caa8 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/api/CardSettingsComponent.kt @@ -0,0 +1,14 @@ +package com.tangem.tap.features.details.ui.cardsettings.api + +import com.tangem.core.decompose.factory.ComponentFactory +import com.tangem.core.ui.decompose.ComposableContentComponent +import com.tangem.domain.wallets.models.UserWalletId + +interface CardSettingsComponent : ComposableContentComponent { + + data class Params( + val userWalletId: UserWalletId, + ) + + interface Factory : ComponentFactory +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/coderecovery/AccessCodeRecoveryFragment.kt b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/coderecovery/AccessCodeRecoveryFragment.kt deleted file mode 100644 index bcfe7cd28d..0000000000 --- a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/coderecovery/AccessCodeRecoveryFragment.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.tangem.tap.features.details.ui.cardsettings.coderecovery - -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.ui.Modifier -import androidx.fragment.app.viewModels -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.tangem.common.routing.AppRouter -import com.tangem.core.ui.UiDependencies -import com.tangem.core.ui.screen.ComposeFragment -import com.tangem.tap.common.extensions.dispatchNavigationAction -import com.tangem.tap.store -import dagger.hilt.android.AndroidEntryPoint -import javax.inject.Inject - -@AndroidEntryPoint -class AccessCodeRecoveryFragment : ComposeFragment() { - - private val viewModel: AccessCodeRecoveryViewModel by viewModels() - - @Inject - override lateinit var uiDependencies: UiDependencies - - @Composable - override fun ScreenContent(modifier: Modifier) { - val state by viewModel.screenState.collectAsStateWithLifecycle() - - AccessCodeRecoveryScreen( - state = state, - onBackClick = { store.dispatchNavigationAction(AppRouter::pop) }, - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/coderecovery/DefaultAccessCodeRecoveryComponent.kt b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/coderecovery/DefaultAccessCodeRecoveryComponent.kt new file mode 100644 index 0000000000..fd75548292 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/coderecovery/DefaultAccessCodeRecoveryComponent.kt @@ -0,0 +1,40 @@ +package com.tangem.tap.features.details.ui.cardsettings.coderecovery + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.tangem.common.routing.AppRouter +import com.tangem.core.decompose.context.AppComponentContext +import com.tangem.core.decompose.model.getOrCreateModel +import com.tangem.tap.common.extensions.dispatchNavigationAction +import com.tangem.tap.features.details.ui.cardsettings.coderecovery.api.AccessCodeRecoveryComponent +import com.tangem.tap.features.details.ui.cardsettings.coderecovery.model.AccessCodeRecoveryModel +import com.tangem.tap.store +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject + +@Suppress("UnusedPrivateMember") +internal class DefaultAccessCodeRecoveryComponent @AssistedInject constructor( + @Assisted appComponentContext: AppComponentContext, + @Assisted params: Unit, +) : AccessCodeRecoveryComponent, AppComponentContext by appComponentContext { + + private val model: AccessCodeRecoveryModel = getOrCreateModel() + + @Composable + override fun Content(modifier: Modifier) { + val state by model.screenState.collectAsStateWithLifecycle() + + AccessCodeRecoveryScreen( + state = state, + onBackClick = { store.dispatchNavigationAction(AppRouter::pop) }, + ) + } + + @AssistedFactory + interface Factory : AccessCodeRecoveryComponent.Factory { + override fun create(context: AppComponentContext, params: Unit): DefaultAccessCodeRecoveryComponent + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/coderecovery/api/AccessCodeRecoveryComponent.kt b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/coderecovery/api/AccessCodeRecoveryComponent.kt new file mode 100644 index 0000000000..5cd2e1449c --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/coderecovery/api/AccessCodeRecoveryComponent.kt @@ -0,0 +1,9 @@ +package com.tangem.tap.features.details.ui.cardsettings.coderecovery.api + +import com.tangem.core.decompose.factory.ComponentFactory +import com.tangem.core.ui.decompose.ComposableContentComponent + +interface AccessCodeRecoveryComponent : ComposableContentComponent { + + interface Factory : ComponentFactory +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/coderecovery/di/AccessCodeRecoveryFeatureModule.kt b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/coderecovery/di/AccessCodeRecoveryFeatureModule.kt new file mode 100644 index 0000000000..a4c86d70a7 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/coderecovery/di/AccessCodeRecoveryFeatureModule.kt @@ -0,0 +1,25 @@ +package com.tangem.tap.features.details.ui.cardsettings.coderecovery.di + +import com.tangem.core.decompose.model.Model +import com.tangem.tap.features.details.ui.cardsettings.coderecovery.DefaultAccessCodeRecoveryComponent +import com.tangem.tap.features.details.ui.cardsettings.coderecovery.api.AccessCodeRecoveryComponent +import com.tangem.tap.features.details.ui.cardsettings.coderecovery.model.AccessCodeRecoveryModel +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import dagger.multibindings.ClassKey +import dagger.multibindings.IntoMap + +@Module +@InstallIn(SingletonComponent::class) +internal interface AccessCodeRecoveryFeatureModule { + + @Binds + fun bindFactory(impl: DefaultAccessCodeRecoveryComponent.Factory): AccessCodeRecoveryComponent.Factory + + @Binds + @IntoMap + @ClassKey(AccessCodeRecoveryModel::class) + fun bindModel(model: AccessCodeRecoveryModel): Model +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/coderecovery/AccessCodeRecoveryViewModel.kt b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/coderecovery/model/AccessCodeRecoveryModel.kt similarity index 84% rename from app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/coderecovery/AccessCodeRecoveryViewModel.kt rename to app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/coderecovery/model/AccessCodeRecoveryModel.kt index 1652506ca9..b3c2fb4878 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/coderecovery/AccessCodeRecoveryViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/coderecovery/model/AccessCodeRecoveryModel.kt @@ -1,29 +1,33 @@ -package com.tangem.tap.features.details.ui.cardsettings.coderecovery +package com.tangem.tap.features.details.ui.cardsettings.coderecovery.model -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope +import androidx.compose.runtime.Stable import com.tangem.common.doOnSuccess import com.tangem.common.routing.AppRouter import com.tangem.core.analytics.Analytics +import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.model.Model 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.features.details.ui.cardsettings.coderecovery.AccessCodeRecoveryScreenState 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 -import dagger.hilt.android.lifecycle.HiltViewModel +import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import javax.inject.Inject -@HiltViewModel -internal class AccessCodeRecoveryViewModel @Inject constructor( +@Stable +@ComponentScoped +internal class AccessCodeRecoveryModel @Inject constructor( + override val dispatchers: CoroutineDispatcherProvider, private val tangemSdkManager: TangemSdkManager, private val cardSettingsInteractor: CardSettingsInteractor, -) : ViewModel() { +) : Model() { private val scannedScanResponse = cardSettingsInteractor.scannedScanResponse.value ?: error("Scan response is null") @@ -47,7 +51,7 @@ internal class AccessCodeRecoveryViewModel @Inject constructor( ) } - private fun saveChanges() = viewModelScope.launch { + private fun saveChanges() = modelScope.launch { val isEnabled = screenState.value.enabledSelection tangemSdkManager diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/di/CardSettingsFeatureModule.kt b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/di/CardSettingsFeatureModule.kt new file mode 100644 index 0000000000..78f5ba6486 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/di/CardSettingsFeatureModule.kt @@ -0,0 +1,25 @@ +package com.tangem.tap.features.details.ui.cardsettings.di + +import com.tangem.core.decompose.model.Model +import com.tangem.tap.features.details.ui.cardsettings.api.CardSettingsComponent +import com.tangem.tap.features.details.ui.cardsettings.DefaultCardSettingsComponent +import com.tangem.tap.features.details.ui.cardsettings.model.CardSettingsModel +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import dagger.multibindings.ClassKey +import dagger.multibindings.IntoMap + +@Module +@InstallIn(SingletonComponent::class) +internal interface CardSettingsFeatureModule { + + @Binds + fun bindFactory(impl: DefaultCardSettingsComponent.Factory): CardSettingsComponent.Factory + + @Binds + @IntoMap + @ClassKey(CardSettingsModel::class) + fun bindModel(model: CardSettingsModel): Model +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsViewModel.kt b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/model/CardSettingsModel.kt similarity index 89% rename from app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsViewModel.kt rename to app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/model/CardSettingsModel.kt index 68d354a90c..11964f58c4 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/model/CardSettingsModel.kt @@ -1,16 +1,15 @@ -package com.tangem.tap.features.details.ui.cardsettings +package com.tangem.tap.features.details.ui.cardsettings.model -import android.os.Bundle -import androidx.lifecycle.SavedStateHandle -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope +import androidx.compose.runtime.Stable import arrow.core.getOrElse import com.tangem.common.CompletionResult import com.tangem.common.doOnSuccess import com.tangem.common.routing.AppRoute import com.tangem.common.routing.AppRouter -import com.tangem.common.routing.bundle.unbundle import com.tangem.core.analytics.Analytics +import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.model.Model +import com.tangem.core.decompose.model.ParamsContainer import com.tangem.domain.card.ScanCardProcessor import com.tangem.domain.card.repository.CardSdkConfigRepository import com.tangem.domain.common.CardTypesResolver @@ -20,7 +19,6 @@ import com.tangem.domain.models.scan.CardDTO import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.settings.repositories.SettingsRepository import com.tangem.domain.wallets.builder.UserWalletIdBuilder -import com.tangem.domain.wallets.models.UserWalletId import com.tangem.domain.wallets.usecase.GetUserWalletUseCase import com.tangem.sdk.api.TangemSdkManager import com.tangem.tap.common.analytics.events.AnalyticsParam @@ -29,13 +27,16 @@ 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.features.details.ui.cardsettings.CardInfo +import com.tangem.tap.features.details.ui.cardsettings.CardSettingsScreenState +import com.tangem.tap.features.details.ui.cardsettings.api.CardSettingsComponent 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 import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsAction import com.tangem.tap.store +import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.wallet.R -import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking @@ -43,22 +44,24 @@ import timber.log.Timber import javax.inject.Inject @Suppress("LongParameterList") -@HiltViewModel -internal class CardSettingsViewModel @Inject constructor( +@Stable +@ComponentScoped +internal class CardSettingsModel @Inject constructor( + paramsContainer: ParamsContainer, + override val dispatchers: CoroutineDispatcherProvider, private val scanCardProcessor: ScanCardProcessor, private val tangemSdkManager: TangemSdkManager, private val cardSettingsInteractor: CardSettingsInteractor, private val getUserWalletUseCase: GetUserWalletUseCase, private val cardSdkConfigRepository: CardSdkConfigRepository, private val settingsRepository: SettingsRepository, - savedStateHandle: SavedStateHandle, -) : ViewModel() { +) : Model() { + + private val params = paramsContainer.require() private var previousBiometricsRequestPolicy: Boolean = false - private val userWalletId = savedStateHandle.get(AppRoute.CardSettings.USER_WALLET_ID_KEY) - ?.unbundle(UserWalletId.serializer()) - ?: error("User wallet ID is required for CardSettingsViewModel") + private val userWalletId = params.userWalletId val screenState: MutableStateFlow = MutableStateFlow(getInitialState()) @@ -68,10 +71,11 @@ internal class CardSettingsViewModel @Inject constructor( cardSettingsInteractor.scannedScanResponse .filterNotNull() .onEach(::updateCardDetails) - .launchIn(viewModelScope) + .launchIn(modelScope) } - override fun onCleared() { + override fun onDestroy() { + super.onDestroy() // Restore the previous value of access code request policy cardSdkConfigRepository.isBiometricsRequestPolicy = previousBiometricsRequestPolicy } @@ -96,7 +100,7 @@ internal class CardSettingsViewModel @Inject constructor( onBackClick = ::onBackClick, ) - private fun scanCard() = viewModelScope.launch { + private fun scanCard() = modelScope.launch { scanCardProcessor.scan( analyticsSource = com.tangem.core.analytics.models.AnalyticsParam.ScreensSources.Settings, allowsRequestAccessCodeFromRepository = true, @@ -217,7 +221,7 @@ internal class CardSettingsViewModel @Inject constructor( } } - private fun changeAccessCode() = viewModelScope.launch { + private fun changeAccessCode() = modelScope.launch { val scanResponse = requireNotNull(cardSettingsInteractor.scannedScanResponse.value) { "Scan response is null" } when (val result = tangemSdkManager.setAccessCode(scanResponse.card.cardId)) { diff --git a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt index 2342a80e63..5818faad8e 100644 --- a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt +++ b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt @@ -22,8 +22,8 @@ import com.tangem.features.tokendetails.TokenDetailsComponent import com.tangem.features.wallet.navigation.WalletRouter import com.tangem.tap.features.details.ui.appcurrency.AppCurrencySelectorFragment import com.tangem.tap.features.details.ui.appsettings.AppSettingsFragment -import com.tangem.tap.features.details.ui.cardsettings.CardSettingsFragment -import com.tangem.tap.features.details.ui.cardsettings.coderecovery.AccessCodeRecoveryFragment +import com.tangem.tap.features.details.ui.cardsettings.api.CardSettingsComponent +import com.tangem.tap.features.details.ui.cardsettings.coderecovery.api.AccessCodeRecoveryComponent import com.tangem.tap.features.details.ui.resetcard.ResetCardFragment import com.tangem.tap.features.details.ui.securitymode.SecurityModeFragment import com.tangem.tap.features.details.ui.walletconnect.api.WalletConnectComponent @@ -65,6 +65,8 @@ internal class ChildFactory @Inject constructor( private val tokenDetailsComponentFactory: TokenDetailsComponent.Factory, private val walletConnectComponentFactory: WalletConnectComponent.Factory, private val qrScanningComponentFactory: QrScanningComponent.Factory, + private val accessCodeRecoveryComponentFactory: AccessCodeRecoveryComponent.Factory, + private val cardSettingsComponentFactory: CardSettingsComponent.Factory, private val walletRouter: WalletRouter, private val testerRouter: TesterRouter, private val pushNotificationRouter: PushNotificationsRouter, @@ -285,11 +287,23 @@ internal class ChildFactory @Inject constructor( componentFactory = qrScanningComponentFactory, ) } - is AppRoute.AccessCodeRecovery, + is AppRoute.AccessCodeRecovery -> { + createComponentChild( + contextProvider = contextProvider(route, contextFactory), + params = Unit, + componentFactory = accessCodeRecoveryComponentFactory, + ) + } + is AppRoute.CardSettings -> { + createComponentChild( + contextProvider = contextProvider(route, contextFactory), + params = CardSettingsComponent.Params(userWalletId = route.userWalletId), + componentFactory = cardSettingsComponentFactory, + ) + } is AppRoute.AppCurrencySelector, is AppRoute.SaveWallet, is AppRoute.AppSettings, - is AppRoute.CardSettings, is AppRoute.DetailsSecurity, is AppRoute.OnboardingNote, is AppRoute.OnboardingOther, @@ -314,7 +328,11 @@ internal class ChildFactory @Inject constructor( Child.Initial } is AppRoute.AccessCodeRecovery -> { - route.asFragmentChild(Provider { AccessCodeRecoveryFragment() }) + route.asComponentChild( + contextProvider = contextProvider(route, contextFactory), + params = Unit, + componentFactory = accessCodeRecoveryComponentFactory, + ) } is AppRoute.AppCurrencySelector -> { route.asFragmentChild(Provider { AppCurrencySelectorFragment() }) @@ -340,7 +358,11 @@ internal class ChildFactory @Inject constructor( route.asFragmentChild(Provider { AppSettingsFragment() }) } is AppRoute.CardSettings -> { - route.asFragmentChild(Provider { CardSettingsFragment() }) + route.asComponentChild( + contextProvider = contextProvider(route, contextFactory), + params = CardSettingsComponent.Params(userWalletId = route.userWalletId), + componentFactory = cardSettingsComponentFactory, + ) } is AppRoute.Details -> { route.asComponentChild( diff --git a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt index 62df97b518..2d3246daa6 100644 --- a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt +++ b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt @@ -111,14 +111,7 @@ sealed class AppRoute(val path: String) : Route { @Serializable data class CardSettings( val userWalletId: UserWalletId, - ) : AppRoute(path = "/card_settings/${userWalletId.stringValue}"), RouteBundleParams { - - override fun getBundle(): Bundle = bundle(serializer()) - - companion object { - const val USER_WALLET_ID_KEY = "userWalletId" - } - } + ) : AppRoute(path = "/card_settings/${userWalletId.stringValue}") @Serializable data object AppSettings : AppRoute(path = "/app_settings") diff --git a/domain/visa/models/src/main/kotlin/com/tangem/domain/visa/model/VisaActivationOrderInfo.kt b/domain/visa/models/src/main/kotlin/com/tangem/domain/visa/model/VisaActivationOrderInfo.kt index b8320e7678..78bbd9692b 100644 --- a/domain/visa/models/src/main/kotlin/com/tangem/domain/visa/model/VisaActivationOrderInfo.kt +++ b/domain/visa/models/src/main/kotlin/com/tangem/domain/visa/model/VisaActivationOrderInfo.kt @@ -1,9 +1,11 @@ package com.tangem.domain.visa.model import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass import kotlinx.serialization.Serializable @Serializable +@JsonClass(generateAdapter = true) data class VisaActivationOrderInfo( @Json(name = "orderId") val orderId: String, @Json(name = "customer_id") val customerId: String, From 2c65f0cfb0375d0c2e26ad134f84d948f807ec2d Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 21 Feb 2025 12:16:36 +0300 Subject: [PATCH 16/33] Updated on 2026-08-14 --- .../main/java/com/tangem/tap/MainActivity.kt | 5 ++++ data/balance-hiding/build.gradle.kts | 1 + .../DefaultBalanceHidingRepository.kt | 5 +++- .../DefaultDeviceFlipDetector.kt | 26 +++++++++++++++++-- .../balancehiding/di/BalanceHidingModule.kt | 19 +++++--------- 5 files changed, 40 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/MainActivity.kt b/app/src/main/java/com/tangem/tap/MainActivity.kt index 9b8c16a128..20410b9a00 100644 --- a/app/src/main/java/com/tangem/tap/MainActivity.kt +++ b/app/src/main/java/com/tangem/tap/MainActivity.kt @@ -46,6 +46,7 @@ import com.tangem.core.ui.message.EventMessageEffect import com.tangem.core.ui.message.SnackbarMessage import com.tangem.core.ui.res.TangemColorPalette import com.tangem.core.ui.res.TangemTheme +import com.tangem.data.balancehiding.DefaultDeviceFlipDetector import com.tangem.data.card.sdk.CardSdkOwner import com.tangem.domain.apptheme.model.AppThemeMode import com.tangem.domain.card.ScanCardUseCase @@ -205,6 +206,9 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac @Inject internal lateinit var uiDependencies: UiDependencies + @Inject + internal lateinit var defaultDeviceFlipDetector: DefaultDeviceFlipDetector + internal val viewModel: MainViewModel by viewModels() private lateinit var appThemeModeFlow: SharedFlow @@ -271,6 +275,7 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac } lifecycle.addObserver(WindowObscurationObserver) + lifecycle.addObserver(defaultDeviceFlipDetector) } private fun installEventMessageEffect() { diff --git a/data/balance-hiding/build.gradle.kts b/data/balance-hiding/build.gradle.kts index 84db19b2d7..3d3caf3397 100644 --- a/data/balance-hiding/build.gradle.kts +++ b/data/balance-hiding/build.gradle.kts @@ -12,6 +12,7 @@ android { dependencies { implementation(deps.androidx.datastore) + implementation(deps.androidx.appCompat) /** DI */ implementation(deps.hilt.android) diff --git a/data/balance-hiding/src/main/java/com/tangem/data/balancehiding/DefaultBalanceHidingRepository.kt b/data/balance-hiding/src/main/java/com/tangem/data/balancehiding/DefaultBalanceHidingRepository.kt index f2fdcd320e..b0200df3ff 100644 --- a/data/balance-hiding/src/main/java/com/tangem/data/balancehiding/DefaultBalanceHidingRepository.kt +++ b/data/balance-hiding/src/main/java/com/tangem/data/balancehiding/DefaultBalanceHidingRepository.kt @@ -8,8 +8,11 @@ import com.tangem.datasource.local.preferences.utils.storeObject import com.tangem.domain.balancehiding.BalanceHidingSettings import com.tangem.domain.balancehiding.repositories.BalanceHidingRepository import kotlinx.coroutines.flow.Flow +import javax.inject.Inject +import javax.inject.Singleton -internal class DefaultBalanceHidingRepository( +@Singleton +internal class DefaultBalanceHidingRepository @Inject constructor( private val appPreferencesStore: AppPreferencesStore, ) : BalanceHidingRepository { diff --git a/data/balance-hiding/src/main/java/com/tangem/data/balancehiding/DefaultDeviceFlipDetector.kt b/data/balance-hiding/src/main/java/com/tangem/data/balancehiding/DefaultDeviceFlipDetector.kt index 30b2e97726..9a4c8de638 100644 --- a/data/balance-hiding/src/main/java/com/tangem/data/balancehiding/DefaultDeviceFlipDetector.kt +++ b/data/balance-hiding/src/main/java/com/tangem/data/balancehiding/DefaultDeviceFlipDetector.kt @@ -3,18 +3,40 @@ package com.tangem.data.balancehiding import android.content.Context import android.hardware.Sensor import android.hardware.SensorManager +import androidx.lifecycle.DefaultLifecycleObserver +import androidx.lifecycle.LifecycleOwner import com.tangem.domain.balancehiding.DeviceFlipDetector +import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.callbackFlow +import java.util.concurrent.atomic.AtomicBoolean +import javax.inject.Inject +import javax.inject.Singleton -internal class DefaultDeviceFlipDetector(context: Context) : DeviceFlipDetector { +@Singleton +class DefaultDeviceFlipDetector @Inject constructor( + @ApplicationContext context: Context, +) : DeviceFlipDetector, DefaultLifecycleObserver { private val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager private var gravitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY) + private var isResumedState = AtomicBoolean(false) + + override fun onPause(owner: LifecycleOwner) { + isResumedState.set(false) + } + + override fun onResume(owner: LifecycleOwner) { + isResumedState.set(true) + } override fun getDeviceFlipFlow(): Flow = callbackFlow { - val listener = FlipListener { trySend(Unit) } + val listener = FlipListener { + if (isResumedState.get()) { + trySend(Unit) + } + } gravitySensor?.let { sensorManager.registerListener(listener, it, SensorManager.SENSOR_DELAY_NORMAL) diff --git a/data/balance-hiding/src/main/java/com/tangem/data/balancehiding/di/BalanceHidingModule.kt b/data/balance-hiding/src/main/java/com/tangem/data/balancehiding/di/BalanceHidingModule.kt index f83fac4932..0f213c83f8 100644 --- a/data/balance-hiding/src/main/java/com/tangem/data/balancehiding/di/BalanceHidingModule.kt +++ b/data/balance-hiding/src/main/java/com/tangem/data/balancehiding/di/BalanceHidingModule.kt @@ -1,31 +1,24 @@ package com.tangem.data.balancehiding.di -import android.content.Context import com.tangem.data.balancehiding.DefaultBalanceHidingRepository import com.tangem.data.balancehiding.DefaultDeviceFlipDetector -import com.tangem.datasource.local.preferences.AppPreferencesStore import com.tangem.domain.balancehiding.DeviceFlipDetector import com.tangem.domain.balancehiding.repositories.BalanceHidingRepository +import dagger.Binds import dagger.Module -import dagger.Provides import dagger.hilt.InstallIn -import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import javax.inject.Singleton @Module @InstallIn(SingletonComponent::class) -internal object BalanceHidingModule { +internal interface BalanceHidingModule { - @Provides + @Binds @Singleton - fun provideBalanceHidingRepository(appPreferencesStore: AppPreferencesStore): BalanceHidingRepository { - return DefaultBalanceHidingRepository(appPreferencesStore = appPreferencesStore) - } + fun provideBalanceHidingRepository(impl: DefaultBalanceHidingRepository): BalanceHidingRepository - @Provides + @Binds @Singleton - fun provideFlipDetector(@ApplicationContext context: Context): DeviceFlipDetector { - return DefaultDeviceFlipDetector(context = context) - } + fun provideFlipDetector(impl: DefaultDeviceFlipDetector): DeviceFlipDetector } \ No newline at end of file From 6afeba5f96c50c66537cc642a7cb9da3fd739e4d Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 21 Feb 2025 11:26:05 +0000 Subject: [PATCH 17/33] Updated on 2026-08-14 --- gradle/tangem_dependencies.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/tangem_dependencies.toml b/gradle/tangem_dependencies.toml index 2b6ab573a0..b58666bdd9 100644 --- a/gradle/tangem_dependencies.toml +++ b/gradle/tangem_dependencies.toml @@ -1,7 +1,7 @@ [versions] -tangemBlockchainSdk = "release-app_5.21-958" +tangemBlockchainSdk = "develop-959" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds -tangemCardSdk = "release-app_5.21-435" +tangemCardSdk = "develop-434" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ tangemVico = "2.0.0-alpha.25-tangem-developments8" #tangemVico = "0.0.1" # Keep it! - used for local builds ^ From c5d78b20407b744d8224b092f1eaff8018b03463 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 24 Feb 2025 00:58:45 +0500 Subject: [PATCH 18/33] Updated on 2026-08-14 --- .../configs/feature_toggles_config.json | 4 ++ .../local/preferences/PreferencesKeys.kt | 2 + .../data/wallets/DefaultWalletsRepository.kt | 20 ++++++ .../wallets/repository/WalletsRepository.kt | 6 ++ features/nft/api/.gitignore | 1 + features/nft/api/build.gradle.kts | 22 +++++++ .../tangem/features/nft/NFTFeatureToggles.kt | 5 ++ features/nft/impl/.gitignore | 1 + features/nft/impl/build.gradle.kts | 66 +++++++++++++++++++ .../features/nft/DefaultNFTFeatureToggles.kt | 10 +++ .../tangem/features/nft/NFTFeatureModule.kt | 19 ++++++ 11 files changed, 156 insertions(+) create mode 100644 features/nft/api/.gitignore create mode 100644 features/nft/api/build.gradle.kts create mode 100644 features/nft/api/src/main/kotlin/com/tangem/features/nft/NFTFeatureToggles.kt create mode 100644 features/nft/impl/.gitignore create mode 100644 features/nft/impl/build.gradle.kts create mode 100644 features/nft/impl/src/main/kotlin/com/tangem/features/nft/DefaultNFTFeatureToggles.kt create mode 100644 features/nft/impl/src/main/kotlin/com/tangem/features/nft/NFTFeatureModule.kt diff --git a/core/config-toggles/src/main/assets/configs/feature_toggles_config.json b/core/config-toggles/src/main/assets/configs/feature_toggles_config.json index ba2bb626ea..92d4653d08 100644 --- a/core/config-toggles/src/main/assets/configs/feature_toggles_config.json +++ b/core/config-toggles/src/main/assets/configs/feature_toggles_config.json @@ -46,5 +46,9 @@ { "name": "BALANCES_CACHING_ENABLED", "version": "5.21.0" + }, + { + "name": "NFT_ENABLED", + "version": "undefined" } ] diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt b/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt index 434d4c4a92..52d244da2b 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt @@ -121,6 +121,8 @@ object PreferencesKeys { val SEED_FIRST_NOTIFICATION_SHOW_TIME by lazy { longPreferencesKey("seedFirstNotificationTime") } + val WALLETS_WITH_NFT_ENABLED_KEY by lazy { stringSetPreferencesKey(name = "walletsWithNftEnabled") } + fun getShouldShowStoriesKey(storyId: String) = booleanPreferencesKey("shouldShowStories_$storyId") // region Permission diff --git a/data/wallets/src/main/java/com/tangem/data/wallets/DefaultWalletsRepository.kt b/data/wallets/src/main/java/com/tangem/data/wallets/DefaultWalletsRepository.kt index 0d0c0f38ee..e8a5b95b08 100644 --- a/data/wallets/src/main/java/com/tangem/data/wallets/DefaultWalletsRepository.kt +++ b/data/wallets/src/main/java/com/tangem/data/wallets/DefaultWalletsRepository.kt @@ -202,4 +202,24 @@ internal class DefaultWalletsRepository( } } } + + override fun nftEnabledStatus(userWalletId: UserWalletId): Flow { + return appPreferencesStore + .get(key = PreferencesKeys.WALLETS_WITH_NFT_ENABLED_KEY, default = emptySet()) + .map { it.contains(userWalletId.stringValue) } + } + + override suspend fun enableNFT(userWalletId: UserWalletId) { + appPreferencesStore.editData { + val added = it[PreferencesKeys.WALLETS_WITH_NFT_ENABLED_KEY].orEmpty() + it[PreferencesKeys.WALLETS_WITH_NFT_ENABLED_KEY] = added + userWalletId.stringValue + } + } + + override suspend fun disableNFT(userWalletId: UserWalletId) { + appPreferencesStore.editData { + val added = it[PreferencesKeys.WALLETS_WITH_NFT_ENABLED_KEY].orEmpty() + it[PreferencesKeys.WALLETS_WITH_NFT_ENABLED_KEY] = added - userWalletId.stringValue + } + } } \ No newline at end of file diff --git a/domain/wallets/src/main/java/com/tangem/domain/wallets/repository/WalletsRepository.kt b/domain/wallets/src/main/java/com/tangem/domain/wallets/repository/WalletsRepository.kt index f226543d60..b1e526ce5c 100644 --- a/domain/wallets/src/main/java/com/tangem/domain/wallets/repository/WalletsRepository.kt +++ b/domain/wallets/src/main/java/com/tangem/domain/wallets/repository/WalletsRepository.kt @@ -29,4 +29,10 @@ interface WalletsRepository { suspend fun acceptSeedPhraseSecondNotification(userWalletId: UserWalletId) suspend fun markWallet2WasCreated(userWalletId: UserWalletId) + + fun nftEnabledStatus(userWalletId: UserWalletId): Flow + + suspend fun enableNFT(userWalletId: UserWalletId) + + suspend fun disableNFT(userWalletId: UserWalletId) } \ No newline at end of file diff --git a/features/nft/api/.gitignore b/features/nft/api/.gitignore new file mode 100644 index 0000000000..42afabfd2a --- /dev/null +++ b/features/nft/api/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/features/nft/api/build.gradle.kts b/features/nft/api/build.gradle.kts new file mode 100644 index 0000000000..f94a0582c0 --- /dev/null +++ b/features/nft/api/build.gradle.kts @@ -0,0 +1,22 @@ +plugins { + alias(deps.plugins.android.library) + alias(deps.plugins.kotlin.android) + id("configuration") +} + +android { + namespace = "com.tangem.features.nft.api" +} + +dependencies { + + /* Project - Domain */ + implementation(projects.domain.models) + + /* Project - Core */ + implementation(projects.core.decompose) + implementation(projects.core.ui) + + /* Compose */ + implementation(deps.compose.runtime) +} \ No newline at end of file diff --git a/features/nft/api/src/main/kotlin/com/tangem/features/nft/NFTFeatureToggles.kt b/features/nft/api/src/main/kotlin/com/tangem/features/nft/NFTFeatureToggles.kt new file mode 100644 index 0000000000..a3b0ad1cb5 --- /dev/null +++ b/features/nft/api/src/main/kotlin/com/tangem/features/nft/NFTFeatureToggles.kt @@ -0,0 +1,5 @@ +package com.tangem.features.nft + +interface NFTFeatureToggles { + val isNFTEnabled: Boolean +} \ No newline at end of file diff --git a/features/nft/impl/.gitignore b/features/nft/impl/.gitignore new file mode 100644 index 0000000000..42afabfd2a --- /dev/null +++ b/features/nft/impl/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/features/nft/impl/build.gradle.kts b/features/nft/impl/build.gradle.kts new file mode 100644 index 0000000000..0de9bbcd2d --- /dev/null +++ b/features/nft/impl/build.gradle.kts @@ -0,0 +1,66 @@ +plugins { + alias(deps.plugins.android.library) + alias(deps.plugins.kotlin.android) + alias(deps.plugins.kotlin.kapt) + alias(deps.plugins.kotlin.serialization) + alias(deps.plugins.hilt.android) + id("configuration") +} + +android { + namespace = "com.tangem.features.nft.impl" +} + +dependencies { + /** Api */ + implementation(projects.features.nft.api) + + /** Core modules */ + implementation(projects.core.configToggles) + implementation(projects.core.analytics) + implementation(projects.core.analytics.models) + implementation(projects.core.utils) + implementation(projects.core.ui) + implementation(projects.core.res) + implementation(projects.core.decompose) + implementation(projects.core.navigation) + implementation(projects.core.datasource) + + /** Common */ + implementation(projects.common.ui) + implementation(projects.common.routing) + + /** Tangem libraries */ + implementation(projects.libs.tangemSdkApi) + implementation(deps.tangem.card.core) + implementation(deps.tangem.card.android) { + exclude(module = "joda-time") + } + + /** AndroidX libraries */ + implementation(deps.androidx.core.ktx) + implementation(deps.lifecycle.runtime.ktx) + + /** Compose libraries */ + implementation(deps.compose.material) // to use buttons and text field in MultiWalletSeedPhraseImport.kt + implementation(deps.compose.material3) + implementation(deps.compose.animation) + implementation(deps.compose.foundation) + implementation(deps.compose.ui) + implementation(deps.compose.ui.tooling) + implementation(deps.compose.coil) + implementation(deps.lottie.compose) + implementation(deps.decompose.ext.compose) + implementation(deps.androidx.activity.compose) + implementation(deps.androidx.datastore) + + /** Other libraries */ + implementation(deps.kotlin.immutable.collections) + implementation(deps.kotlin.serialization) + implementation(deps.timber) + implementation(deps.firebase.crashlytics) + + /** DI */ + implementation(deps.hilt.android) + kapt(deps.hilt.kapt) +} \ No newline at end of file diff --git a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/DefaultNFTFeatureToggles.kt b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/DefaultNFTFeatureToggles.kt new file mode 100644 index 0000000000..7697217e52 --- /dev/null +++ b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/DefaultNFTFeatureToggles.kt @@ -0,0 +1,10 @@ +package com.tangem.features.nft + +import com.tangem.core.configtoggle.feature.FeatureTogglesManager + +internal class DefaultNFTFeatureToggles( + private val featureTogglesManager: FeatureTogglesManager, +) : NFTFeatureToggles { + override val isNFTEnabled: Boolean + get() = featureTogglesManager.isFeatureEnabled(name = "NFT_ENABLED") +} \ No newline at end of file diff --git a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/NFTFeatureModule.kt b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/NFTFeatureModule.kt new file mode 100644 index 0000000000..b456b29b0b --- /dev/null +++ b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/NFTFeatureModule.kt @@ -0,0 +1,19 @@ +package com.tangem.features.nft + +import com.tangem.core.configtoggle.feature.FeatureTogglesManager +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +internal object NFTFeatureModule { + + @Provides + @Singleton + fun provideFeatureToggles(featureTogglesManager: FeatureTogglesManager): NFTFeatureToggles { + return DefaultNFTFeatureToggles(featureTogglesManager) + } +} \ No newline at end of file From 6ad6215eb00c200d7aafaccf7b8e261a6616c9c7 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 24 Feb 2025 09:31:32 +0200 Subject: [PATCH 19/33] Updated on 2026-08-14 --- .../auth/DefaultExpressAuthProvider.kt | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/network/auth/DefaultExpressAuthProvider.kt b/app/src/main/java/com/tangem/tap/network/auth/DefaultExpressAuthProvider.kt index 7331b9f95c..452b90127d 100644 --- a/app/src/main/java/com/tangem/tap/network/auth/DefaultExpressAuthProvider.kt +++ b/app/src/main/java/com/tangem/tap/network/auth/DefaultExpressAuthProvider.kt @@ -4,6 +4,7 @@ import com.tangem.datasource.local.preferences.AppPreferencesStore import com.tangem.datasource.local.preferences.PreferencesKeys import com.tangem.datasource.local.preferences.utils.getSyncOrDefault import com.tangem.datasource.local.userwallet.UserWalletsStore +import com.tangem.domain.wallets.models.UserWallet import com.tangem.lib.auth.ExpressAuthProvider import kotlinx.coroutines.runBlocking import java.util.UUID @@ -25,6 +26,17 @@ internal class DefaultExpressAuthProvider( } override fun getRefCode(): String { + val selectedUserWallet = userWalletsStore.selectedUserWalletOrNull ?: error("Can not get selected user wallet") + + return when { + isRing(selectedUserWallet) -> "ring" + isChangeNow(selectedUserWallet) -> "ChangeNow" + isPartner(selectedUserWallet) -> "partner" + else -> "" + } + } + + private fun isRing(selectedUserWallet: UserWallet): Boolean { val addedWalletsWithRings = runBlocking { appPreferencesStore.getSyncOrDefault( key = PreferencesKeys.ADDED_WALLETS_WITH_RING_KEY, @@ -32,9 +44,19 @@ internal class DefaultExpressAuthProvider( ) } - val userWalletId = userWalletsStore.selectedUserWalletOrNull?.walletId?.stringValue - ?: error("No user id provided") + return addedWalletsWithRings.contains(selectedUserWallet.walletId.stringValue) + } - return if (addedWalletsWithRings.contains(userWalletId)) "ring" else "" + private fun isChangeNow(selectedUserWallet: UserWallet): Boolean { + return selectedUserWallet.scanResponse.card.batchId == BATCH_ID_CHANGENOW + } + + private fun isPartner(selectedUserWallet: UserWallet): Boolean { + return selectedUserWallet.scanResponse.card.batchId == BATCH_ID_PARTNER + } + + private companion object { + const val BATCH_ID_CHANGENOW = "BB000013" + const val BATCH_ID_PARTNER = "AF990015" } } \ No newline at end of file From 6d56af68f5d08d08679ffa7cfba0f076224ed2a8 Mon Sep 17 00:00:00 2001 From: Tangem Date: Sat, 22 Feb 2025 14:27:25 +0300 Subject: [PATCH 20/33] Updated on 2026-08-14 --- .../com/tangem/tap/domain/sdk/impl/DefaultTangemSdkManager.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/com/tangem/tap/domain/sdk/impl/DefaultTangemSdkManager.kt b/app/src/main/java/com/tangem/tap/domain/sdk/impl/DefaultTangemSdkManager.kt index d0f4cc5985..abf3ce3f3c 100644 --- a/app/src/main/java/com/tangem/tap/domain/sdk/impl/DefaultTangemSdkManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/sdk/impl/DefaultTangemSdkManager.kt @@ -490,6 +490,7 @@ internal class DefaultTangemSdkManager( activationInput = activationInput, coroutineScope = this, ), + cardId = activationInput.cardId, initialMessage = Message(resources.getStringSafe(R.string.initial_message_tap_header)), ) } @@ -502,6 +503,7 @@ internal class DefaultTangemSdkManager( runnable = VisaCustomerWalletApproveTask( visaDataForApprove = visaDataForApprove, ), + cardId = visaDataForApprove.customerWalletCardId, initialMessage = Message(resources.getStringSafe(R.string.initial_message_tap_header)), ) } From 3d9e937ee90ac1a8a2a532185e677d1f88e76bf6 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 17 Feb 2025 21:44:49 +0300 Subject: [PATCH 21/33] Updated on 2026-08-14 --- .../network/auth/DefaultVisaAuthProvider.kt | 19 --- .../tangem/tap/network/auth/di/AuthModule.kt | 13 -- .../api/common/visa/TangemVisaAuthProvider.kt | 6 - .../datasource/api/visa/TangemVisaApi.kt | 19 ++- .../datasource/api/visa/TangemVisaAuthApi.kt | 3 +- .../visa/models/response/VisaCustomerInfo.kt | 15 +++ .../models/response}/VisaTxHistoryResponse.kt | 2 +- .../data/visa/di/ImplementedVisaDataModule.kt | 25 ---- .../visa/DefaultVisaActivationRepository.kt | 6 + .../tangem/data/visa/DefaultVisaRepository.kt | 123 ++++++------------ .../data/visa/MockVisaActivationRepository.kt | 4 + ...isaRepository.kt => MockVisaRepository.kt} | 3 +- .../com/tangem/data/visa/config/VisaConfig.kt | 2 + .../tangem/data/visa/config/VisaLibLoader.kt | 32 +---- .../data/visa/di/ImplementedVisaRepository.kt | 6 - .../di/ImplementedVisaRepositoryModule.kt | 16 --- .../com/tangem/data/visa/di/VisaDataModule.kt | 27 ++-- .../tangem/data/visa/utils/CurrencyUtils.kt | 0 .../data/visa/utils/VisaApiRequestMaker.kt | 107 +++++++++++++++ .../tangem/data/visa/utils/VisaConstants.kt | 10 +- .../data/visa/utils/VisaCurrencyFactory.kt | 0 .../data/visa/utils/VisaTxDetailsFactory.kt | 2 +- .../visa/utils/VisaTxHistoryItemFactory.kt | 2 +- .../visa/utils/VisaTxHistoryPagingSource.kt | 6 +- .../domain/visa/SetVisaPinCodeUseCase.kt | 5 +- .../repository/VisaActivationRepository.kt | 2 + .../visa/DefaultVisaContractInfoProvider.kt | 48 ++++--- .../lib/visa/VisaContractInfoProvider.kt | 9 +- .../kotlin/com/tangem/lib/visa/api/VisaApi.kt | 18 --- .../com/tangem/lib/visa/api/VisaApiBuilder.kt | 72 ---------- 30 files changed, 258 insertions(+), 344 deletions(-) delete mode 100644 app/src/main/java/com/tangem/tap/network/auth/DefaultVisaAuthProvider.kt delete mode 100644 core/datasource/src/main/java/com/tangem/datasource/api/common/visa/TangemVisaAuthProvider.kt create mode 100644 core/datasource/src/main/java/com/tangem/datasource/api/visa/models/response/VisaCustomerInfo.kt rename {libs/visa/src/main/kotlin/com/tangem/lib/visa/model => core/datasource/src/main/java/com/tangem/datasource/api/visa/models/response}/VisaTxHistoryResponse.kt (98%) delete mode 100644 data/visa/src/debug/kotlin/com/tangem/data/visa/di/ImplementedVisaDataModule.kt rename data/visa/src/{debug => main}/kotlin/com/tangem/data/visa/DefaultVisaRepository.kt (65%) rename data/visa/src/main/kotlin/com/tangem/data/visa/{DummyVisaRepository.kt => MockVisaRepository.kt} (89%) rename data/visa/src/{debug => main}/kotlin/com/tangem/data/visa/config/VisaConfig.kt (92%) rename data/visa/src/{debug => main}/kotlin/com/tangem/data/visa/config/VisaLibLoader.kt (68%) delete mode 100644 data/visa/src/main/kotlin/com/tangem/data/visa/di/ImplementedVisaRepository.kt delete mode 100644 data/visa/src/main/kotlin/com/tangem/data/visa/di/ImplementedVisaRepositoryModule.kt rename data/visa/src/{debug => main}/kotlin/com/tangem/data/visa/utils/CurrencyUtils.kt (100%) create mode 100644 data/visa/src/main/kotlin/com/tangem/data/visa/utils/VisaApiRequestMaker.kt rename data/visa/src/{debug => main}/kotlin/com/tangem/data/visa/utils/VisaConstants.kt (86%) rename data/visa/src/{debug => main}/kotlin/com/tangem/data/visa/utils/VisaCurrencyFactory.kt (100%) rename data/visa/src/{debug => main}/kotlin/com/tangem/data/visa/utils/VisaTxDetailsFactory.kt (97%) rename data/visa/src/{debug => main}/kotlin/com/tangem/data/visa/utils/VisaTxHistoryItemFactory.kt (89%) rename data/visa/src/{debug => main}/kotlin/com/tangem/data/visa/utils/VisaTxHistoryPagingSource.kt (92%) delete mode 100644 libs/visa/src/main/kotlin/com/tangem/lib/visa/api/VisaApi.kt delete mode 100644 libs/visa/src/main/kotlin/com/tangem/lib/visa/api/VisaApiBuilder.kt diff --git a/app/src/main/java/com/tangem/tap/network/auth/DefaultVisaAuthProvider.kt b/app/src/main/java/com/tangem/tap/network/auth/DefaultVisaAuthProvider.kt deleted file mode 100644 index 0a793b0222..0000000000 --- a/app/src/main/java/com/tangem/tap/network/auth/DefaultVisaAuthProvider.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.tangem.tap.network.auth - -import com.tangem.datasource.api.common.visa.TangemVisaAuthProvider -import com.tangem.domain.visa.model.VisaCardActivationStatus -import com.tangem.domain.visa.model.getAuthHeader -import com.tangem.domain.wallets.legacy.UserWalletsListManager -import javax.inject.Inject - -internal class DefaultVisaAuthProvider @Inject constructor( - private val userWalletsListManager: UserWalletsListManager, -) : TangemVisaAuthProvider { - - override suspend fun getAuthHeader(cardId: String): String { - val card = userWalletsListManager.userWalletsSync.firstOrNull { it.cardId == cardId } - val status = card?.scanResponse?.visaCardActivationStatus as? VisaCardActivationStatus.Activated - ?: return "Error in the app!" - return status.visaAuthTokens.getAuthHeader() - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/network/auth/di/AuthModule.kt b/app/src/main/java/com/tangem/tap/network/auth/di/AuthModule.kt index 829f08d9cc..c72a9c145c 100644 --- a/app/src/main/java/com/tangem/tap/network/auth/di/AuthModule.kt +++ b/app/src/main/java/com/tangem/tap/network/auth/di/AuthModule.kt @@ -1,21 +1,17 @@ package com.tangem.tap.network.auth.di import com.tangem.datasource.api.common.AuthProvider -import com.tangem.datasource.api.common.visa.TangemVisaAuthProvider import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage import com.tangem.datasource.local.preferences.AppPreferencesStore import com.tangem.datasource.local.userwallet.UserWalletsStore import com.tangem.domain.wallets.legacy.UserWalletsListManager import com.tangem.lib.auth.ExpressAuthProvider import com.tangem.lib.auth.StakeKitAuthProvider -import com.tangem.tap.network.auth.* import com.tangem.tap.network.auth.DefaultAppVersionProvider import com.tangem.tap.network.auth.DefaultAuthProvider import com.tangem.tap.network.auth.DefaultExpressAuthProvider import com.tangem.tap.network.auth.DefaultStakeKitAuthProvider -import com.tangem.tap.network.auth.DefaultVisaAuthProvider import com.tangem.utils.version.AppVersionProvider -import dagger.Binds import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -55,13 +51,4 @@ internal class AuthModule { fun provideAppVersionProvider(): AppVersionProvider { return DefaultAppVersionProvider() } -} - -@Module -@InstallIn(SingletonComponent::class) -internal interface AuthBindModule { - - @Binds - @Singleton - fun bindVisaAuthProvider(authStorage: DefaultVisaAuthProvider): TangemVisaAuthProvider } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/common/visa/TangemVisaAuthProvider.kt b/core/datasource/src/main/java/com/tangem/datasource/api/common/visa/TangemVisaAuthProvider.kt deleted file mode 100644 index 1f164d8411..0000000000 --- a/core/datasource/src/main/java/com/tangem/datasource/api/common/visa/TangemVisaAuthProvider.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.tangem.datasource.api.common.visa - -interface TangemVisaAuthProvider { - - suspend fun getAuthHeader(cardId: String): String -} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/visa/TangemVisaApi.kt b/core/datasource/src/main/java/com/tangem/datasource/api/visa/TangemVisaApi.kt index 802738fbd7..a0d08a74a1 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/visa/TangemVisaApi.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/visa/TangemVisaApi.kt @@ -5,9 +5,7 @@ import com.tangem.datasource.api.utils.ReadTimeout import com.tangem.datasource.api.visa.models.request.ActivationByCardWalletRequest import com.tangem.datasource.api.visa.models.request.ActivationByCustomerWalletRequest import com.tangem.datasource.api.visa.models.request.SetPinCodeRequest -import com.tangem.datasource.api.visa.models.response.CardActivationRemoteStateResponse -import com.tangem.datasource.api.visa.models.response.CardWalletDataToSignResponse -import com.tangem.datasource.api.visa.models.response.CustomerWalletDataToSignResponse +import com.tangem.datasource.api.visa.models.response.* import retrofit2.http.Body import retrofit2.http.GET import retrofit2.http.Header @@ -71,4 +69,19 @@ interface TangemVisaApi { @Header("Authorization") authHeader: String, @Body body: SetPinCodeRequest, ): ApiResponse + + @GET("customer/info") + suspend fun getCustomerInfo( + @Header("Authorization") authHeader: String, + @Query("card_id") cardId: String, + ): ApiResponse + + @GET("product_instance/transactions") + suspend fun getTxHistory( + @Header("Authorization") authHeader: String, + @Query("customer_id") customerId: String, + @Query("product_instance_id") productInstanceId: String, + @Query("limit") limit: Int, + @Query("offset") offset: Int, + ): ApiResponse } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/visa/TangemVisaAuthApi.kt b/core/datasource/src/main/java/com/tangem/datasource/api/visa/TangemVisaAuthApi.kt index 1e200c63bd..b2ed8d19be 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/visa/TangemVisaAuthApi.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/visa/TangemVisaAuthApi.kt @@ -1,5 +1,6 @@ package com.tangem.datasource.api.visa +import com.tangem.datasource.api.common.response.ApiResponse import com.tangem.datasource.api.visa.models.response.GenerateNonceResponse import com.tangem.datasource.api.visa.models.response.JWTResponse import retrofit2.http.Field @@ -27,5 +28,5 @@ interface TangemVisaAuthApi { ): JWTResponse @POST("auth/refresh_token") - suspend fun refreshAccessToken(@Field("refresh_token") refreshToken: String): JWTResponse + suspend fun refreshAccessToken(@Field("refresh_token") refreshToken: String): ApiResponse } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/visa/models/response/VisaCustomerInfo.kt b/core/datasource/src/main/java/com/tangem/datasource/api/visa/models/response/VisaCustomerInfo.kt new file mode 100644 index 0000000000..70d5f6ac94 --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/api/visa/models/response/VisaCustomerInfo.kt @@ -0,0 +1,15 @@ +package com.tangem.datasource.api.visa.models.response + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class VisaCustomerInfo( + @Json(name = "payment_accounts") val paymentAccounts: List, +) { + data class PaymentAccount( + @Json(name = "id") val id: String, + @Json(name = "customer_wallet_address") val customerWalletAddress: String, + @Json(name = "payment_account_address") val paymentAccountAddress: String, + ) +} \ No newline at end of file diff --git a/libs/visa/src/main/kotlin/com/tangem/lib/visa/model/VisaTxHistoryResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/visa/models/response/VisaTxHistoryResponse.kt similarity index 98% rename from libs/visa/src/main/kotlin/com/tangem/lib/visa/model/VisaTxHistoryResponse.kt rename to core/datasource/src/main/java/com/tangem/datasource/api/visa/models/response/VisaTxHistoryResponse.kt index bf722ca7bf..7c4d7d0a22 100644 --- a/libs/visa/src/main/kotlin/com/tangem/lib/visa/model/VisaTxHistoryResponse.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/visa/models/response/VisaTxHistoryResponse.kt @@ -1,4 +1,4 @@ -package com.tangem.lib.visa.model +package com.tangem.datasource.api.visa.models.response import com.squareup.moshi.Json import com.squareup.moshi.JsonClass diff --git a/data/visa/src/debug/kotlin/com/tangem/data/visa/di/ImplementedVisaDataModule.kt b/data/visa/src/debug/kotlin/com/tangem/data/visa/di/ImplementedVisaDataModule.kt deleted file mode 100644 index efb081bdc6..0000000000 --- a/data/visa/src/debug/kotlin/com/tangem/data/visa/di/ImplementedVisaDataModule.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.tangem.data.visa.di - -import com.tangem.data.common.cache.CacheRegistry -import com.tangem.data.visa.DefaultVisaRepository -import com.tangem.data.visa.config.VisaLibLoader -import com.tangem.datasource.api.tangemTech.TangemTechApi -import com.tangem.datasource.local.userwallet.UserWalletsStore -import com.tangem.domain.visa.repository.VisaRepository -import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import dagger.Binds -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -internal interface ImplementedVisaDataModule { - - @Binds - @Singleton - @ImplementedVisaRepository - fun provideVisaRepository(impl: DefaultVisaRepository): VisaRepository -} \ No newline at end of file diff --git a/data/visa/src/main/kotlin/com/tangem/data/visa/DefaultVisaActivationRepository.kt b/data/visa/src/main/kotlin/com/tangem/data/visa/DefaultVisaActivationRepository.kt index 4bb73eee50..b4bb976ce9 100644 --- a/data/visa/src/main/kotlin/com/tangem/data/visa/DefaultVisaActivationRepository.kt +++ b/data/visa/src/main/kotlin/com/tangem/data/visa/DefaultVisaActivationRepository.kt @@ -1,5 +1,6 @@ package com.tangem.data.visa +import com.tangem.data.visa.config.VisaLibLoader import com.tangem.data.visa.converter.AccessCodeDataConverter import com.tangem.data.visa.converter.VisaActivationStatusConverter import com.tangem.datasource.api.common.response.ApiResponseError @@ -28,6 +29,7 @@ internal class DefaultVisaActivationRepository @AssistedInject constructor( private val visaAuthTokenStorage: VisaAuthTokenStorage, private val accessCodeDataConverter: AccessCodeDataConverter, private val visaAuthRepository: VisaAuthRepository, + private val visaLibLoader: VisaLibLoader, ) : VisaActivationRepository { override suspend fun getActivationRemoteState(): VisaActivationRemoteState = withContext(dispatcherProvider.io) { @@ -192,6 +194,10 @@ internal class DefaultVisaActivationRepository @AssistedInject constructor( } } + override suspend fun getPinCodeRsaEncryptionPublicKey(): String { + return visaLibLoader.getOrCreateConfig().rsaPublicKey + } + private suspend fun request(requestBlock: suspend () -> T): T { return runCatching { requestBlock() diff --git a/data/visa/src/debug/kotlin/com/tangem/data/visa/DefaultVisaRepository.kt b/data/visa/src/main/kotlin/com/tangem/data/visa/DefaultVisaRepository.kt similarity index 65% rename from data/visa/src/debug/kotlin/com/tangem/data/visa/DefaultVisaRepository.kt rename to data/visa/src/main/kotlin/com/tangem/data/visa/DefaultVisaRepository.kt index b7ce28f265..6a78abbf06 100644 --- a/data/visa/src/debug/kotlin/com/tangem/data/visa/DefaultVisaRepository.kt +++ b/data/visa/src/main/kotlin/com/tangem/data/visa/DefaultVisaRepository.kt @@ -12,21 +12,18 @@ import com.tangem.common.extensions.toHexString import com.tangem.data.common.cache.CacheRegistry import com.tangem.data.visa.config.VisaLibLoader import com.tangem.data.visa.utils.* -import com.tangem.datasource.api.common.response.ApiResponseError import com.tangem.datasource.api.common.response.getOrThrow -import com.tangem.datasource.api.common.visa.TangemVisaAuthProvider import com.tangem.datasource.api.tangemTech.TangemTechApi +import com.tangem.datasource.api.visa.TangemVisaApi +import com.tangem.datasource.api.visa.models.response.VisaTxHistoryResponse import com.tangem.datasource.local.userwallet.UserWalletsStore import com.tangem.domain.common.util.cardTypesResolver -import com.tangem.domain.common.visa.VisaUtilities -import com.tangem.domain.visa.exception.RefreshTokenExpiredException -import com.tangem.domain.visa.model.* -import com.tangem.domain.visa.repository.VisaAuthRepository +import com.tangem.domain.visa.model.VisaCurrency +import com.tangem.domain.visa.model.VisaTxDetails +import com.tangem.domain.visa.model.VisaTxHistoryItem import com.tangem.domain.visa.repository.VisaRepository import com.tangem.domain.wallets.models.UserWallet import com.tangem.domain.wallets.models.UserWalletId -import com.tangem.lib.visa.api.VisaApi -import com.tangem.lib.visa.model.VisaTxHistoryResponse import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow @@ -35,8 +32,8 @@ import kotlinx.coroutines.withContext import java.math.BigDecimal import javax.inject.Inject import javax.inject.Singleton -import kotlin.jvm.Throws +@Suppress("LongParameterList") @Singleton internal class DefaultVisaRepository @Inject constructor( private val visaLibLoader: VisaLibLoader, @@ -44,8 +41,8 @@ internal class DefaultVisaRepository @Inject constructor( private val cacheRegistry: CacheRegistry, private val userWalletsStore: UserWalletsStore, private val dispatchers: CoroutineDispatcherProvider, - private val visaAuthProvider: TangemVisaAuthProvider, - private val visaAuthRepository: VisaAuthRepository, + private val visaApiRequestMaker: VisaApiRequestMaker, + private val visaApi: TangemVisaApi, ) : VisaRepository { private val currencyFactory by lazy(mode = LazyThreadSafetyMode.NONE) { @@ -65,27 +62,32 @@ internal class DefaultVisaRepository @Inject constructor( override suspend fun getVisaCurrency(userWalletId: UserWalletId, isRefresh: Boolean): VisaCurrency { val address = makeAddress(userWalletId) - fetchVisaCurrencyIfExpired(address, isRefresh) + fetchVisaCurrencyIfExpired(userWalletId, address, isRefresh) return requireNotNull(fetchedCurrencies.value[address]) { "Unable to find VISA currency for $address" } } - private suspend fun fetchVisaCurrencyIfExpired(address: String, isRefresh: Boolean) { + private suspend fun fetchVisaCurrencyIfExpired(userWalletId: UserWalletId, address: String, isRefresh: Boolean) { cacheRegistry.invokeOnExpire( key = getVisaCurrencyKey(address), skipCache = isRefresh, - block = { fetchVisaCurrency(address) }, + block = { fetchVisaCurrency(userWalletId, address) }, ) } - private suspend fun fetchVisaCurrency(address: String) { + private suspend fun fetchVisaCurrency(userWalletId: UserWalletId, address: String) { val contractInfoProvider = visaLibLoader.getOrCreateProvider() parZip( dispatchers.io, - { contractInfoProvider.getContractInfo(address) }, + { + contractInfoProvider.getContractInfo( + walletAddress = address, + paymentAccountAddress = getPaymentAccountAddress(userWalletId), + ) + }, { getFiatRate() }, { contractInfo, fiatRate -> fetchedCurrencies.update { value -> @@ -104,7 +106,7 @@ internal class DefaultVisaRepository @Inject constructor( ): Flow> { val userWallet = findVisaUserWallet(userWalletId) val cardPubKey = getCardPubKey(userWallet) - val api = visaLibLoader.getOrCreateApi() + val pager = Pager( config = PagingConfig( pageSize = pageSize, @@ -121,7 +123,7 @@ internal class DefaultVisaRepository @Inject constructor( cacheRegistry = cacheRegistry, fetchedItems = fetchedHistoryItems, dispatchers = dispatchers, - requestTxHistory = { offset, pageSize -> getTxHistory(api, userWalletId, offset, pageSize) }, + requestTxHistory = { offset, pageSize -> getTxHistory(userWalletId, offset, pageSize) }, ) }, ) @@ -145,22 +147,31 @@ internal class DefaultVisaRepository @Inject constructor( } } - private suspend fun getTxHistory( - api: VisaApi, - userWalletId: UserWalletId, - offset: Int, - pageSize: Int, - ): VisaTxHistoryResponse = withContext(dispatchers.io) { + private suspend fun getPaymentAccountAddress(userWalletId: UserWalletId): String? = runCatching { val userWallet = findVisaUserWallet(userWalletId) - val cardPubKey = getCardPubKey(userWallet) - request(userWalletId = userWalletId) { - api.getTxHistory( - authorizationHeader = visaAuthProvider.getAuthHeader(userWallet.cardId), - cardPublicKey = cardPubKey, + val customerInfo = visaApiRequestMaker.request(userWalletId) { authHeader, _ -> + visaApi.getCustomerInfo( + authHeader = authHeader, + cardId = userWallet.scanResponse.card.cardId, + ) + } + + // TODO select correct account when multiple accounts are available (will be implemented when backend is ready) + customerInfo.paymentAccounts.firstOrNull()?.paymentAccountAddress + }.getOrNull() + + private suspend fun getTxHistory(userWalletId: UserWalletId, offset: Int, pageSize: Int): VisaTxHistoryResponse { + return visaApiRequestMaker.request( + userWalletId = userWalletId, + ) { authHeader, accessCodeData -> + visaApi.getTxHistory( + authHeader = authHeader, + customerId = accessCodeData.customerId, + productInstanceId = accessCodeData.productInstanceId, limit = pageSize, offset = offset, - ).getOrThrow() + ) } } @@ -217,56 +228,4 @@ internal class DefaultVisaRepository @Inject constructor( private fun getVisaCurrencyKey(address: String): String { return "visa_currency_$address" } - - private suspend fun request( - userWalletId: UserWalletId, - requestBlock: suspend () -> T, - ): T { - return runCatching { - requestBlock() - }.getOrElse { responseError -> - if (responseError !is ApiResponseError.HttpException || - responseError.code != ApiResponseError.HttpException.Code.UNAUTHORIZED - ) { - throw responseError - } - - val authTokens = getAuthTokens(userWalletId) - val newTokens = runCatching { - visaAuthRepository.refreshAccessTokens(authTokens.refreshToken) - }.getOrElse { - if (it is ApiResponseError.HttpException && - it.code == ApiResponseError.HttpException.Code.UNAUTHORIZED - ) { - userWalletsStore.update(userWalletId) { userWallet -> - userWallet.copy( - scanResponse = userWallet.scanResponse.copy( - visaCardActivationStatus = VisaCardActivationStatus.RefreshTokenExpired - ) - ) - } - } - throw RefreshTokenExpiredException() - } - - userWalletsStore.update(userWalletId) { userWallet -> - userWallet.copy( - scanResponse = userWallet.scanResponse.copy( - visaCardActivationStatus = VisaCardActivationStatus.Activated( - visaAuthTokens = newTokens - ) - ) - ) - } - - requestBlock() - } - } - - @Throws - private suspend fun getAuthTokens(userWalletId: UserWalletId): VisaAuthTokens { - val userWallet = findVisaUserWallet(userWalletId) - val status = userWallet.scanResponse.visaCardActivationStatus ?: error("Visa card activation status not found") - return (status as? VisaCardActivationStatus.Activated)?.visaAuthTokens ?: error("Visa card is not activated") - } } \ No newline at end of file diff --git a/data/visa/src/main/kotlin/com/tangem/data/visa/MockVisaActivationRepository.kt b/data/visa/src/main/kotlin/com/tangem/data/visa/MockVisaActivationRepository.kt index 8ebb4ae1b4..ed49e8187b 100644 --- a/data/visa/src/main/kotlin/com/tangem/data/visa/MockVisaActivationRepository.kt +++ b/data/visa/src/main/kotlin/com/tangem/data/visa/MockVisaActivationRepository.kt @@ -45,6 +45,10 @@ class MockVisaActivationRepository @AssistedInject constructor( override suspend fun sendPinCode(pinCode: VisaEncryptedPinCode) {} + override suspend fun getPinCodeRsaEncryptionPublicKey(): String { + return CryptoUtils.generateRandomBytes(length = 32).toHexString() + } + @AssistedFactory interface Factory : VisaActivationRepository.Factory { override fun create(cardId: VisaCardId): MockVisaActivationRepository diff --git a/data/visa/src/main/kotlin/com/tangem/data/visa/DummyVisaRepository.kt b/data/visa/src/main/kotlin/com/tangem/data/visa/MockVisaRepository.kt similarity index 89% rename from data/visa/src/main/kotlin/com/tangem/data/visa/DummyVisaRepository.kt rename to data/visa/src/main/kotlin/com/tangem/data/visa/MockVisaRepository.kt index e965d71e93..87402d0554 100644 --- a/data/visa/src/main/kotlin/com/tangem/data/visa/DummyVisaRepository.kt +++ b/data/visa/src/main/kotlin/com/tangem/data/visa/MockVisaRepository.kt @@ -7,8 +7,9 @@ import com.tangem.domain.visa.model.VisaTxHistoryItem import com.tangem.domain.visa.repository.VisaRepository import com.tangem.domain.wallets.models.UserWalletId import kotlinx.coroutines.flow.Flow +import javax.inject.Inject -internal class DummyVisaRepository : VisaRepository { +internal class MockVisaRepository @Inject constructor() : VisaRepository { override suspend fun getVisaCurrency(userWalletId: UserWalletId, isRefresh: Boolean): VisaCurrency { TODO("Not implemented for this build type") diff --git a/data/visa/src/debug/kotlin/com/tangem/data/visa/config/VisaConfig.kt b/data/visa/src/main/kotlin/com/tangem/data/visa/config/VisaConfig.kt similarity index 92% rename from data/visa/src/debug/kotlin/com/tangem/data/visa/config/VisaConfig.kt rename to data/visa/src/main/kotlin/com/tangem/data/visa/config/VisaConfig.kt index 187f4ca9e6..2dd3b5566c 100644 --- a/data/visa/src/debug/kotlin/com/tangem/data/visa/config/VisaConfig.kt +++ b/data/visa/src/main/kotlin/com/tangem/data/visa/config/VisaConfig.kt @@ -11,6 +11,8 @@ internal data class VisaConfig( val mainnet: Addresses, @Json(name = "txHistoryAPIAdditionalHeaders") val header: Header, + @Json(name = "rsaPublicKey") + val rsaPublicKey: String, ) { @JsonClass(generateAdapter = true) diff --git a/data/visa/src/debug/kotlin/com/tangem/data/visa/config/VisaLibLoader.kt b/data/visa/src/main/kotlin/com/tangem/data/visa/config/VisaLibLoader.kt similarity index 68% rename from data/visa/src/debug/kotlin/com/tangem/data/visa/config/VisaLibLoader.kt rename to data/visa/src/main/kotlin/com/tangem/data/visa/config/VisaLibLoader.kt index e5062cf662..471f56ea4e 100644 --- a/data/visa/src/debug/kotlin/com/tangem/data/visa/config/VisaLibLoader.kt +++ b/data/visa/src/main/kotlin/com/tangem/data/visa/config/VisaLibLoader.kt @@ -1,13 +1,9 @@ package com.tangem.data.visa.config -import com.squareup.moshi.Moshi import com.tangem.data.visa.BuildConfig import com.tangem.data.visa.utils.VisaConstants import com.tangem.datasource.asset.loader.AssetLoader -import com.tangem.datasource.di.NetworkMoshi import com.tangem.lib.visa.VisaContractInfoProvider -import com.tangem.lib.visa.api.VisaApi -import com.tangem.lib.visa.api.VisaApiBuilder import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock @@ -15,21 +11,19 @@ import javax.inject.Inject internal class VisaLibLoader @Inject constructor( private val assetLoader: AssetLoader, - @NetworkMoshi private val moshi: Moshi, private val dispatchers: CoroutineDispatcherProvider, ) { - private val createMutex = Mutex() + private val createMutex2 = Mutex() private var config: VisaConfig? = null private var provider: VisaContractInfoProvider? = null - private var api: VisaApi? = null + + suspend fun getOrCreateConfig(): VisaConfig = config ?: getOrLoadConfig() suspend fun getOrCreateProvider(): VisaContractInfoProvider = provider ?: createProvider() - suspend fun getOrCreateApi(): VisaApi = api ?: createApi() - private suspend fun createProvider(): VisaContractInfoProvider = createMutex.withLock { val config = getOrLoadConfig() @@ -54,24 +48,7 @@ internal class VisaLibLoader @Inject constructor( } } - private suspend fun createApi(): VisaApi = createMutex.withLock { - val config = getOrLoadConfig() - - api = VisaApiBuilder( - useDevApi = VisaConstants.USE_TEST_ENV, - isNetworkLoggingEnabled = BuildConfig.LOG_ENABLED, - moshi = moshi, - headers = mapOf( - X_ASN_HEADER_NAME to config.header.xAsn, - ), - ).build() - - return requireNotNull(api) { - "Visa API is not created" - } - } - - private suspend fun getOrLoadConfig(): VisaConfig { + private suspend fun getOrLoadConfig(): VisaConfig = createMutex2.withLock { config = assetLoader.load(VISA_CONFIG_FILE_NAME) return requireNotNull(config) { @@ -81,6 +58,5 @@ internal class VisaLibLoader @Inject constructor( companion object { private const val VISA_CONFIG_FILE_NAME = "tangem-app-config/visa_config" - private const val X_ASN_HEADER_NAME = "x-asn" } } \ No newline at end of file diff --git a/data/visa/src/main/kotlin/com/tangem/data/visa/di/ImplementedVisaRepository.kt b/data/visa/src/main/kotlin/com/tangem/data/visa/di/ImplementedVisaRepository.kt deleted file mode 100644 index 074af6e72d..0000000000 --- a/data/visa/src/main/kotlin/com/tangem/data/visa/di/ImplementedVisaRepository.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.tangem.data.visa.di - -import javax.inject.Qualifier - -@Qualifier -internal annotation class ImplementedVisaRepository \ No newline at end of file diff --git a/data/visa/src/main/kotlin/com/tangem/data/visa/di/ImplementedVisaRepositoryModule.kt b/data/visa/src/main/kotlin/com/tangem/data/visa/di/ImplementedVisaRepositoryModule.kt deleted file mode 100644 index 96de38914e..0000000000 --- a/data/visa/src/main/kotlin/com/tangem/data/visa/di/ImplementedVisaRepositoryModule.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.tangem.data.visa.di - -import com.tangem.domain.visa.repository.VisaRepository -import dagger.BindsOptionalOf -import dagger.Module -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent - -@Module -@InstallIn(SingletonComponent::class) -internal interface ImplementedVisaRepositoryModule { - - @BindsOptionalOf - @ImplementedVisaRepository - fun bindImplementedVisaRepository(): VisaRepository -} \ No newline at end of file diff --git a/data/visa/src/main/kotlin/com/tangem/data/visa/di/VisaDataModule.kt b/data/visa/src/main/kotlin/com/tangem/data/visa/di/VisaDataModule.kt index 5cfa0296bb..e1cc459371 100644 --- a/data/visa/src/main/kotlin/com/tangem/data/visa/di/VisaDataModule.kt +++ b/data/visa/src/main/kotlin/com/tangem/data/visa/di/VisaDataModule.kt @@ -1,36 +1,20 @@ package com.tangem.data.visa.di import com.tangem.data.visa.DefaultVisaAuthRepository -import com.tangem.data.visa.DummyVisaRepository +import com.tangem.data.visa.MockVisaRepository import com.tangem.data.visa.MockVisaActivationRepository import com.tangem.domain.visa.repository.VisaActivationRepository import com.tangem.domain.visa.repository.VisaAuthRepository import com.tangem.domain.visa.repository.VisaRepository import dagger.Binds import dagger.Module -import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent -import java.util.Optional import javax.inject.Singleton -import kotlin.jvm.optionals.getOrNull @Module @InstallIn(SingletonComponent::class) -internal object VisaDataModule { - - @Provides - @Singleton - fun provideVisaRepository( - @ImplementedVisaRepository implementedVisaRepository: Optional, - ): VisaRepository { - return implementedVisaRepository.getOrNull() ?: DummyVisaRepository() - } -} - -@Module -@InstallIn(SingletonComponent::class) -internal interface VisaDataBindsModule { +internal interface VisaDataModule { @Binds @Singleton @@ -48,4 +32,11 @@ internal interface VisaDataBindsModule { fun bindVisaActivationRepositoryFactory( repository: MockVisaActivationRepository.Factory, ): VisaActivationRepository.Factory + + // @Binds + // fun bindVisaRepository(repository: DefaultVisaRepository): VisaRepository + + // Mocked + @Binds + fun bindVisaRepository(repository: MockVisaRepository): VisaRepository } \ No newline at end of file diff --git a/data/visa/src/debug/kotlin/com/tangem/data/visa/utils/CurrencyUtils.kt b/data/visa/src/main/kotlin/com/tangem/data/visa/utils/CurrencyUtils.kt similarity index 100% rename from data/visa/src/debug/kotlin/com/tangem/data/visa/utils/CurrencyUtils.kt rename to data/visa/src/main/kotlin/com/tangem/data/visa/utils/CurrencyUtils.kt diff --git a/data/visa/src/main/kotlin/com/tangem/data/visa/utils/VisaApiRequestMaker.kt b/data/visa/src/main/kotlin/com/tangem/data/visa/utils/VisaApiRequestMaker.kt new file mode 100644 index 0000000000..d06d1fb0de --- /dev/null +++ b/data/visa/src/main/kotlin/com/tangem/data/visa/utils/VisaApiRequestMaker.kt @@ -0,0 +1,107 @@ +package com.tangem.data.visa.utils + +import com.tangem.data.visa.converter.AccessCodeDataConverter +import com.tangem.data.visa.model.AccessCodeData +import com.tangem.datasource.api.common.response.ApiResponse +import com.tangem.datasource.api.common.response.ApiResponseError +import com.tangem.datasource.api.common.response.getOrThrow +import com.tangem.datasource.api.visa.TangemVisaAuthApi +import com.tangem.datasource.local.userwallet.UserWalletsStore +import com.tangem.domain.common.util.cardTypesResolver +import com.tangem.domain.visa.exception.RefreshTokenExpiredException +import com.tangem.domain.visa.model.VisaAuthTokens +import com.tangem.domain.visa.model.VisaCardActivationStatus +import com.tangem.domain.visa.model.getAuthHeader +import com.tangem.domain.wallets.models.UserWallet +import com.tangem.domain.wallets.models.UserWalletId +import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import kotlinx.coroutines.withContext +import javax.inject.Inject +import kotlin.jvm.Throws + +typealias VisaAuthorizationHeader = String + +internal class VisaApiRequestMaker @Inject constructor( + private val userWalletsStore: UserWalletsStore, + private val visaAuthApi: TangemVisaAuthApi, + private val accessCodeDataConverter: AccessCodeDataConverter, + private val dispatcherProvider: CoroutineDispatcherProvider, +) { + suspend fun request( + userWalletId: UserWalletId, + requestBlock: suspend (header: VisaAuthorizationHeader, accessCodeData: AccessCodeData) -> ApiResponse, + ): T = withContext(dispatcherProvider.io) { + val authTokens = getAuthTokens(userWalletId) + val authHeader = authTokens.getAuthHeader() + val accessCodeData = accessCodeDataConverter.convert(authTokens) + + runCatching { + requestBlock(authHeader, accessCodeData).getOrThrow() + }.getOrElse { responseError -> + if (responseError !is ApiResponseError.HttpException || + responseError.code != ApiResponseError.HttpException.Code.UNAUTHORIZED + ) { + throw responseError + } + + val newTokens = runCatching { + refreshAccessTokens(authTokens.refreshToken) + }.getOrElse { + if (it is ApiResponseError.HttpException && + it.code == ApiResponseError.HttpException.Code.UNAUTHORIZED + ) { + userWalletsStore.update(userWalletId) { userWallet -> + userWallet.copy( + scanResponse = userWallet.scanResponse.copy( + visaCardActivationStatus = VisaCardActivationStatus.RefreshTokenExpired, + ), + ) + } + } + throw RefreshTokenExpiredException() + } + + userWalletsStore.update(userWalletId) { userWallet -> + userWallet.copy( + scanResponse = userWallet.scanResponse.copy( + visaCardActivationStatus = VisaCardActivationStatus.Activated( + visaAuthTokens = newTokens, + ), + ), + ) + } + + val newAuthHeader = newTokens.getAuthHeader() + val newAccessCodeData = accessCodeDataConverter.convert(newTokens) + + requestBlock(newAuthHeader, newAccessCodeData).getOrThrow() + } + } + + private suspend fun refreshAccessTokens(refreshToken: VisaAuthTokens.RefreshToken): VisaAuthTokens { + val result = visaAuthApi.refreshAccessToken(refreshToken.value).getOrThrow() + + return VisaAuthTokens( + accessToken = result.accessToken, + refreshToken = VisaAuthTokens.RefreshToken(result.refreshToken), + ) + } + + @Throws + private suspend fun getAuthTokens(userWalletId: UserWalletId): VisaAuthTokens { + val userWallet = findVisaUserWallet(userWalletId) + val status = userWallet.scanResponse.visaCardActivationStatus ?: error("Visa card activation status not found") + return (status as? VisaCardActivationStatus.Activated)?.visaAuthTokens ?: error("Visa card is not activated") + } + + private suspend fun findVisaUserWallet(userWalletId: UserWalletId): UserWallet { + val userWallet = requireNotNull(userWalletsStore.getSyncOrNull(userWalletId)) { + "No user wallet found: $userWalletId" + } + if (!userWallet.scanResponse.cardTypesResolver.isVisaWallet()) { + error("VISA wallet required: $userWalletId") + } + + return userWallet + } +} \ No newline at end of file diff --git a/data/visa/src/debug/kotlin/com/tangem/data/visa/utils/VisaConstants.kt b/data/visa/src/main/kotlin/com/tangem/data/visa/utils/VisaConstants.kt similarity index 86% rename from data/visa/src/debug/kotlin/com/tangem/data/visa/utils/VisaConstants.kt rename to data/visa/src/main/kotlin/com/tangem/data/visa/utils/VisaConstants.kt index 27cd336588..1a6f0a142a 100644 --- a/data/visa/src/debug/kotlin/com/tangem/data/visa/utils/VisaConstants.kt +++ b/data/visa/src/main/kotlin/com/tangem/data/visa/utils/VisaConstants.kt @@ -15,9 +15,9 @@ internal object VisaConstants { ) /* - * Must be `false` in production - * Don't forget to change CardTypesResolver.isVisaWallet - * */ + * Must be `false` in production + * Don't forget to change CardTypesResolver.isVisaWallet + * */ const val IS_DEMO_MODE_ENABLED = false const val USE_TEST_ENV = true @@ -40,5 +40,7 @@ internal fun getDemoAddress(): String { internal fun getDemoPublicKey(): String { return if (VisaConstants.USE_TEST_ENV) { VisaConstants.DEMO_TESTNET_PUBLIC_KEY - } else VisaConstants.DEMO_MAINNET_PUBLIC_KEY + } else { + VisaConstants.DEMO_MAINNET_PUBLIC_KEY + } } \ No newline at end of file diff --git a/data/visa/src/debug/kotlin/com/tangem/data/visa/utils/VisaCurrencyFactory.kt b/data/visa/src/main/kotlin/com/tangem/data/visa/utils/VisaCurrencyFactory.kt similarity index 100% rename from data/visa/src/debug/kotlin/com/tangem/data/visa/utils/VisaCurrencyFactory.kt rename to data/visa/src/main/kotlin/com/tangem/data/visa/utils/VisaCurrencyFactory.kt diff --git a/data/visa/src/debug/kotlin/com/tangem/data/visa/utils/VisaTxDetailsFactory.kt b/data/visa/src/main/kotlin/com/tangem/data/visa/utils/VisaTxDetailsFactory.kt similarity index 97% rename from data/visa/src/debug/kotlin/com/tangem/data/visa/utils/VisaTxDetailsFactory.kt rename to data/visa/src/main/kotlin/com/tangem/data/visa/utils/VisaTxDetailsFactory.kt index 5108e0387e..c69adf5664 100644 --- a/data/visa/src/debug/kotlin/com/tangem/data/visa/utils/VisaTxDetailsFactory.kt +++ b/data/visa/src/main/kotlin/com/tangem/data/visa/utils/VisaTxDetailsFactory.kt @@ -2,8 +2,8 @@ package com.tangem.data.visa.utils import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.externallinkprovider.TxExploreState +import com.tangem.datasource.api.visa.models.response.VisaTxHistoryResponse import com.tangem.domain.visa.model.VisaTxDetails -import com.tangem.lib.visa.model.VisaTxHistoryResponse internal class VisaTxDetailsFactory { diff --git a/data/visa/src/debug/kotlin/com/tangem/data/visa/utils/VisaTxHistoryItemFactory.kt b/data/visa/src/main/kotlin/com/tangem/data/visa/utils/VisaTxHistoryItemFactory.kt similarity index 89% rename from data/visa/src/debug/kotlin/com/tangem/data/visa/utils/VisaTxHistoryItemFactory.kt rename to data/visa/src/main/kotlin/com/tangem/data/visa/utils/VisaTxHistoryItemFactory.kt index 86d1439068..75a8c4eefe 100644 --- a/data/visa/src/debug/kotlin/com/tangem/data/visa/utils/VisaTxHistoryItemFactory.kt +++ b/data/visa/src/main/kotlin/com/tangem/data/visa/utils/VisaTxHistoryItemFactory.kt @@ -1,7 +1,7 @@ package com.tangem.data.visa.utils +import com.tangem.datasource.api.visa.models.response.VisaTxHistoryResponse import com.tangem.domain.visa.model.VisaTxHistoryItem -import com.tangem.lib.visa.model.VisaTxHistoryResponse internal class VisaTxHistoryItemFactory { diff --git a/data/visa/src/debug/kotlin/com/tangem/data/visa/utils/VisaTxHistoryPagingSource.kt b/data/visa/src/main/kotlin/com/tangem/data/visa/utils/VisaTxHistoryPagingSource.kt similarity index 92% rename from data/visa/src/debug/kotlin/com/tangem/data/visa/utils/VisaTxHistoryPagingSource.kt rename to data/visa/src/main/kotlin/com/tangem/data/visa/utils/VisaTxHistoryPagingSource.kt index e233435e55..4393d4f372 100644 --- a/data/visa/src/debug/kotlin/com/tangem/data/visa/utils/VisaTxHistoryPagingSource.kt +++ b/data/visa/src/main/kotlin/com/tangem/data/visa/utils/VisaTxHistoryPagingSource.kt @@ -3,13 +3,9 @@ package com.tangem.data.visa.utils import androidx.paging.PagingSource import androidx.paging.PagingState import com.tangem.data.common.cache.CacheRegistry -import com.tangem.datasource.api.common.response.ApiResponseError -import com.tangem.datasource.api.common.response.getOrThrow -import com.tangem.datasource.api.common.visa.TangemVisaAuthProvider +import com.tangem.datasource.api.visa.models.response.VisaTxHistoryResponse import com.tangem.domain.visa.model.VisaTxHistoryItem import com.tangem.domain.wallets.models.UserWallet -import com.tangem.lib.visa.api.VisaApi -import com.tangem.lib.visa.model.VisaTxHistoryResponse import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.update diff --git a/domain/visa/src/main/kotlin/com/tangem/domain/visa/SetVisaPinCodeUseCase.kt b/domain/visa/src/main/kotlin/com/tangem/domain/visa/SetVisaPinCodeUseCase.kt index 7b05cf26b8..6fda7af7df 100644 --- a/domain/visa/src/main/kotlin/com/tangem/domain/visa/SetVisaPinCodeUseCase.kt +++ b/domain/visa/src/main/kotlin/com/tangem/domain/visa/SetVisaPinCodeUseCase.kt @@ -18,8 +18,6 @@ import javax.crypto.spec.SecretKeySpec private const val KEY_SIZE = 256 -private const val RSA_PUB_KEY = "TODO" // TODO add RSA public key [REDACTED_TASK_KEY] - class SetVisaPinCodeUseCase( private val visaActivationRepositoryFactory: VisaActivationRepository.Factory, ) { @@ -30,9 +28,10 @@ class SetVisaPinCodeUseCase( pinCode: String, ): Either = Either.catch { val visaActivationRepository = visaActivationRepositoryFactory.create(visaCardId) + val rsaPublicKey = visaActivationRepository.getPinCodeRsaEncryptionPublicKey() val sessionKey = generateSessionKey() - val sessionId = getSessionId(RSA_PUB_KEY, sessionKey) + val sessionId = getSessionId(rsaPublicKey, sessionKey) val secureRandom = SecureRandom() val iv = ByteArray(size = 16) diff --git a/domain/visa/src/main/kotlin/com/tangem/domain/visa/repository/VisaActivationRepository.kt b/domain/visa/src/main/kotlin/com/tangem/domain/visa/repository/VisaActivationRepository.kt index 5f7959f423..f6d451fb7b 100644 --- a/domain/visa/src/main/kotlin/com/tangem/domain/visa/repository/VisaActivationRepository.kt +++ b/domain/visa/src/main/kotlin/com/tangem/domain/visa/repository/VisaActivationRepository.kt @@ -20,6 +20,8 @@ interface VisaActivationRepository { suspend fun sendPinCode(pinCode: VisaEncryptedPinCode) + suspend fun getPinCodeRsaEncryptionPublicKey(): String + interface Factory { fun create(cardId: VisaCardId): VisaActivationRepository } diff --git a/libs/visa/src/main/kotlin/com/tangem/lib/visa/DefaultVisaContractInfoProvider.kt b/libs/visa/src/main/kotlin/com/tangem/lib/visa/DefaultVisaContractInfoProvider.kt index 2265f6258f..395904554e 100644 --- a/libs/visa/src/main/kotlin/com/tangem/lib/visa/DefaultVisaContractInfoProvider.kt +++ b/libs/visa/src/main/kotlin/com/tangem/lib/visa/DefaultVisaContractInfoProvider.kt @@ -20,27 +20,38 @@ internal class DefaultVisaContractInfoProvider( private val dispatchers: CoroutineDispatcherProvider, ) : VisaContractInfoProvider { - override suspend fun getContractInfo(walletAddress: String): VisaContractInfo { + override suspend fun getContractInfo(walletAddress: String, paymentAccountAddress: String?): VisaContractInfo { return parZip( dispatchers.io, - { loadPaymentAccount(walletAddress) }, + { loadPaymentAccount(walletAddress = walletAddress, paymentAccountAddress = paymentAccountAddress) }, { loadPaymentTokenInfo() }, { paymentAccount, paymentToken -> - fetchBalancesAndLimits(paymentAccount, paymentToken) + fetchBalancesAndLimits( + paymentAccount = paymentAccount, + paymentToken = paymentToken, + walletAddress = walletAddress, + ) }, ) } - private fun loadPaymentAccount(walletAddress: String): TangemPaymentAccount { + private fun loadPaymentAccount(walletAddress: String, paymentAccountAddress: String?): TangemPaymentAccount { + return TangemPaymentAccount.load( + /* contractAddress = */ paymentAccountAddress ?: getPaymentAccountAddressFromRegistry(walletAddress), + /* web3j = */ web3j, + /* transactionManager = */ transactionManager, + /* contractGasProvider = */ gasProvider, + ) + } + + private fun getPaymentAccountAddressFromRegistry(walletAddress: String): String { val paymentAccountRegistry = TangemPaymentAccountRegistry.load( /* contractAddress = */ paymentAccountRegistryAddress, /* web3j = */ web3j, /* transactionManager = */ transactionManager, /* contractGasProvider = */ gasProvider, ) - val paymentAccountAddress = paymentAccountRegistry.paymentAccountByCard(walletAddress).send() - - return TangemPaymentAccount.load(paymentAccountAddress, web3j, transactionManager, gasProvider) + return paymentAccountRegistry.paymentAccountByCard(walletAddress).send() } private fun loadPaymentTokenInfo(): PaymentTokenInfo { @@ -63,11 +74,12 @@ internal class DefaultVisaContractInfoProvider( private suspend fun fetchBalancesAndLimits( paymentAccount: TangemPaymentAccount, paymentToken: PaymentTokenInfo, + walletAddress: String, ): VisaContractInfo = parZip( dispatchers.io, { fetchToken(paymentAccount) }, { fetchBalances(paymentAccount, paymentToken) }, - { fetchLimits(paymentAccount, paymentToken) }, + { fetchLimits(paymentAccount, paymentToken, walletAddress) }, { token, balances, (oldLimit, newLimit, changeDate) -> VisaContractInfo(token, balances, oldLimit, newLimit, changeDate) }, @@ -123,19 +135,15 @@ internal class DefaultVisaContractInfoProvider( private fun fetchLimits( paymentAccount: TangemPaymentAccount, paymentToken: PaymentTokenInfo, + walletAddress: String, ): Triple { - TODO() // TODO: [REDACTED_TASK_KEY] - // val ( - // oldLimit, - // newLimit, - // changeDateSeconds, - // ) = paymentAccount.cards("").send().component5() - // - // return Triple( - // first = getLimits(oldLimit, paymentToken), - // second = getLimits(newLimit, paymentToken), - // third = changeDateSeconds.toInstant(), - // ) + val limits = paymentAccount.cards(walletAddress).send().component5() + + return Triple( + first = getLimits(limits.oldValue, paymentToken), + second = getLimits(limits.newValue, paymentToken), + third = limits.changeTimestamp.toInstant(), + ) } @Suppress("UnusedPrivateMember") diff --git a/libs/visa/src/main/kotlin/com/tangem/lib/visa/VisaContractInfoProvider.kt b/libs/visa/src/main/kotlin/com/tangem/lib/visa/VisaContractInfoProvider.kt index 4696b698fb..4587bfabf1 100644 --- a/libs/visa/src/main/kotlin/com/tangem/lib/visa/VisaContractInfoProvider.kt +++ b/libs/visa/src/main/kotlin/com/tangem/lib/visa/VisaContractInfoProvider.kt @@ -21,7 +21,14 @@ import java.util.concurrent.TimeUnit interface VisaContractInfoProvider { - suspend fun getContractInfo(walletAddress: String): VisaContractInfo + /** + * Fetches Visa contract info for the given wallet address. + * + * @param walletAddress Wallet address to fetch contract info for. + * @param paymentAccountAddress Payment account address to fetch data from. If null, + * it will be fetched from the registry. + */ + suspend fun getContractInfo(walletAddress: String, paymentAccountAddress: String?): VisaContractInfo class Builder( private val useTestnetRpc: Boolean, diff --git a/libs/visa/src/main/kotlin/com/tangem/lib/visa/api/VisaApi.kt b/libs/visa/src/main/kotlin/com/tangem/lib/visa/api/VisaApi.kt deleted file mode 100644 index 106ced7a60..0000000000 --- a/libs/visa/src/main/kotlin/com/tangem/lib/visa/api/VisaApi.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.tangem.lib.visa.api - -import com.tangem.datasource.api.common.response.ApiResponse -import com.tangem.lib.visa.model.VisaTxHistoryResponse -import retrofit2.http.GET -import retrofit2.http.Header -import retrofit2.http.Query - -interface VisaApi { - - @GET("transaction") - suspend fun getTxHistory( - @Header("Authorization") authorizationHeader: String, - @Query("card_public_key") cardPublicKey: String, - @Query("limit") limit: Int, - @Query("offset") offset: Int, - ): ApiResponse -} \ No newline at end of file diff --git a/libs/visa/src/main/kotlin/com/tangem/lib/visa/api/VisaApiBuilder.kt b/libs/visa/src/main/kotlin/com/tangem/lib/visa/api/VisaApiBuilder.kt deleted file mode 100644 index ef1a99dd5f..0000000000 --- a/libs/visa/src/main/kotlin/com/tangem/lib/visa/api/VisaApiBuilder.kt +++ /dev/null @@ -1,72 +0,0 @@ -package com.tangem.lib.visa.api - -import android.util.Log -import com.ihsanbal.logging.Level -import com.ihsanbal.logging.LoggingInterceptor -import com.squareup.moshi.Moshi -import com.tangem.datasource.api.common.response.ApiResponseCallAdapterFactory -import com.tangem.lib.visa.utils.Constants -import com.tangem.lib.visa.utils.Constants.NETWORK_LOGS_TAG -import okhttp3.Interceptor -import okhttp3.OkHttpClient -import retrofit2.Retrofit -import retrofit2.converter.moshi.MoshiConverterFactory -import java.util.concurrent.TimeUnit - -class VisaApiBuilder( - private val useDevApi: Boolean, - private val isNetworkLoggingEnabled: Boolean, - private val moshi: Moshi, - private val headers: Map, - private val networkTimeoutSeconds: Long = Constants.NETWORK_TIMEOUT_SECONDS, -) { - - fun build(): VisaApi { - val okHttpClient = createOkHttpClient() - val retrofit = createRetrofit(okHttpClient) - return retrofit.create(VisaApi::class.java) - } - - private fun createOkHttpClient(): OkHttpClient { - val builder = OkHttpClient.Builder().apply { - connectTimeout(networkTimeoutSeconds, TimeUnit.SECONDS) - readTimeout(networkTimeoutSeconds, TimeUnit.SECONDS) - writeTimeout(networkTimeoutSeconds, TimeUnit.SECONDS) - - if (isNetworkLoggingEnabled) { - addInterceptor(createNetworkLoggingInterceptor()) - } - - if (headers.isNotEmpty()) { - addInterceptor { chain -> - val request = chain.request().newBuilder().apply { - headers.forEach { (key, value) -> addHeader(key, value) } - }.build() - - chain.proceed(request) - } - } - } - - return builder.build() - } - - private fun createRetrofit(okHttpClient: OkHttpClient): Retrofit { - val baseUrl = if (useDevApi) Constants.VISA_API_DEV_URL else Constants.VISA_API_PROD_URL - - return Retrofit.Builder() - .addConverterFactory(MoshiConverterFactory.create(moshi)) - .addCallAdapterFactory(ApiResponseCallAdapterFactory.create()) - .baseUrl(baseUrl) - .client(okHttpClient) - .build() - } -} - -private fun createNetworkLoggingInterceptor(): Interceptor { - return LoggingInterceptor.Builder() - .setLevel(Level.BODY) - .log(Log.VERBOSE) - .tag(NETWORK_LOGS_TAG) - .build() -} \ No newline at end of file From b2d47a56a2e65c9be90f54bc7d7c4f90f214bd1f Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 21 Feb 2025 15:45:53 +0300 Subject: [PATCH 22/33] Updated on 2026-08-14 --- .../com/tangem/data/visa/config/VisaLibLoader.kt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/data/visa/src/main/kotlin/com/tangem/data/visa/config/VisaLibLoader.kt b/data/visa/src/main/kotlin/com/tangem/data/visa/config/VisaLibLoader.kt index 471f56ea4e..f8935ef774 100644 --- a/data/visa/src/main/kotlin/com/tangem/data/visa/config/VisaLibLoader.kt +++ b/data/visa/src/main/kotlin/com/tangem/data/visa/config/VisaLibLoader.kt @@ -16,8 +16,10 @@ internal class VisaLibLoader @Inject constructor( private val createMutex = Mutex() private val createMutex2 = Mutex() + @Volatile private var config: VisaConfig? = null + @Volatile private var provider: VisaContractInfoProvider? = null suspend fun getOrCreateConfig(): VisaConfig = config ?: getOrLoadConfig() @@ -25,6 +27,8 @@ internal class VisaLibLoader @Inject constructor( suspend fun getOrCreateProvider(): VisaContractInfoProvider = provider ?: createProvider() private suspend fun createProvider(): VisaContractInfoProvider = createMutex.withLock { + if (provider != null) return@withLock requireNotNull(provider) + val config = getOrLoadConfig() provider = VisaContractInfoProvider.Builder( @@ -49,10 +53,12 @@ internal class VisaLibLoader @Inject constructor( } private suspend fun getOrLoadConfig(): VisaConfig = createMutex2.withLock { + if (config != null) return@withLock requireNotNull(config) + config = assetLoader.load(VISA_CONFIG_FILE_NAME) - return requireNotNull(config) { - "Visa config is not found" + return@withLock requireNotNull(config) { + "Visa config is not loaded" } } From dd60ff7542c3ee3c222375561c7e64fb1ee6046e Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 24 Feb 2025 14:50:44 +0300 Subject: [PATCH 23/33] Updated on 2026-08-14 --- .../features/details/redux/DetailsAction.kt | 4 +- .../details/redux/DetailsMiddleware.kt | 8 +-- .../AppCurrencySelectorFragment.kt | 31 ------------ .../DefaultAppCurrencySelectorComponent.kt | 38 ++++++++++++++ .../api/AppCurrencySelectorComponent.kt | 9 ++++ .../di/AppCurrencySelectorFeatureModule.kt | 25 ++++++++++ .../AppCurrencySelectorModel.kt} | 27 +++++----- .../ui/appsettings/AppSettingsFragment.kt | 42 ---------------- .../DefaultAppSettingsComponent.kt | 49 +++++++++++++++++++ .../AppSettingsItemsAnalyticsSender.kt | 4 +- .../appsettings/api/AppSettingsComponent.kt | 9 ++++ .../di/AppSettingsFeatureModule.kt | 25 ++++++++++ .../AppSettingsModel.kt} | 30 +++++++----- .../DefaultWalletConnectComponent.kt | 2 +- .../tangem/tap/routing/utils/ChildFactory.kt | 34 ++++++++++--- 15 files changed, 225 insertions(+), 112 deletions(-) delete mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/AppCurrencySelectorFragment.kt create mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/DefaultAppCurrencySelectorComponent.kt create mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/api/AppCurrencySelectorComponent.kt create mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/di/AppCurrencySelectorFeatureModule.kt rename app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/{AppCurrencySelectorViewModel.kt => model/AppCurrencySelectorModel.kt} (77%) delete mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsFragment.kt create mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/appsettings/DefaultAppSettingsComponent.kt create mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/appsettings/api/AppSettingsComponent.kt create mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/appsettings/di/AppSettingsFeatureModule.kt rename app/src/main/java/com/tangem/tap/features/details/ui/appsettings/{AppSettingsViewModel.kt => model/AppSettingsModel.kt} (92%) diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsAction.kt b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsAction.kt index 53844799aa..6b648b7c0d 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsAction.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsAction.kt @@ -1,9 +1,9 @@ package com.tangem.tap.features.details.redux -import androidx.lifecycle.LifecycleCoroutineScope import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.apptheme.model.AppThemeMode import com.tangem.domain.models.scan.ScanResponse +import kotlinx.coroutines.CoroutineScope import org.rekotlin.Action sealed class DetailsAction : Action { @@ -27,7 +27,7 @@ sealed class DetailsAction : Action { } data class CheckBiometricsStatus( - val lifecycleScope: LifecycleCoroutineScope, + val coroutineScope: CoroutineScope, ) : AppSettings() data object EnrollBiometrics : AppSettings() diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt index 106bc50e1e..af4c05b261 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt @@ -1,6 +1,5 @@ package com.tangem.tap.features.details.redux -import androidx.lifecycle.LifecycleCoroutineScope import com.tangem.common.CompletionResult import com.tangem.common.doOnFailure import com.tangem.common.doOnSuccess @@ -22,6 +21,7 @@ import com.tangem.tap.store import com.tangem.tap.tangemSdkManager import com.tangem.utils.coroutines.JobHolder import com.tangem.utils.coroutines.saveIn +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flow @@ -67,7 +67,7 @@ class DetailsMiddleware { } } is DetailsAction.AppSettings.CheckBiometricsStatus -> { - observeBiometricsStatusChanges(action.lifecycleScope) + observeBiometricsStatusChanges(action.coroutineScope) } is DetailsAction.AppSettings.EnrollBiometrics -> { enrollBiometrics() @@ -90,7 +90,7 @@ class DetailsMiddleware { } } - private fun observeBiometricsStatusChanges(lifecycleScope: LifecycleCoroutineScope) { + private fun observeBiometricsStatusChanges(scope: CoroutineScope) { val needEnrollBiometricsFlow = flow { do { val needEnrollBiometrics = runCatching(tangemSdkManager::needEnrollBiometrics).getOrNull() @@ -108,7 +108,7 @@ class DetailsMiddleware { .onEach { needEnrollBiometrics -> store.dispatchWithMain(DetailsAction.AppSettings.BiometricsStatusChanged(needEnrollBiometrics)) } - .launchIn(lifecycleScope) + .launchIn(scope) .saveIn(checkBiometricsStatusJobHolder) } diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/AppCurrencySelectorFragment.kt b/app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/AppCurrencySelectorFragment.kt deleted file mode 100644 index e4170e8003..0000000000 --- a/app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/AppCurrencySelectorFragment.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.tangem.tap.features.details.ui.appcurrency - -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.ui.Modifier -import androidx.fragment.app.viewModels -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.tangem.core.ui.UiDependencies -import com.tangem.core.ui.components.NavigationBar3ButtonsScrim -import com.tangem.core.ui.screen.ComposeFragment -import dagger.hilt.android.AndroidEntryPoint -import javax.inject.Inject - -@AndroidEntryPoint -internal class AppCurrencySelectorFragment : ComposeFragment() { - - @Inject - override lateinit var uiDependencies: UiDependencies - - private val viewModel: AppCurrencySelectorViewModel by viewModels() - - @Composable - override fun ScreenContent(modifier: Modifier) { - val uiState by viewModel.uiState.collectAsStateWithLifecycle() - NavigationBar3ButtonsScrim() - AppCurrencySelectorScreen( - modifier = modifier, - state = uiState, - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/DefaultAppCurrencySelectorComponent.kt b/app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/DefaultAppCurrencySelectorComponent.kt new file mode 100644 index 0000000000..6f6ec872a4 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/DefaultAppCurrencySelectorComponent.kt @@ -0,0 +1,38 @@ +package com.tangem.tap.features.details.ui.appcurrency + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.tangem.core.decompose.context.AppComponentContext +import com.tangem.core.decompose.model.getOrCreateModel +import com.tangem.core.ui.components.NavigationBar3ButtonsScrim +import com.tangem.tap.features.details.ui.appcurrency.api.AppCurrencySelectorComponent +import com.tangem.tap.features.details.ui.appcurrency.model.AppCurrencySelectorModel +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject + +@Suppress("UnusedPrivateMember") +internal class DefaultAppCurrencySelectorComponent @AssistedInject constructor( + @Assisted appComponentContext: AppComponentContext, + @Assisted params: Unit, +) : AppCurrencySelectorComponent, AppComponentContext by appComponentContext { + + private val model: AppCurrencySelectorModel = getOrCreateModel() + + @Composable + override fun Content(modifier: Modifier) { + val uiState by model.uiState.collectAsStateWithLifecycle() + NavigationBar3ButtonsScrim() + AppCurrencySelectorScreen( + modifier = modifier, + state = uiState, + ) + } + + @AssistedFactory + interface Factory : AppCurrencySelectorComponent.Factory { + override fun create(context: AppComponentContext, params: Unit): DefaultAppCurrencySelectorComponent + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/api/AppCurrencySelectorComponent.kt b/app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/api/AppCurrencySelectorComponent.kt new file mode 100644 index 0000000000..3b823712b2 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/api/AppCurrencySelectorComponent.kt @@ -0,0 +1,9 @@ +package com.tangem.tap.features.details.ui.appcurrency.api + +import com.tangem.core.decompose.factory.ComponentFactory +import com.tangem.core.ui.decompose.ComposableContentComponent + +interface AppCurrencySelectorComponent : ComposableContentComponent { + + interface Factory : ComponentFactory +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/di/AppCurrencySelectorFeatureModule.kt b/app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/di/AppCurrencySelectorFeatureModule.kt new file mode 100644 index 0000000000..293c87d7a3 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/di/AppCurrencySelectorFeatureModule.kt @@ -0,0 +1,25 @@ +package com.tangem.tap.features.details.ui.appcurrency.di + +import com.tangem.core.decompose.model.Model +import com.tangem.tap.features.details.ui.appcurrency.DefaultAppCurrencySelectorComponent +import com.tangem.tap.features.details.ui.appcurrency.api.AppCurrencySelectorComponent +import com.tangem.tap.features.details.ui.appcurrency.model.AppCurrencySelectorModel +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import dagger.multibindings.ClassKey +import dagger.multibindings.IntoMap + +@Module +@InstallIn(SingletonComponent::class) +internal interface AppCurrencySelectorFeatureModule { + + @Binds + fun bindFactory(impl: DefaultAppCurrencySelectorComponent.Factory): AppCurrencySelectorComponent.Factory + + @Binds + @IntoMap + @ClassKey(AppCurrencySelectorModel::class) + fun bindModel(model: AppCurrencySelectorModel): Model +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/AppCurrencySelectorViewModel.kt b/app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/model/AppCurrencySelectorModel.kt similarity index 77% rename from app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/AppCurrencySelectorViewModel.kt rename to app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/model/AppCurrencySelectorModel.kt index 41d27d02a9..abddb2896e 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/AppCurrencySelectorViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/model/AppCurrencySelectorModel.kt @@ -1,35 +1,38 @@ -package com.tangem.tap.features.details.ui.appcurrency +package com.tangem.tap.features.details.ui.appcurrency.model -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope +import androidx.compose.runtime.Stable import com.tangem.common.routing.AppRouter import com.tangem.core.analytics.api.AnalyticsEventHandler - +import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.model.Model import com.tangem.domain.appcurrency.GetAvailableCurrenciesUseCase import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.SelectAppCurrencyUseCase import com.tangem.tap.common.analytics.events.Settings +import com.tangem.tap.features.details.ui.appcurrency.AppCurrencySelectorIntents +import com.tangem.tap.features.details.ui.appcurrency.AppCurrencySelectorState +import com.tangem.tap.features.details.ui.appcurrency.AppCurrencySelectorStateHolder import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch import javax.inject.Inject -@HiltViewModel -internal class AppCurrencySelectorViewModel @Inject constructor( +@Stable +@ComponentScoped +internal class AppCurrencySelectorModel @Inject constructor( + override val dispatchers: CoroutineDispatcherProvider, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, private val getAvailableCurrenciesUseCase: GetAvailableCurrenciesUseCase, private val selectAppCurrencyUseCase: SelectAppCurrencyUseCase, private val router: AppRouter, - private val dispatchers: CoroutineDispatcherProvider, private val analyticsEventHandler: AnalyticsEventHandler, -) : ViewModel(), AppCurrencySelectorIntents { +) : Model(), AppCurrencySelectorIntents { private val stateController = AppCurrencySelectorStateHolder( intents = this, onSubscription = { fetchCurrencies() }, - stateFlowScope = viewModelScope, + stateFlowScope = modelScope, ) val uiState: StateFlow = stateController.stateFlow @@ -47,7 +50,7 @@ internal class AppCurrencySelectorViewModel @Inject constructor( } override fun onCurrencyClick(currency: AppCurrencySelectorState.Currency) { - viewModelScope.launch(dispatchers.io) { + modelScope.launch(dispatchers.io) { selectAppCurrencyUseCase(currency.id) .onRight { analyticsEventHandler.send( @@ -63,7 +66,7 @@ internal class AppCurrencySelectorViewModel @Inject constructor( } private fun fetchCurrencies() { - viewModelScope.launch(dispatchers.io) { + modelScope.launch(dispatchers.io) { val availableCurrencies = getAvailableCurrenciesUseCase() .onRight(stateController::updateStateWithAvailableCurrencies) .getOrNull() diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsFragment.kt b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsFragment.kt deleted file mode 100644 index 9036d7d1fd..0000000000 --- a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsFragment.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.tangem.tap.features.details.ui.appsettings - -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalLifecycleOwner -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.tangem.common.routing.AppRouter -import com.tangem.core.ui.UiDependencies -import com.tangem.core.ui.screen.ComposeFragment -import com.tangem.domain.appcurrency.repository.AppCurrencyRepository -import com.tangem.tap.common.extensions.dispatchNavigationAction -import com.tangem.tap.store -import dagger.hilt.android.AndroidEntryPoint -import javax.inject.Inject - -@AndroidEntryPoint -internal class AppSettingsFragment : ComposeFragment() { - - @Inject - override lateinit var uiDependencies: UiDependencies - - @Inject - lateinit var appCurrencyRepository: AppCurrencyRepository - - @Composable - override fun ScreenContent(modifier: Modifier) { - val viewModel = hiltViewModel().apply { - LocalLifecycleOwner.current.lifecycle.addObserver(observer = this) - } - val state by viewModel.uiState.collectAsStateWithLifecycle() - - AppSettingsScreen( - modifier = modifier, - state = state, - onBackClick = { - store.dispatchNavigationAction(AppRouter::pop) - }, - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/DefaultAppSettingsComponent.kt b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/DefaultAppSettingsComponent.kt new file mode 100644 index 0000000000..a92b632003 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/DefaultAppSettingsComponent.kt @@ -0,0 +1,49 @@ +package com.tangem.tap.features.details.ui.appsettings + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.arkivanov.essenty.lifecycle.doOnResume +import com.tangem.common.routing.AppRouter +import com.tangem.core.decompose.context.AppComponentContext +import com.tangem.core.decompose.model.getOrCreateModel +import com.tangem.tap.common.extensions.dispatchNavigationAction +import com.tangem.tap.features.details.ui.appsettings.api.AppSettingsComponent +import com.tangem.tap.features.details.ui.appsettings.model.AppSettingsModel +import com.tangem.tap.store +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject + +@Suppress("UnusedPrivateMember") +internal class DefaultAppSettingsComponent @AssistedInject constructor( + @Assisted appComponentContext: AppComponentContext, + @Assisted params: Unit, +) : AppSettingsComponent, AppComponentContext by appComponentContext { + + private val model: AppSettingsModel = getOrCreateModel() + + init { + + doOnResume { model.onResume() } + } + + @Composable + override fun Content(modifier: Modifier) { + val state by model.uiState.collectAsStateWithLifecycle() + + AppSettingsScreen( + modifier = modifier, + state = state, + onBackClick = { + store.dispatchNavigationAction(AppRouter::pop) + }, + ) + } + + @AssistedFactory + interface Factory : AppSettingsComponent.Factory { + override fun create(context: AppComponentContext, params: Unit): DefaultAppSettingsComponent + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/analytics/AppSettingsItemsAnalyticsSender.kt b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/analytics/AppSettingsItemsAnalyticsSender.kt index d61f054cb5..fc0137dca3 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/analytics/AppSettingsItemsAnalyticsSender.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/analytics/AppSettingsItemsAnalyticsSender.kt @@ -2,13 +2,13 @@ package com.tangem.tap.features.details.ui.appsettings.analytics import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.models.AnalyticsEvent +import com.tangem.core.decompose.di.ComponentScoped import com.tangem.tap.common.analytics.events.Settings import com.tangem.tap.features.details.ui.appsettings.AppSettingsItemsFactory import com.tangem.tap.features.details.ui.appsettings.AppSettingsScreenState -import dagger.hilt.android.scopes.ViewModelScoped import javax.inject.Inject -@ViewModelScoped +@ComponentScoped internal class AppSettingsItemsAnalyticsSender @Inject constructor( private val analyticsHandler: AnalyticsEventHandler, ) { diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/api/AppSettingsComponent.kt b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/api/AppSettingsComponent.kt new file mode 100644 index 0000000000..62be87bc2c --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/api/AppSettingsComponent.kt @@ -0,0 +1,9 @@ +package com.tangem.tap.features.details.ui.appsettings.api + +import com.tangem.core.decompose.factory.ComponentFactory +import com.tangem.core.ui.decompose.ComposableContentComponent + +interface AppSettingsComponent : ComposableContentComponent { + + interface Factory : ComponentFactory +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/di/AppSettingsFeatureModule.kt b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/di/AppSettingsFeatureModule.kt new file mode 100644 index 0000000000..8991fbdc06 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/di/AppSettingsFeatureModule.kt @@ -0,0 +1,25 @@ +package com.tangem.tap.features.details.ui.appsettings.di + +import com.tangem.core.decompose.model.Model +import com.tangem.tap.features.details.ui.appsettings.DefaultAppSettingsComponent +import com.tangem.tap.features.details.ui.appsettings.api.AppSettingsComponent +import com.tangem.tap.features.details.ui.appsettings.model.AppSettingsModel +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import dagger.multibindings.ClassKey +import dagger.multibindings.IntoMap + +@Module +@InstallIn(SingletonComponent::class) +internal interface AppSettingsFeatureModule { + + @Binds + fun bindFactory(impl: DefaultAppSettingsComponent.Factory): AppSettingsComponent.Factory + + @Binds + @IntoMap + @ClassKey(AppSettingsModel::class) + fun bindModel(model: AppSettingsModel): Model +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsViewModel.kt b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/model/AppSettingsModel.kt similarity index 92% rename from app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsViewModel.kt rename to app/src/main/java/com/tangem/tap/features/details/ui/appsettings/model/AppSettingsModel.kt index 55d16d7d80..953ad0933c 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/model/AppSettingsModel.kt @@ -1,8 +1,10 @@ -package com.tangem.tap.features.details.ui.appsettings +package com.tangem.tap.features.details.ui.appsettings.model -import androidx.lifecycle.* +import androidx.compose.runtime.Stable import com.tangem.common.routing.AppRoute import com.tangem.core.analytics.api.AnalyticsEventHandler +import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.model.Model import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.appcurrency.repository.AppCurrencyRepository import com.tangem.domain.apptheme.model.AppThemeMode @@ -20,12 +22,15 @@ import com.tangem.tap.features.details.redux.AppSetting import com.tangem.tap.features.details.redux.AppSettingsState import com.tangem.tap.features.details.redux.DetailsAction import com.tangem.tap.features.details.redux.DetailsState +import com.tangem.tap.features.details.ui.appsettings.AppSettingsDialogsFactory +import com.tangem.tap.features.details.ui.appsettings.AppSettingsItemsFactory +import com.tangem.tap.features.details.ui.appsettings.AppSettingsScreenState import com.tangem.tap.features.details.ui.appsettings.analytics.AppSettingsItemsAnalyticsSender import com.tangem.tap.scope import com.tangem.tap.store +import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.coroutines.JobHolder import com.tangem.utils.coroutines.saveIn -import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.flow.* @@ -34,8 +39,10 @@ import org.rekotlin.StoreSubscriber import javax.inject.Inject @Suppress("LongParameterList") -@HiltViewModel -internal class AppSettingsViewModel @Inject constructor( +@Stable +@ComponentScoped +internal class AppSettingsModel @Inject constructor( + override val dispatchers: CoroutineDispatcherProvider, private val appCurrencyRepository: AppCurrencyRepository, private val walletsRepository: WalletsRepository, private val canUseBiometryUseCase: CanUseBiometryUseCase, @@ -44,9 +51,7 @@ internal class AppSettingsViewModel @Inject constructor( private val appThemeModeRepository: AppThemeModeRepository, private val settingsRepository: SettingsRepository, private val appSettingsItemsAnalyticsSender: AppSettingsItemsAnalyticsSender, -) : ViewModel(), - StoreSubscriber, - DefaultLifecycleObserver { +) : Model(), StoreSubscriber { private val itemsFactory = AppSettingsItemsFactory() private val dialogsFactory = AppSettingsDialogsFactory() @@ -82,11 +87,12 @@ internal class AppSettingsViewModel @Inject constructor( } } - override fun onResume(owner: LifecycleOwner) { - store.dispatch(DetailsAction.AppSettings.CheckBiometricsStatus(owner.lifecycleScope)) + fun onResume() { + store.dispatch(DetailsAction.AppSettings.CheckBiometricsStatus(modelScope)) } - override fun onCleared() { + override fun onDestroy() { + super.onDestroy() store.unsubscribe(subscriber = this) } @@ -225,7 +231,7 @@ internal class AppSettingsViewModel @Inject constructor( .saveIn(appCurrencyUpdatesJobHolder) } - private fun bootstrapBiometricsUpdates() = viewModelScope.launch { + private fun bootstrapBiometricsUpdates() = modelScope.launch { val state = AppSettingsState( saveWallets = walletsRepository.shouldSaveUserWalletsSync(), saveAccessCodes = settingsRepository.shouldSaveAccessCodes(), diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/DefaultWalletConnectComponent.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/DefaultWalletConnectComponent.kt index 02357ff195..73a0989519 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/DefaultWalletConnectComponent.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/DefaultWalletConnectComponent.kt @@ -49,7 +49,7 @@ internal class DefaultWalletConnectComponent @AssistedInject constructor( } override fun newState(state: WalletConnectState) { - screenState?.value = model.updateState(state) + screenState.value = model.updateState(state) } @Composable diff --git a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt index 7274342341..229d4b63a2 100644 --- a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt +++ b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt @@ -20,8 +20,8 @@ import com.tangem.features.staking.api.StakingComponent import com.tangem.features.tester.api.TesterRouter import com.tangem.features.tokendetails.TokenDetailsComponent import com.tangem.features.wallet.navigation.WalletRouter -import com.tangem.tap.features.details.ui.appcurrency.AppCurrencySelectorFragment -import com.tangem.tap.features.details.ui.appsettings.AppSettingsFragment +import com.tangem.tap.features.details.ui.appcurrency.api.AppCurrencySelectorComponent +import com.tangem.tap.features.details.ui.appsettings.api.AppSettingsComponent import com.tangem.tap.features.details.ui.cardsettings.api.CardSettingsComponent import com.tangem.tap.features.details.ui.cardsettings.coderecovery.api.AccessCodeRecoveryComponent import com.tangem.tap.features.details.ui.resetcard.ResetCardFragment @@ -67,6 +67,8 @@ internal class ChildFactory @Inject constructor( private val qrScanningComponentFactory: QrScanningComponent.Factory, private val accessCodeRecoveryComponentFactory: AccessCodeRecoveryComponent.Factory, private val cardSettingsComponentFactory: CardSettingsComponent.Factory, + private val appCurrencySelectorComponentFactory: AppCurrencySelectorComponent.Factory, + private val appSettingsComponentFactory: AppSettingsComponent.Factory, private val walletRouter: WalletRouter, private val testerRouter: TesterRouter, private val pushNotificationRouter: PushNotificationsRouter, @@ -303,9 +305,21 @@ internal class ChildFactory @Inject constructor( componentFactory = cardSettingsComponentFactory, ) } - is AppRoute.AppCurrencySelector, + is AppRoute.AppCurrencySelector -> { + createComponentChild( + contextProvider = contextProvider(route, contextFactory), + params = Unit, + componentFactory = appCurrencySelectorComponentFactory, + ) + } + is AppRoute.AppSettings -> { + createComponentChild( + contextProvider = contextProvider(route, contextFactory), + params = Unit, + componentFactory = appSettingsComponentFactory, + ) + } is AppRoute.SaveWallet, - is AppRoute.AppSettings, is AppRoute.DetailsSecurity, is AppRoute.OnboardingNote, is AppRoute.OnboardingOther, @@ -337,7 +351,11 @@ internal class ChildFactory @Inject constructor( ) } is AppRoute.AppCurrencySelector -> { - route.asFragmentChild(Provider { AppCurrencySelectorFragment() }) + route.asComponentChild( + contextProvider = contextProvider(route, contextFactory), + params = Unit, + componentFactory = appCurrencySelectorComponentFactory, + ) } is AppRoute.SaveWallet -> { route.asFragmentChild(Provider { SaveWalletBottomSheetFragment() }) @@ -357,7 +375,11 @@ internal class ChildFactory @Inject constructor( ) } is AppRoute.AppSettings -> { - route.asFragmentChild(Provider { AppSettingsFragment() }) + route.asComponentChild( + contextProvider = contextProvider(route, contextFactory), + params = Unit, + componentFactory = appSettingsComponentFactory, + ) } is AppRoute.CardSettings -> { route.asComponentChild( From 3503a14f3b1ee3733bf3fec2825864f71c439800 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 24 Feb 2025 17:28:05 +0300 Subject: [PATCH 24/33] Updated on 2026-08-14 --- .../domain/userWalletList/model/UserWalletInformation.kt | 3 +++ .../com/tangem/tap/domain/userWalletList/utils/Mapper.kt | 8 +++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/model/UserWalletInformation.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/model/UserWalletInformation.kt index 2697b453b7..e7a9f1873f 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/model/UserWalletInformation.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/model/UserWalletInformation.kt @@ -4,12 +4,15 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass import com.tangem.domain.models.scan.CardDTO import com.tangem.domain.models.scan.ScanResponse +import com.tangem.domain.visa.model.VisaCardActivationStatus import com.tangem.domain.wallets.models.UserWalletId @JsonClass(generateAdapter = true) internal data class UserWalletSensitiveInformation( @Json(name = "wallets") val wallets: List, + @Json(name = "visaCardActivationStatus") + val visaCardActivationStatus: VisaCardActivationStatus? = null, ) @JsonClass(generateAdapter = true) diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/utils/Mapper.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/utils/Mapper.kt index 7b869eb69f..4c73101416 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/utils/Mapper.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/utils/Mapper.kt @@ -6,7 +6,10 @@ import com.tangem.tap.domain.userWalletList.model.UserWalletPublicInformation import com.tangem.tap.domain.userWalletList.model.UserWalletSensitiveInformation internal val UserWallet.sensitiveInformation: UserWalletSensitiveInformation - get() = UserWalletSensitiveInformation(scanResponse.card.wallets) + get() = UserWalletSensitiveInformation( + wallets = scanResponse.card.wallets, + visaCardActivationStatus = scanResponse.visaCardActivationStatus, + ) internal val UserWallet.publicInformation: UserWalletPublicInformation get() = UserWalletPublicInformation( @@ -19,6 +22,7 @@ internal val UserWallet.publicInformation: UserWalletPublicInformation card = scanResponse.card.copy( wallets = emptyList(), ), + visaCardActivationStatus = null, ), hasBackupError = hasBackupError, ) @@ -45,6 +49,7 @@ internal fun UserWallet.updateWith(sensitiveInformation: UserWalletSensitiveInfo card = scanResponse.card.copy( wallets = sensitiveInformation.wallets, ), + visaCardActivationStatus = sensitiveInformation.visaCardActivationStatus, ), ) } @@ -70,5 +75,6 @@ internal fun UserWallet.lock(): UserWallet = copy( card = scanResponse.card.copy( wallets = emptyList(), ), + visaCardActivationStatus = null, ), ) \ No newline at end of file From 8212dffeb6b1f0e387499e47adee8c869022ab58 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 24 Feb 2025 21:30:53 +0300 Subject: [PATCH 25/33] Updated on 2026-08-14 --- .../ui/resetcard/DefaultResetCardComponent.kt | 40 ++++++++++++++++ .../details/ui/resetcard/ResetCardFragment.kt | 34 ------------- .../ui/resetcard/api/ResetCardComponent.kt | 17 +++++++ .../ui/resetcard/di/ResetCardFeatureModule.kt | 25 ++++++++++ .../ResetCardModel.kt} | 47 +++++++++--------- .../DefaultSecurityModeComponent.kt | 43 +++++++++++++++++ .../ui/securitymode/SecurityModeFragment.kt | 34 ------------- .../securitymode/api/SecurityModeComponent.kt | 14 ++++++ .../di/SecurityModeFeatureModule.kt | 25 ++++++++++ .../SecurityModeModel.kt} | 20 ++++---- .../tangem/tap/routing/utils/ChildFactory.kt | 48 ++++++++++++++++--- .../com/tangem/common/routing/AppRoute.kt | 18 +------ 12 files changed, 243 insertions(+), 122 deletions(-) create mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/resetcard/DefaultResetCardComponent.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardFragment.kt create mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/resetcard/api/ResetCardComponent.kt create mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/resetcard/di/ResetCardFeatureModule.kt rename app/src/main/java/com/tangem/tap/features/details/ui/resetcard/{ResetCardViewModel.kt => model/ResetCardModel.kt} (88%) create mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/securitymode/DefaultSecurityModeComponent.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/securitymode/SecurityModeFragment.kt create mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/securitymode/api/SecurityModeComponent.kt create mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/securitymode/di/SecurityModeFeatureModule.kt rename app/src/main/java/com/tangem/tap/features/details/ui/securitymode/{SecurityModeViewModel.kt => model/SecurityModeModel.kt} (87%) diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/DefaultResetCardComponent.kt b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/DefaultResetCardComponent.kt new file mode 100644 index 0000000000..16000cb7bb --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/DefaultResetCardComponent.kt @@ -0,0 +1,40 @@ +package com.tangem.tap.features.details.ui.resetcard + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.tangem.common.routing.AppRouter +import com.tangem.core.decompose.context.AppComponentContext +import com.tangem.core.decompose.model.getOrCreateModel +import com.tangem.tap.common.extensions.dispatchNavigationAction +import com.tangem.tap.features.details.ui.resetcard.api.ResetCardComponent +import com.tangem.tap.features.details.ui.resetcard.model.ResetCardModel +import com.tangem.tap.store +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject + +internal class DefaultResetCardComponent @AssistedInject constructor( + @Assisted appComponentContext: AppComponentContext, + @Assisted params: ResetCardComponent.Params, +) : ResetCardComponent, AppComponentContext by appComponentContext { + + private val model: ResetCardModel = getOrCreateModel(params) + + @Composable + override fun Content(modifier: Modifier) { + val state by model.screenState.collectAsStateWithLifecycle() + + ResetCardScreen( + modifier = modifier, + state = state, + onBackClick = { store.dispatchNavigationAction(AppRouter::pop) }, + ) + } + + @AssistedFactory + interface Factory : ResetCardComponent.Factory { + override fun create(context: AppComponentContext, params: ResetCardComponent.Params): DefaultResetCardComponent + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardFragment.kt b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardFragment.kt deleted file mode 100644 index 041a91ee08..0000000000 --- a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardFragment.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.tangem.tap.features.details.ui.resetcard - -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.ui.Modifier -import androidx.fragment.app.viewModels -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.tangem.common.routing.AppRouter -import com.tangem.core.ui.UiDependencies -import com.tangem.core.ui.screen.ComposeFragment -import com.tangem.tap.common.extensions.dispatchNavigationAction -import com.tangem.tap.store -import dagger.hilt.android.AndroidEntryPoint -import javax.inject.Inject - -@AndroidEntryPoint -internal class ResetCardFragment : ComposeFragment() { - - @Inject - override lateinit var uiDependencies: UiDependencies - - private val viewModel: ResetCardViewModel by viewModels() - - @Composable - override fun ScreenContent(modifier: Modifier) { - val state by viewModel.screenState.collectAsStateWithLifecycle() - - ResetCardScreen( - state = state, - onBackClick = { store.dispatchNavigationAction(AppRouter::pop) }, - modifier = modifier, - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/api/ResetCardComponent.kt b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/api/ResetCardComponent.kt new file mode 100644 index 0000000000..abbe76595b --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/api/ResetCardComponent.kt @@ -0,0 +1,17 @@ +package com.tangem.tap.features.details.ui.resetcard.api + +import com.tangem.core.decompose.factory.ComponentFactory +import com.tangem.core.ui.decompose.ComposableContentComponent +import com.tangem.domain.wallets.models.UserWalletId + +interface ResetCardComponent : ComposableContentComponent { + + data class Params( + val userWalletId: UserWalletId, + val cardId: String, + val isActiveBackupStatus: Boolean, + val backupCardsCount: Int, + ) + + interface Factory : ComponentFactory +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/di/ResetCardFeatureModule.kt b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/di/ResetCardFeatureModule.kt new file mode 100644 index 0000000000..cdda8d97d4 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/di/ResetCardFeatureModule.kt @@ -0,0 +1,25 @@ +package com.tangem.tap.features.details.ui.resetcard.di + +import com.tangem.core.decompose.model.Model +import com.tangem.tap.features.details.ui.resetcard.DefaultResetCardComponent +import com.tangem.tap.features.details.ui.resetcard.api.ResetCardComponent +import com.tangem.tap.features.details.ui.resetcard.model.ResetCardModel +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import dagger.multibindings.ClassKey +import dagger.multibindings.IntoMap + +@Module +@InstallIn(SingletonComponent::class) +internal interface ResetCardFeatureModule { + + @Binds + fun bindFactory(impl: DefaultResetCardComponent.Factory): ResetCardComponent.Factory + + @Binds + @IntoMap + @ClassKey(ResetCardModel::class) + fun bindModel(model: ResetCardModel): Model +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardViewModel.kt b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/model/ResetCardModel.kt similarity index 88% rename from app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardViewModel.kt rename to app/src/main/java/com/tangem/tap/features/details/ui/resetcard/model/ResetCardModel.kt index ebcdf702a9..a4108e3ea0 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/model/ResetCardModel.kt @@ -1,21 +1,19 @@ -package com.tangem.tap.features.details.ui.resetcard +package com.tangem.tap.features.details.ui.resetcard.model -import android.os.Bundle -import androidx.lifecycle.SavedStateHandle -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope +import androidx.compose.runtime.Stable import arrow.core.getOrElse import com.tangem.common.routing.AppRoute -import com.tangem.common.routing.bundle.unbundle import com.tangem.common.routing.utils.popTo import com.tangem.core.analytics.api.AnalyticsEventHandler +import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.model.Model +import com.tangem.core.decompose.model.ParamsContainer import com.tangem.domain.card.DeleteSavedAccessCodesUseCase import com.tangem.domain.card.ResetCardUseCase import com.tangem.domain.card.ResetCardUserCodeParams import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.wallets.legacy.UserWalletsListManager import com.tangem.domain.wallets.legacy.asLockable -import com.tangem.domain.wallets.models.UserWalletId import com.tangem.domain.wallets.usecase.DeleteWalletUseCase import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase import com.tangem.domain.wallets.usecase.GetUserWalletUseCase @@ -24,9 +22,12 @@ import com.tangem.tap.common.extensions.dispatchNavigationAction import com.tangem.tap.common.extensions.onUserWalletSelected import com.tangem.tap.features.details.ui.cardsettings.domain.CardSettingsInteractor import com.tangem.tap.features.details.ui.common.utils.getResetToFactoryDescription +import com.tangem.tap.features.details.ui.resetcard.ResetCardDialog +import com.tangem.tap.features.details.ui.resetcard.ResetCardScreenState +import com.tangem.tap.features.details.ui.resetcard.api.ResetCardComponent import com.tangem.tap.store +import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.extensions.DELAY_SDK_DIALOG_CLOSE -import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.update @@ -35,8 +36,11 @@ import timber.log.Timber import javax.inject.Inject @Suppress("LongParameterList") -@HiltViewModel -internal class ResetCardViewModel @Inject constructor( +@Stable +@ComponentScoped +internal class ResetCardModel @Inject constructor( + override val dispatchers: CoroutineDispatcherProvider, + paramsContainer: ParamsContainer, getUserWalletUseCase: GetUserWalletUseCase, private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase, private val resetCardUseCase: ResetCardUseCase, @@ -45,13 +49,12 @@ internal class ResetCardViewModel @Inject constructor( private val userWalletsListManager: UserWalletsListManager, private val analyticsEventHandler: AnalyticsEventHandler, private val cardSettingsInteractor: CardSettingsInteractor, - savedStateHandle: SavedStateHandle, -) : ViewModel() { +) : Model() { + + private val params = paramsContainer.require() // region Card-set specific data. All cards from single set have the same userWalletId and cardTypesResolver - private val currentUserWalletId = savedStateHandle.get(AppRoute.ResetToFactory.USER_WALLET_ID) - ?.unbundle(UserWalletId.serializer()) - ?: error("UserWalletId must be provided for ResetCardViewModel") + private val currentUserWalletId = params.userWalletId // Use only for card-specific data private val userWallet = getUserWalletUseCase(userWalletId = currentUserWalletId) @@ -65,15 +68,11 @@ internal class ResetCardViewModel @Inject constructor( // endregion // region Data of card that was scanned on CardSettings - private val primaryCardId: String = savedStateHandle.get(AppRoute.ResetToFactory.CARD_ID) - ?: error("CardId must be provided for ResetCardViewModel") + private val primaryCardId: String = params.cardId - private val isActiveBackupPrimaryCard = - savedStateHandle.get(AppRoute.ResetToFactory.IS_ACTIVE_BACKUP_STATUS) - ?: error("IsActiveBackupCard must be provided for ResetCardViewModel") + private val isActiveBackupPrimaryCard = params.isActiveBackupStatus - private val primaryBackupCardsCount = savedStateHandle.get(AppRoute.ResetToFactory.BACKUP_CARDS_COUNT) - ?: error("CardCount must be provided for ResetCardViewModel") + private val primaryBackupCardsCount = params.backupCardsCount // endregion // TODO: move logic to separate domain entity @@ -177,7 +176,7 @@ internal class ResetCardViewModel @Inject constructor( } private fun makeFullReset() { - viewModelScope.launch { + modelScope.launch { resetCardUseCase(cardId = primaryCardId, params = currentUserCodeParams).onRight { deleteSavedAccessCodesUseCase(cardId = primaryCardId) val hasUserWallets = deleteWalletUseCase(userWalletId = currentUserWalletId).getOrElse { @@ -203,7 +202,7 @@ internal class ResetCardViewModel @Inject constructor( private fun onContinueResetClick() { dismissDialog() - viewModelScope.launch { + modelScope.launch { resetCardUseCase( cardNumber = resetBackupCardCount + 1, params = currentUserCodeParams, diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/DefaultSecurityModeComponent.kt b/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/DefaultSecurityModeComponent.kt new file mode 100644 index 0000000000..151b4c123d --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/DefaultSecurityModeComponent.kt @@ -0,0 +1,43 @@ +package com.tangem.tap.features.details.ui.securitymode + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.tangem.common.routing.AppRouter +import com.tangem.core.decompose.context.AppComponentContext +import com.tangem.core.decompose.model.getOrCreateModel +import com.tangem.tap.common.extensions.dispatchNavigationAction +import com.tangem.tap.features.details.ui.securitymode.api.SecurityModeComponent +import com.tangem.tap.features.details.ui.securitymode.model.SecurityModeModel +import com.tangem.tap.store +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject + +internal class DefaultSecurityModeComponent @AssistedInject constructor( + @Assisted appComponentContext: AppComponentContext, + @Assisted params: SecurityModeComponent.Params, +) : SecurityModeComponent, AppComponentContext by appComponentContext { + + private val model: SecurityModeModel = getOrCreateModel(params) + + @Composable + override fun Content(modifier: Modifier) { + val state by model.screenState.collectAsStateWithLifecycle() + + SecurityModeScreen( + modifier = modifier, + state = state, + onBackClick = { store.dispatchNavigationAction(AppRouter::pop) }, + ) + } + + @AssistedFactory + interface Factory : SecurityModeComponent.Factory { + override fun create( + context: AppComponentContext, + params: SecurityModeComponent.Params, + ): DefaultSecurityModeComponent + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/SecurityModeFragment.kt b/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/SecurityModeFragment.kt deleted file mode 100644 index 1c5fe7f90b..0000000000 --- a/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/SecurityModeFragment.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.tangem.tap.features.details.ui.securitymode - -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.ui.Modifier -import androidx.fragment.app.viewModels -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.tangem.common.routing.AppRouter -import com.tangem.core.ui.UiDependencies -import com.tangem.core.ui.screen.ComposeFragment -import com.tangem.tap.common.extensions.dispatchNavigationAction -import com.tangem.tap.store -import dagger.hilt.android.AndroidEntryPoint -import javax.inject.Inject - -@AndroidEntryPoint -internal class SecurityModeFragment : ComposeFragment() { - - @Inject - override lateinit var uiDependencies: UiDependencies - - private val viewModel: SecurityModeViewModel by viewModels() - - @Composable - override fun ScreenContent(modifier: Modifier) { - val state by viewModel.screenState.collectAsStateWithLifecycle() - - SecurityModeScreen( - modifier = modifier, - state = state, - onBackClick = { store.dispatchNavigationAction(AppRouter::pop) }, - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/api/SecurityModeComponent.kt b/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/api/SecurityModeComponent.kt new file mode 100644 index 0000000000..a09d7ba6c9 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/api/SecurityModeComponent.kt @@ -0,0 +1,14 @@ +package com.tangem.tap.features.details.ui.securitymode.api + +import com.tangem.core.decompose.factory.ComponentFactory +import com.tangem.core.ui.decompose.ComposableContentComponent +import com.tangem.domain.wallets.models.UserWalletId + +interface SecurityModeComponent : ComposableContentComponent { + + data class Params( + val userWalletId: UserWalletId, + ) + + interface Factory : ComponentFactory +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/di/SecurityModeFeatureModule.kt b/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/di/SecurityModeFeatureModule.kt new file mode 100644 index 0000000000..3fb8b00635 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/di/SecurityModeFeatureModule.kt @@ -0,0 +1,25 @@ +package com.tangem.tap.features.details.ui.securitymode.di + +import com.tangem.core.decompose.model.Model +import com.tangem.tap.features.details.ui.securitymode.DefaultSecurityModeComponent +import com.tangem.tap.features.details.ui.securitymode.api.SecurityModeComponent +import com.tangem.tap.features.details.ui.securitymode.model.SecurityModeModel +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import dagger.multibindings.ClassKey +import dagger.multibindings.IntoMap + +@Module +@InstallIn(SingletonComponent::class) +internal interface SecurityModeFeatureModule { + + @Binds + fun bindFactory(impl: DefaultSecurityModeComponent.Factory): SecurityModeComponent.Factory + + @Binds + @IntoMap + @ClassKey(SecurityModeModel::class) + fun bindModel(model: SecurityModeModel): Model +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/SecurityModeViewModel.kt b/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/model/SecurityModeModel.kt similarity index 87% rename from app/src/main/java/com/tangem/tap/features/details/ui/securitymode/SecurityModeViewModel.kt rename to app/src/main/java/com/tangem/tap/features/details/ui/securitymode/model/SecurityModeModel.kt index a7f0b763b3..5fe21b868c 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/SecurityModeViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/model/SecurityModeModel.kt @@ -1,11 +1,12 @@ -package com.tangem.tap.features.details.ui.securitymode +package com.tangem.tap.features.details.ui.securitymode.model -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope +import androidx.compose.runtime.Stable import com.tangem.common.CompletionResult import com.tangem.common.core.TangemSdkError import com.tangem.common.routing.AppRouter import com.tangem.core.analytics.Analytics +import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.model.Model import com.tangem.domain.common.util.cardTypesResolver import com.tangem.sdk.api.TangemSdkManager import com.tangem.tap.common.analytics.events.AnalyticsParam @@ -15,18 +16,21 @@ 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 import com.tangem.tap.features.details.ui.common.utils.getCurrentSecurityOption +import com.tangem.tap.features.details.ui.securitymode.SecurityModeScreenState import com.tangem.tap.store -import dagger.hilt.android.lifecycle.HiltViewModel +import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import javax.inject.Inject -@HiltViewModel -internal class SecurityModeViewModel @Inject constructor( +@Stable +@ComponentScoped +internal class SecurityModeModel @Inject constructor( + override val dispatchers: CoroutineDispatcherProvider, private val tangemSdkManager: TangemSdkManager, private val cardSettingsInteractor: CardSettingsInteractor, -) : ViewModel() { +) : Model() { private val scannedScanResponse = cardSettingsInteractor.scannedScanResponse.value ?: error("Scan response is null") @@ -62,7 +66,7 @@ internal class SecurityModeViewModel @Inject constructor( val cardId = scannedScanResponse.card.cardId val selectedOption = screenState.value.selectedSecurityMode - viewModelScope.launch { + modelScope.launch { val result = when (selectedOption) { SecurityOption.LongTap -> tangemSdkManager.setLongTap(cardId) SecurityOption.PassCode -> tangemSdkManager.setPasscode(cardId) diff --git a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt index 229d4b63a2..ff2cfe56d1 100644 --- a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt +++ b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt @@ -24,8 +24,8 @@ import com.tangem.tap.features.details.ui.appcurrency.api.AppCurrencySelectorCom import com.tangem.tap.features.details.ui.appsettings.api.AppSettingsComponent import com.tangem.tap.features.details.ui.cardsettings.api.CardSettingsComponent import com.tangem.tap.features.details.ui.cardsettings.coderecovery.api.AccessCodeRecoveryComponent -import com.tangem.tap.features.details.ui.resetcard.ResetCardFragment -import com.tangem.tap.features.details.ui.securitymode.SecurityModeFragment +import com.tangem.tap.features.details.ui.resetcard.api.ResetCardComponent +import com.tangem.tap.features.details.ui.securitymode.api.SecurityModeComponent import com.tangem.tap.features.details.ui.walletconnect.api.WalletConnectComponent import com.tangem.tap.features.home.api.HomeComponent import com.tangem.tap.features.onboarding.products.note.OnboardingNoteFragment @@ -69,6 +69,8 @@ internal class ChildFactory @Inject constructor( private val cardSettingsComponentFactory: CardSettingsComponent.Factory, private val appCurrencySelectorComponentFactory: AppCurrencySelectorComponent.Factory, private val appSettingsComponentFactory: AppSettingsComponent.Factory, + private val securityModeComponentFactory: SecurityModeComponent.Factory, + private val resetCardComponentFactory: ResetCardComponent.Factory, private val walletRouter: WalletRouter, private val testerRouter: TesterRouter, private val pushNotificationRouter: PushNotificationsRouter, @@ -319,14 +321,33 @@ internal class ChildFactory @Inject constructor( componentFactory = appSettingsComponentFactory, ) } + is AppRoute.DetailsSecurity -> { + createComponentChild( + contextProvider = contextProvider(route, contextFactory), + params = SecurityModeComponent.Params( + userWalletId = route.userWalletId, + ), + componentFactory = securityModeComponentFactory, + ) + } + is AppRoute.ResetToFactory -> { + createComponentChild( + contextProvider = contextProvider(route, contextFactory), + params = ResetCardComponent.Params( + userWalletId = route.userWalletId, + cardId = route.cardId, + isActiveBackupStatus = route.isActiveBackupStatus, + backupCardsCount = route.backupCardsCount, + ), + componentFactory = resetCardComponentFactory, + ) + } is AppRoute.SaveWallet, - is AppRoute.DetailsSecurity, is AppRoute.OnboardingNote, is AppRoute.OnboardingOther, is AppRoute.OnboardingTwins, is AppRoute.OnboardingWallet, is AppRoute.ReferralProgram, - is AppRoute.ResetToFactory, is AppRoute.Wallet, is AppRoute.PushNotification, -> error("Unsupported route: $route") @@ -396,7 +417,13 @@ internal class ChildFactory @Inject constructor( ) } is AppRoute.DetailsSecurity -> { - route.asFragmentChild(Provider { SecurityModeFragment() }) + route.asComponentChild( + contextProvider = contextProvider(route, contextFactory), + params = SecurityModeComponent.Params( + userWalletId = route.userWalletId, + ), + componentFactory = securityModeComponentFactory, + ) } is AppRoute.Disclaimer -> { route.asComponentChild( @@ -451,7 +478,16 @@ internal class ChildFactory @Inject constructor( route.asFragmentChild(Provider { ReferralFragment() }) } is AppRoute.ResetToFactory -> { - route.asFragmentChild(Provider { ResetCardFragment() }) + route.asComponentChild( + contextProvider = contextProvider(route, contextFactory), + params = ResetCardComponent.Params( + userWalletId = route.userWalletId, + cardId = route.cardId, + isActiveBackupStatus = route.isActiveBackupStatus, + backupCardsCount = route.backupCardsCount, + ), + componentFactory = resetCardComponentFactory, + ) } is AppRoute.Swap -> { route.asComponentChild( diff --git a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt index 4fec799a3c..dddee065b7 100644 --- a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt +++ b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt @@ -103,10 +103,7 @@ sealed class AppRoute(val path: String) : Route { @Serializable data class DetailsSecurity( val userWalletId: UserWalletId, - ) : AppRoute(path = "/details/security"), RouteBundleParams { - - override fun getBundle(): Bundle = bundle(serializer()) - } + ) : AppRoute(path = "/details/security") @Serializable data class CardSettings( @@ -136,18 +133,7 @@ sealed class AppRoute(val path: String) : Route { "/$cardId" + "/$isActiveBackupStatus" + "/$backupCardsCount", - ), - RouteBundleParams { - - override fun getBundle(): Bundle = bundle(serializer()) - - companion object { - const val USER_WALLET_ID = "userWalletId" - const val CARD_ID = "cardId" - const val IS_ACTIVE_BACKUP_STATUS = "isActiveBackupStatus" - const val BACKUP_CARDS_COUNT = "backupCardsCount" - } - } + ) @Serializable data object AccessCodeRecovery : AppRoute(path = "/access_code_recovery"), RouteBundleParams { From e88aaebe5d0aaa5a0e1871bb5db648b2771f8be4 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 25 Feb 2025 05:35:58 +0000 Subject: [PATCH 26/33] Updated on 2026-08-14 --- gradle/tangem_dependencies.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/tangem_dependencies.toml b/gradle/tangem_dependencies.toml index 3be6bacbc0..b58666bdd9 100644 --- a/gradle/tangem_dependencies.toml +++ b/gradle/tangem_dependencies.toml @@ -1,7 +1,7 @@ [versions] -tangemBlockchainSdk = "release-app_5.21-963" +tangemBlockchainSdk = "develop-959" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds -tangemCardSdk = "release-app_5.21-435" +tangemCardSdk = "develop-434" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ tangemVico = "2.0.0-alpha.25-tangem-developments8" #tangemVico = "0.0.1" # Keep it! - used for local builds ^ From e8da66786f0c665c18908fefb247c490fb77a6f0 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 25 Feb 2025 09:53:16 +0300 Subject: [PATCH 27/33] Updated on 2026-08-14 --- gradle/tangem_dependencies.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/tangem_dependencies.toml b/gradle/tangem_dependencies.toml index b58666bdd9..422608e325 100644 --- a/gradle/tangem_dependencies.toml +++ b/gradle/tangem_dependencies.toml @@ -1,5 +1,5 @@ [versions] -tangemBlockchainSdk = "develop-959" +tangemBlockchainSdk = "develop-965" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "develop-434" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ From 4a6e57a049ca7cc88c9b83f83566200ff9e3d678 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 25 Feb 2025 10:02:39 +0300 Subject: [PATCH 28/33] Updated on 2026-08-14 --- app/build.gradle.kts | 2 +- .../tangem/tap/routing/utils/ChildFactory.kt | 17 ++++- .../di/CoroutineDispatcherProviderModule.kt | 2 +- features/referral/api/.gitignore | 1 + features/referral/api/build.gradle.kts | 20 ++++++ .../feature/referral/api/ReferralComponent.kt | 14 +++++ features/referral/domain/build.gradle.kts | 1 + .../domain/di/ReferralDomainModule.kt | 8 +-- .../{presentation => impl}/.gitignore | 0 .../{presentation => impl}/build.gradle.kts | 4 ++ .../referral/DefaultReferralComponent.kt | 30 +++++++++ .../referral/analytics/ReferralEvents.kt | 0 .../feature/referral/di/ComponentModule.kt | 25 ++++++++ .../feature/referral/model/ReferralModel.kt} | 62 ++++++++----------- .../referral/models/DemoModeException.kt | 0 .../referral/models/ReferralStateHolder.kt | 0 .../feature/referral/ui/AgreementText.kt | 0 .../referral/ui/NonParticipateBottomBlock.kt | 0 .../referral/ui/ParticipateBottomBlock.kt | 0 .../feature/referral/ui/ReferralScreen.kt | 0 .../feature/referral/ReferralFragment.kt | 37 ----------- .../feature/referral/router/ReferralRouter.kt | 12 ---- settings.gradle.kts | 3 +- 23 files changed, 143 insertions(+), 95 deletions(-) create mode 100644 features/referral/api/.gitignore create mode 100644 features/referral/api/build.gradle.kts create mode 100644 features/referral/api/src/main/kotlin/com/tangem/feature/referral/api/ReferralComponent.kt rename features/referral/{presentation => impl}/.gitignore (100%) rename features/referral/{presentation => impl}/build.gradle.kts (93%) create mode 100644 features/referral/impl/src/main/java/com/tangem/feature/referral/DefaultReferralComponent.kt rename features/referral/{presentation => impl}/src/main/java/com/tangem/feature/referral/analytics/ReferralEvents.kt (100%) create mode 100644 features/referral/impl/src/main/java/com/tangem/feature/referral/di/ComponentModule.kt rename features/referral/{presentation/src/main/java/com/tangem/feature/referral/viewmodels/ReferralViewModel.kt => impl/src/main/java/com/tangem/feature/referral/model/ReferralModel.kt} (78%) rename features/referral/{presentation => impl}/src/main/java/com/tangem/feature/referral/models/DemoModeException.kt (100%) rename features/referral/{presentation => impl}/src/main/java/com/tangem/feature/referral/models/ReferralStateHolder.kt (100%) rename features/referral/{presentation => impl}/src/main/java/com/tangem/feature/referral/ui/AgreementText.kt (100%) rename features/referral/{presentation => impl}/src/main/java/com/tangem/feature/referral/ui/NonParticipateBottomBlock.kt (100%) rename features/referral/{presentation => impl}/src/main/java/com/tangem/feature/referral/ui/ParticipateBottomBlock.kt (100%) rename features/referral/{presentation => impl}/src/main/java/com/tangem/feature/referral/ui/ReferralScreen.kt (100%) delete mode 100644 features/referral/presentation/src/main/java/com/tangem/feature/referral/ReferralFragment.kt delete mode 100644 features/referral/presentation/src/main/java/com/tangem/feature/referral/router/ReferralRouter.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 8fa9c93920..c3a1e5b24a 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -146,7 +146,7 @@ dependencies { /** Features */ implementation(projects.features.onboarding) - implementation(projects.features.referral.presentation) + implementation(projects.features.referral.impl) implementation(projects.features.referral.domain) implementation(projects.features.referral.data) implementation(projects.features.swap.api) diff --git a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt index ff2cfe56d1..bcea27fccd 100644 --- a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt +++ b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt @@ -3,7 +3,7 @@ package com.tangem.tap.routing.utils import com.tangem.common.routing.AppRoute import com.tangem.core.decompose.context.AppComponentContext import com.tangem.feature.qrscanning.QrScanningComponent -import com.tangem.feature.referral.ReferralFragment +import com.tangem.feature.referral.api.ReferralComponent import com.tangem.feature.stories.api.StoriesComponent import com.tangem.feature.walletsettings.component.WalletSettingsComponent import com.tangem.features.details.component.DetailsComponent @@ -71,6 +71,7 @@ internal class ChildFactory @Inject constructor( private val appSettingsComponentFactory: AppSettingsComponent.Factory, private val securityModeComponentFactory: SecurityModeComponent.Factory, private val resetCardComponentFactory: ResetCardComponent.Factory, + private val referralComponentFactory: ReferralComponent.Factory, private val walletRouter: WalletRouter, private val testerRouter: TesterRouter, private val pushNotificationRouter: PushNotificationsRouter, @@ -342,12 +343,18 @@ internal class ChildFactory @Inject constructor( componentFactory = resetCardComponentFactory, ) } + is AppRoute.ReferralProgram -> { + createComponentChild( + contextProvider = contextProvider(route, contextFactory), + params = ReferralComponent.Params(route.userWalletId), + componentFactory = referralComponentFactory, + ) + } is AppRoute.SaveWallet, is AppRoute.OnboardingNote, is AppRoute.OnboardingOther, is AppRoute.OnboardingTwins, is AppRoute.OnboardingWallet, - is AppRoute.ReferralProgram, is AppRoute.Wallet, is AppRoute.PushNotification, -> error("Unsupported route: $route") @@ -475,7 +482,11 @@ internal class ChildFactory @Inject constructor( ) } is AppRoute.ReferralProgram -> { - route.asFragmentChild(Provider { ReferralFragment() }) + route.asComponentChild( + contextProvider = contextProvider(route, contextFactory), + params = ReferralComponent.Params(route.userWalletId), + componentFactory = referralComponentFactory, + ) } is AppRoute.ResetToFactory -> { route.asComponentChild( diff --git a/core/utils/src/main/java/com/tangem/utils/di/CoroutineDispatcherProviderModule.kt b/core/utils/src/main/java/com/tangem/utils/di/CoroutineDispatcherProviderModule.kt index 6dd1011462..cf0847f2f0 100644 --- a/core/utils/src/main/java/com/tangem/utils/di/CoroutineDispatcherProviderModule.kt +++ b/core/utils/src/main/java/com/tangem/utils/di/CoroutineDispatcherProviderModule.kt @@ -9,7 +9,7 @@ import dagger.hilt.components.SingletonComponent @Module @InstallIn(SingletonComponent::class) -interface CoroutineDispatcherProviderModule { +internal interface CoroutineDispatcherProviderModule { @Binds fun bindCoroutineDispatcherProvider( diff --git a/features/referral/api/.gitignore b/features/referral/api/.gitignore new file mode 100644 index 0000000000..796b96d1c4 --- /dev/null +++ b/features/referral/api/.gitignore @@ -0,0 +1 @@ +/build diff --git a/features/referral/api/build.gradle.kts b/features/referral/api/build.gradle.kts new file mode 100644 index 0000000000..22a3ba6fa3 --- /dev/null +++ b/features/referral/api/build.gradle.kts @@ -0,0 +1,20 @@ +plugins { + alias(deps.plugins.android.library) + alias(deps.plugins.kotlin.android) + alias(deps.plugins.kotlin.serialization) + id("kotlin-parcelize") + id("configuration") +} + +android { + namespace = "com.tangem.features.referral.api" +} + +dependencies { + /* Project - Core */ + implementation(projects.core.decompose) + implementation(projects.core.ui) + + /* Project - Domain */ + implementation(projects.domain.wallets.models) +} \ No newline at end of file diff --git a/features/referral/api/src/main/kotlin/com/tangem/feature/referral/api/ReferralComponent.kt b/features/referral/api/src/main/kotlin/com/tangem/feature/referral/api/ReferralComponent.kt new file mode 100644 index 0000000000..de0cda3a93 --- /dev/null +++ b/features/referral/api/src/main/kotlin/com/tangem/feature/referral/api/ReferralComponent.kt @@ -0,0 +1,14 @@ +package com.tangem.feature.referral.api + +import com.tangem.core.decompose.factory.ComponentFactory +import com.tangem.core.ui.decompose.ComposableContentComponent +import com.tangem.domain.wallets.models.UserWalletId + +interface ReferralComponent : ComposableContentComponent { + + data class Params( + val userWalletId: UserWalletId, + ) + + interface Factory : ComponentFactory +} \ No newline at end of file diff --git a/features/referral/domain/build.gradle.kts b/features/referral/domain/build.gradle.kts index a77d439bbb..0ca36ddd1a 100644 --- a/features/referral/domain/build.gradle.kts +++ b/features/referral/domain/build.gradle.kts @@ -13,6 +13,7 @@ dependencies { /** Libs */ implementation(projects.core.utils) + implementation(projects.core.decompose) /** Core modules */ implementation(projects.libs.crypto) diff --git a/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/di/ReferralDomainModule.kt b/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/di/ReferralDomainModule.kt index 172c41b27d..07ec550009 100644 --- a/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/di/ReferralDomainModule.kt +++ b/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/di/ReferralDomainModule.kt @@ -1,5 +1,7 @@ package com.tangem.feature.referral.domain.di +import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.DecomposeComponent import com.tangem.domain.card.DerivePublicKeysUseCase import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase import com.tangem.domain.wallets.usecase.GetUserWalletUseCase @@ -10,15 +12,13 @@ import com.tangem.lib.crypto.UserWalletManager import dagger.Module import dagger.Provides import dagger.hilt.InstallIn -import dagger.hilt.android.components.ViewModelComponent -import dagger.hilt.android.scopes.ViewModelScoped @Module -@InstallIn(ViewModelComponent::class) +@InstallIn(DecomposeComponent::class) class ReferralDomainModule { @Provides - @ViewModelScoped + @ComponentScoped fun provideReferralInteractor( referralRepository: ReferralRepository, userWalletManager: UserWalletManager, diff --git a/features/referral/presentation/.gitignore b/features/referral/impl/.gitignore similarity index 100% rename from features/referral/presentation/.gitignore rename to features/referral/impl/.gitignore diff --git a/features/referral/presentation/build.gradle.kts b/features/referral/impl/build.gradle.kts similarity index 93% rename from features/referral/presentation/build.gradle.kts rename to features/referral/impl/build.gradle.kts index 6ee99e86cb..cf2272bee5 100644 --- a/features/referral/presentation/build.gradle.kts +++ b/features/referral/impl/build.gradle.kts @@ -11,6 +11,9 @@ android { } dependencies { + /** Api */ + api(projects.features.referral.api) + /** Core modules */ implementation(projects.core.analytics) implementation(projects.core.analytics.models) @@ -18,6 +21,7 @@ dependencies { implementation(projects.core.res) implementation(projects.core.utils) implementation(projects.core.ui) + implementation(projects.core.decompose) implementation(projects.libs.crypto) implementation(projects.common.routing) diff --git a/features/referral/impl/src/main/java/com/tangem/feature/referral/DefaultReferralComponent.kt b/features/referral/impl/src/main/java/com/tangem/feature/referral/DefaultReferralComponent.kt new file mode 100644 index 0000000000..f30cefaab8 --- /dev/null +++ b/features/referral/impl/src/main/java/com/tangem/feature/referral/DefaultReferralComponent.kt @@ -0,0 +1,30 @@ +package com.tangem.feature.referral + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.tangem.core.decompose.context.AppComponentContext +import com.tangem.core.decompose.model.getOrCreateModel +import com.tangem.feature.referral.api.ReferralComponent +import com.tangem.feature.referral.model.ReferralModel +import com.tangem.feature.referral.ui.ReferralScreen +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject + +class DefaultReferralComponent @AssistedInject constructor( + @Assisted appComponentContext: AppComponentContext, + @Assisted params: ReferralComponent.Params, +) : ReferralComponent, AppComponentContext by appComponentContext { + + private val model: ReferralModel = getOrCreateModel(params) + + @Composable + override fun Content(modifier: Modifier) { + ReferralScreen(stateHolder = model.uiState) + } + + @AssistedFactory + interface Factory : ReferralComponent.Factory { + override fun create(context: AppComponentContext, params: ReferralComponent.Params): DefaultReferralComponent + } +} \ No newline at end of file diff --git a/features/referral/presentation/src/main/java/com/tangem/feature/referral/analytics/ReferralEvents.kt b/features/referral/impl/src/main/java/com/tangem/feature/referral/analytics/ReferralEvents.kt similarity index 100% rename from features/referral/presentation/src/main/java/com/tangem/feature/referral/analytics/ReferralEvents.kt rename to features/referral/impl/src/main/java/com/tangem/feature/referral/analytics/ReferralEvents.kt diff --git a/features/referral/impl/src/main/java/com/tangem/feature/referral/di/ComponentModule.kt b/features/referral/impl/src/main/java/com/tangem/feature/referral/di/ComponentModule.kt new file mode 100644 index 0000000000..54355a0a6c --- /dev/null +++ b/features/referral/impl/src/main/java/com/tangem/feature/referral/di/ComponentModule.kt @@ -0,0 +1,25 @@ +package com.tangem.feature.referral.di + +import com.tangem.core.decompose.model.Model +import com.tangem.feature.referral.DefaultReferralComponent +import com.tangem.feature.referral.api.ReferralComponent +import com.tangem.feature.referral.model.ReferralModel +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import dagger.multibindings.ClassKey +import dagger.multibindings.IntoMap + +@Module +@InstallIn(SingletonComponent::class) +internal interface ComponentModule { + + @Binds + fun provideReferralComponentFactory(impl: DefaultReferralComponent.Factory): ReferralComponent.Factory + + @Binds + @IntoMap + @ClassKey(ReferralModel::class) + fun bindModel(model: ReferralModel): Model +} \ No newline at end of file diff --git a/features/referral/presentation/src/main/java/com/tangem/feature/referral/viewmodels/ReferralViewModel.kt b/features/referral/impl/src/main/java/com/tangem/feature/referral/model/ReferralModel.kt similarity index 78% rename from features/referral/presentation/src/main/java/com/tangem/feature/referral/viewmodels/ReferralViewModel.kt rename to features/referral/impl/src/main/java/com/tangem/feature/referral/model/ReferralModel.kt index 57d35abc7d..621ddbe1aa 100644 --- a/features/referral/presentation/src/main/java/com/tangem/feature/referral/viewmodels/ReferralViewModel.kt +++ b/features/referral/impl/src/main/java/com/tangem/feature/referral/model/ReferralModel.kt @@ -1,21 +1,20 @@ -package com.tangem.feature.referral.viewmodels +package com.tangem.feature.referral.model -import android.os.Bundle +import androidx.compose.runtime.Stable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue -import androidx.lifecycle.SavedStateHandle -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.tangem.common.routing.AppRoute -import com.tangem.common.routing.bundle.unbundle +import com.tangem.common.routing.AppRouter import com.tangem.core.analytics.api.AnalyticsEventHandler +import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.model.Model +import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.navigation.share.ShareManager import com.tangem.core.navigation.url.UrlOpener import com.tangem.domain.demo.IsDemoCardUseCase -import com.tangem.domain.wallets.models.UserWalletId import com.tangem.domain.wallets.usecase.GetUserWalletUseCase import com.tangem.feature.referral.analytics.ReferralEvents +import com.tangem.feature.referral.api.ReferralComponent import com.tangem.feature.referral.domain.ReferralInteractor import com.tangem.feature.referral.domain.errors.ReferralError import com.tangem.feature.referral.domain.models.DiscountType @@ -25,29 +24,26 @@ import com.tangem.feature.referral.models.DemoModeException import com.tangem.feature.referral.models.ReferralStateHolder import com.tangem.feature.referral.models.ReferralStateHolder.ErrorSnackbar import com.tangem.feature.referral.models.ReferralStateHolder.ReferralInfoState -import com.tangem.feature.referral.router.ReferralRouter -import dagger.hilt.android.lifecycle.HiltViewModel +import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.launch import javax.inject.Inject -import kotlin.properties.Delegates @Suppress("LongParameterList") -@HiltViewModel -internal class ReferralViewModel @Inject constructor( +@Stable +@ComponentScoped +internal class ReferralModel @Inject constructor( + paramsContainer: ParamsContainer, + override val dispatchers: CoroutineDispatcherProvider, private val referralInteractor: ReferralInteractor, private val analyticsEventHandler: AnalyticsEventHandler, private val shareManager: ShareManager, private val urlOpener: UrlOpener, private val getUserWalletUseCase: GetUserWalletUseCase, private val isDemoCardUseCase: IsDemoCardUseCase, - savedStateHandle: SavedStateHandle, -) : ViewModel() { + private val appRouter: AppRouter, +) : Model() { - private val userWalletId = savedStateHandle.get(AppRoute.ReferralProgram.USER_WALLET_ID_KEY) - ?.unbundle(UserWalletId.serializer()) - ?: error("User wallet ID is required for Referral screen") - - private var referralRouter: ReferralRouter by Delegates.notNull() + private val params = paramsContainer.require() private var lastReferralData: ReferralData? = null @@ -55,20 +51,14 @@ internal class ReferralViewModel @Inject constructor( private set init { + analyticsEventHandler.send(ReferralEvents.ReferralScreenOpened) loadReferralData() } - fun setRouter(router: ReferralRouter) { - referralRouter = router - uiState = uiState.copy(headerState = ReferralStateHolder.HeaderState(onBackClicked = router::back)) - } - - fun onScreenOpened() { - analyticsEventHandler.send(ReferralEvents.ReferralScreenOpened) - } - private fun createInitiallyUiState() = ReferralStateHolder( - headerState = ReferralStateHolder.HeaderState(onBackClicked = { }), + headerState = ReferralStateHolder.HeaderState( + onBackClicked = appRouter::pop, + ), referralInfoState = ReferralInfoState.Loading, errorSnackbar = null, analytics = ReferralStateHolder.Analytics( @@ -80,9 +70,9 @@ internal class ReferralViewModel @Inject constructor( private fun loadReferralData() { uiState = uiState.copy(referralInfoState = ReferralInfoState.Loading) - viewModelScope.launch { + modelScope.launch { runCatching { - referralInteractor.getReferralStatus(userWalletId).apply { + referralInteractor.getReferralStatus(params.userWalletId).apply { lastReferralData = this } } @@ -92,15 +82,15 @@ internal class ReferralViewModel @Inject constructor( } private fun participate() { - val userWallet = getUserWalletUseCase(userWalletId).getOrNull() ?: error("User wallet not found") + val userWallet = getUserWalletUseCase(params.userWalletId).getOrNull() ?: error("User wallet not found") if (isDemoCardUseCase(cardId = userWallet.cardId)) { showErrorSnackbar(DemoModeException()) } else { analyticsEventHandler.send(ReferralEvents.ClickParticipate) uiState = uiState.copy(referralInfoState = ReferralInfoState.Loading) - viewModelScope.launch { - runCatching { referralInteractor.startReferral(userWalletId) } + modelScope.launch { + runCatching { referralInteractor.startReferral(params.userWalletId) } .onSuccess(::showContent) .onFailure { throwable -> if (throwable is ReferralError.UserCancelledException) { @@ -121,7 +111,7 @@ internal class ReferralViewModel @Inject constructor( private fun showErrorSnackbar(throwable: Throwable) { uiState = uiState.copy( - errorSnackbar = ErrorSnackbar(throwable = throwable, onOkClicked = referralRouter::back), + errorSnackbar = ErrorSnackbar(throwable = throwable, onOkClicked = appRouter::pop), ) } diff --git a/features/referral/presentation/src/main/java/com/tangem/feature/referral/models/DemoModeException.kt b/features/referral/impl/src/main/java/com/tangem/feature/referral/models/DemoModeException.kt similarity index 100% rename from features/referral/presentation/src/main/java/com/tangem/feature/referral/models/DemoModeException.kt rename to features/referral/impl/src/main/java/com/tangem/feature/referral/models/DemoModeException.kt diff --git a/features/referral/presentation/src/main/java/com/tangem/feature/referral/models/ReferralStateHolder.kt b/features/referral/impl/src/main/java/com/tangem/feature/referral/models/ReferralStateHolder.kt similarity index 100% rename from features/referral/presentation/src/main/java/com/tangem/feature/referral/models/ReferralStateHolder.kt rename to features/referral/impl/src/main/java/com/tangem/feature/referral/models/ReferralStateHolder.kt diff --git a/features/referral/presentation/src/main/java/com/tangem/feature/referral/ui/AgreementText.kt b/features/referral/impl/src/main/java/com/tangem/feature/referral/ui/AgreementText.kt similarity index 100% rename from features/referral/presentation/src/main/java/com/tangem/feature/referral/ui/AgreementText.kt rename to features/referral/impl/src/main/java/com/tangem/feature/referral/ui/AgreementText.kt diff --git a/features/referral/presentation/src/main/java/com/tangem/feature/referral/ui/NonParticipateBottomBlock.kt b/features/referral/impl/src/main/java/com/tangem/feature/referral/ui/NonParticipateBottomBlock.kt similarity index 100% rename from features/referral/presentation/src/main/java/com/tangem/feature/referral/ui/NonParticipateBottomBlock.kt rename to features/referral/impl/src/main/java/com/tangem/feature/referral/ui/NonParticipateBottomBlock.kt diff --git a/features/referral/presentation/src/main/java/com/tangem/feature/referral/ui/ParticipateBottomBlock.kt b/features/referral/impl/src/main/java/com/tangem/feature/referral/ui/ParticipateBottomBlock.kt similarity index 100% rename from features/referral/presentation/src/main/java/com/tangem/feature/referral/ui/ParticipateBottomBlock.kt rename to features/referral/impl/src/main/java/com/tangem/feature/referral/ui/ParticipateBottomBlock.kt diff --git a/features/referral/presentation/src/main/java/com/tangem/feature/referral/ui/ReferralScreen.kt b/features/referral/impl/src/main/java/com/tangem/feature/referral/ui/ReferralScreen.kt similarity index 100% rename from features/referral/presentation/src/main/java/com/tangem/feature/referral/ui/ReferralScreen.kt rename to features/referral/impl/src/main/java/com/tangem/feature/referral/ui/ReferralScreen.kt diff --git a/features/referral/presentation/src/main/java/com/tangem/feature/referral/ReferralFragment.kt b/features/referral/presentation/src/main/java/com/tangem/feature/referral/ReferralFragment.kt deleted file mode 100644 index cec296cc80..0000000000 --- a/features/referral/presentation/src/main/java/com/tangem/feature/referral/ReferralFragment.kt +++ /dev/null @@ -1,37 +0,0 @@ -package com.tangem.feature.referral - -import android.os.Bundle -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.fragment.app.viewModels -import com.tangem.common.routing.AppRouter -import com.tangem.core.ui.UiDependencies -import com.tangem.core.ui.screen.ComposeFragment -import com.tangem.feature.referral.router.ReferralRouter -import com.tangem.feature.referral.ui.ReferralScreen -import com.tangem.feature.referral.viewmodels.ReferralViewModel -import dagger.hilt.android.AndroidEntryPoint -import javax.inject.Inject - -@AndroidEntryPoint -class ReferralFragment : ComposeFragment() { - - @Inject - override lateinit var uiDependencies: UiDependencies - - @Inject - internal lateinit var appRouter: AppRouter - - private val viewModel by viewModels() - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - viewModel.onScreenOpened() - viewModel.setRouter(ReferralRouter(appRouter)) - } - - @Composable - override fun ScreenContent(modifier: Modifier) { - ReferralScreen(stateHolder = viewModel.uiState) - } -} \ No newline at end of file diff --git a/features/referral/presentation/src/main/java/com/tangem/feature/referral/router/ReferralRouter.kt b/features/referral/presentation/src/main/java/com/tangem/feature/referral/router/ReferralRouter.kt deleted file mode 100644 index a8ac11e54b..0000000000 --- a/features/referral/presentation/src/main/java/com/tangem/feature/referral/router/ReferralRouter.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.tangem.feature.referral.router - -import com.tangem.common.routing.AppRouter - -internal class ReferralRouter( - private val appRouter: AppRouter, -) { - - fun back() { - appRouter.pop() - } -} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index b89a9482f9..ddb8968ba6 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -171,9 +171,10 @@ include(":features:onboarding") include(":features:onboarding-v2:api") include(":features:onboarding-v2:impl") +include(":features:referral:api") include(":features:referral:data") include(":features:referral:domain") -include(":features:referral:presentation") +include(":features:referral:impl") include(":features:swap:api") include(":features:swap:data") From 5507c2249b5b3b37e208a96a1882f00dd04f2de3 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 25 Feb 2025 10:31:26 +0300 Subject: [PATCH 29/33] Updated on 2026-08-14 --- data/visa/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/visa/build.gradle.kts b/data/visa/build.gradle.kts index b2f273b514..a4adc23b0f 100644 --- a/data/visa/build.gradle.kts +++ b/data/visa/build.gradle.kts @@ -29,7 +29,7 @@ dependencies { implementation(projects.libs.blockchainSdk) /** Project - Libs */ - debugImplementation(projects.libs.visa) + implementation(projects.libs.visa) /** Libs - Other */ implementation(deps.kotlin.coroutines) From c70afd815e71c303cfaf8c9c8ba80ab012e5b81e Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 25 Feb 2025 13:21:07 +0300 Subject: [PATCH 30/33] Updated on 2026-08-14 --- .../main/java/com/tangem/tap/MainActivity.kt | 4 -- .../tap/proxy/redux/DaggerGraphState.kt | 2 - .../tangem/tap/routing/utils/ChildFactory.kt | 18 ++++++-- .../v2/multiwallet/impl/ui/WalletArtwork.kt | 9 +++- .../push-notifications/api/build.gradle.kts | 3 +- .../api/PushNotificationsComponent.kt | 9 ++++ .../api/navigation/PushNotificationsRouter.kt | 8 ---- .../push-notifications/impl/build.gradle.kts | 1 + .../impl/DefaultPushNotificationsComponent.kt | 42 +++++++++++++++++++ .../impl/PushNotificationsFragment.kt | 39 ----------------- .../impl/di/PushNotificationsModule.kt | 33 ++++++++------- .../PushNotificationsClickIntents.kt | 2 +- .../PushNotificationsModel.kt} | 35 +++++++++------- .../DefaultPushNotificationsRouter.kt | 18 -------- .../InnerPushNotificationsRouter.kt | 8 ---- 15 files changed, 112 insertions(+), 119 deletions(-) create mode 100644 features/push-notifications/api/src/main/java/com/tangem/features/pushnotifications/api/PushNotificationsComponent.kt delete mode 100644 features/push-notifications/api/src/main/java/com/tangem/features/pushnotifications/api/navigation/PushNotificationsRouter.kt create mode 100644 features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/DefaultPushNotificationsComponent.kt delete mode 100644 features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/PushNotificationsFragment.kt rename features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/{presentation/viewmodel => model}/PushNotificationsClickIntents.kt (67%) rename features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/{presentation/viewmodel/PushNotificationViewModel.kt => model/PushNotificationsModel.kt} (69%) delete mode 100644 features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/navigation/DefaultPushNotificationsRouter.kt delete mode 100644 features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/navigation/InnerPushNotificationsRouter.kt diff --git a/app/src/main/java/com/tangem/tap/MainActivity.kt b/app/src/main/java/com/tangem/tap/MainActivity.kt index 20410b9a00..3e81d97a82 100644 --- a/app/src/main/java/com/tangem/tap/MainActivity.kt +++ b/app/src/main/java/com/tangem/tap/MainActivity.kt @@ -62,7 +62,6 @@ import com.tangem.domain.tokens.GetPolkadotCheckHasResetUseCase import com.tangem.domain.wallets.legacy.UserWalletsListManager import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent import com.tangem.features.onboarding.v2.OnboardingV2FeatureToggles -import com.tangem.features.pushnotifications.api.navigation.PushNotificationsRouter import com.tangem.features.pushnotifications.api.utils.PUSH_PERMISSION import com.tangem.features.wallet.navigation.WalletRouter import com.tangem.google.GoogleServicesHelper @@ -176,9 +175,6 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac @Inject internal lateinit var routingComponentFactory: RoutingComponent.Factory - @Inject - lateinit var pushNotificationsRouter: PushNotificationsRouter - @Inject lateinit var cardRepository: CardRepository diff --git a/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt b/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt index 3c36d9833b..08b6c9ba8a 100644 --- a/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt +++ b/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt @@ -33,7 +33,6 @@ 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.features.pushnotifications.api.navigation.PushNotificationsRouter import com.tangem.tap.domain.scanCard.CardScanningFeatureToggles import com.tangem.tap.domain.walletconnect2.domain.LegacyWalletConnectRepository import com.tangem.tap.domain.walletconnect2.domain.WalletConnectInteractor @@ -67,7 +66,6 @@ data class DaggerGraphState( val urlOpener: UrlOpener? = null, val shareManager: ShareManager? = null, val appRouter: AppRouter? = null, - val pushNotificationsRouter: PushNotificationsRouter? = null, val transactionSignerFactory: TransactionSignerFactory? = null, val getUserCountryUseCase: GetUserCountryUseCase? = null, val onrampFeatureToggles: OnrampFeatureToggles? = null, diff --git a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt index bcea27fccd..52cf5cc8ee 100644 --- a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt +++ b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt @@ -13,7 +13,7 @@ import com.tangem.features.managetokens.component.ManageTokensSource import com.tangem.features.markets.details.MarketsTokenDetailsComponent import com.tangem.features.onboarding.v2.entry.OnboardingEntryComponent import com.tangem.features.onramp.component.* -import com.tangem.features.pushnotifications.api.navigation.PushNotificationsRouter +import com.tangem.features.pushnotifications.api.PushNotificationsComponent import com.tangem.features.send.api.SendComponent import com.tangem.features.swap.SwapComponent import com.tangem.features.staking.api.StakingComponent @@ -72,9 +72,9 @@ internal class ChildFactory @Inject constructor( private val securityModeComponentFactory: SecurityModeComponent.Factory, private val resetCardComponentFactory: ResetCardComponent.Factory, private val referralComponentFactory: ReferralComponent.Factory, + private val pushNotificationsComponentFactory: PushNotificationsComponent.Factory, private val walletRouter: WalletRouter, private val testerRouter: TesterRouter, - private val pushNotificationRouter: PushNotificationsRouter, private val routingFeatureToggles: RoutingFeatureToggles, ) { @@ -350,13 +350,19 @@ internal class ChildFactory @Inject constructor( componentFactory = referralComponentFactory, ) } + is AppRoute.PushNotification -> { + createComponentChild( + contextProvider = contextProvider(route, contextFactory), + params = Unit, + componentFactory = pushNotificationsComponentFactory, + ) + } is AppRoute.SaveWallet, is AppRoute.OnboardingNote, is AppRoute.OnboardingOther, is AppRoute.OnboardingTwins, is AppRoute.OnboardingWallet, is AppRoute.Wallet, - is AppRoute.PushNotification, -> error("Unsupported route: $route") } // endregion @@ -551,7 +557,11 @@ internal class ChildFactory @Inject constructor( ) } is AppRoute.PushNotification -> { - route.asFragmentChild(Provider { pushNotificationRouter.entryFragment() }) + route.asComponentChild( + contextProvider = contextProvider(route, contextFactory), + params = Unit, + componentFactory = pushNotificationsComponentFactory, + ) } is AppRoute.WalletSettings -> { route.asComponentChild( diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/ui/WalletArtwork.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/ui/WalletArtwork.kt index 78d304117a..6ba4014a77 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/ui/WalletArtwork.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/ui/WalletArtwork.kt @@ -2,10 +2,12 @@ package com.tangem.features.onboarding.v2.multiwallet.impl.ui +import android.content.res.Configuration import androidx.compose.animation.core.Transition import androidx.compose.animation.core.animateFloat import androidx.compose.animation.core.updateTransition import androidx.compose.foundation.Canvas +import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.material3.Button import androidx.compose.material3.Text @@ -106,7 +108,7 @@ fun WalletArtworks( } } - val circleColor = TangemTheme.colors.background.secondary + val circleColor = TangemTheme.colors.button.secondary Canvas( modifier = Modifier @@ -451,11 +453,14 @@ private fun WalletArtworksState.toTransitionSetState(maxWidthDp: Float, maxHeigh } @Preview(showBackground = true, widthDp = 360, heightDp = 640) +@Preview(showBackground = true, widthDp = 360, heightDp = 640, uiMode = Configuration.UI_MODE_NIGHT_YES) @Composable private fun Preview() { TangemThemePreview { Box( - modifier = Modifier.fillMaxSize(), + modifier = Modifier + .background(TangemTheme.colors.background.primary) + .fillMaxSize(), contentAlignment = Alignment.Center, ) { var state: WalletArtworksState by remember { mutableStateOf(WalletArtworksState.Folded) } diff --git a/features/push-notifications/api/build.gradle.kts b/features/push-notifications/api/build.gradle.kts index 8fd2b5a11b..3366d4511c 100644 --- a/features/push-notifications/api/build.gradle.kts +++ b/features/push-notifications/api/build.gradle.kts @@ -9,10 +9,11 @@ android { } dependencies { - /** AndroidX */ implementation(deps.androidx.fragment.ktx) /** Core */ + implementation(projects.core.decompose) + implementation(projects.core.ui) implementation(projects.core.analytics.models) } \ No newline at end of file diff --git a/features/push-notifications/api/src/main/java/com/tangem/features/pushnotifications/api/PushNotificationsComponent.kt b/features/push-notifications/api/src/main/java/com/tangem/features/pushnotifications/api/PushNotificationsComponent.kt new file mode 100644 index 0000000000..515492abe3 --- /dev/null +++ b/features/push-notifications/api/src/main/java/com/tangem/features/pushnotifications/api/PushNotificationsComponent.kt @@ -0,0 +1,9 @@ +package com.tangem.features.pushnotifications.api + +import com.tangem.core.decompose.factory.ComponentFactory +import com.tangem.core.ui.decompose.ComposableContentComponent + +interface PushNotificationsComponent : ComposableContentComponent { + + interface Factory : ComponentFactory +} \ No newline at end of file diff --git a/features/push-notifications/api/src/main/java/com/tangem/features/pushnotifications/api/navigation/PushNotificationsRouter.kt b/features/push-notifications/api/src/main/java/com/tangem/features/pushnotifications/api/navigation/PushNotificationsRouter.kt deleted file mode 100644 index 6881437671..0000000000 --- a/features/push-notifications/api/src/main/java/com/tangem/features/pushnotifications/api/navigation/PushNotificationsRouter.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.tangem.features.pushnotifications.api.navigation - -import androidx.fragment.app.Fragment - -interface PushNotificationsRouter { - - fun entryFragment(): Fragment -} \ No newline at end of file diff --git a/features/push-notifications/impl/build.gradle.kts b/features/push-notifications/impl/build.gradle.kts index de3b57819b..184fccb455 100644 --- a/features/push-notifications/impl/build.gradle.kts +++ b/features/push-notifications/impl/build.gradle.kts @@ -26,6 +26,7 @@ dependencies { implementation(deps.kotlin.immutable.collections) /** Core modules */ + implementation(projects.core.decompose) implementation(projects.core.ui) implementation(projects.core.configToggles) implementation(projects.core.navigation) diff --git a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/DefaultPushNotificationsComponent.kt b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/DefaultPushNotificationsComponent.kt new file mode 100644 index 0000000000..d2ba519029 --- /dev/null +++ b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/DefaultPushNotificationsComponent.kt @@ -0,0 +1,42 @@ +package com.tangem.features.pushnotifications.impl + +import androidx.activity.compose.BackHandler +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import com.tangem.core.decompose.context.AppComponentContext +import com.tangem.core.decompose.model.getOrCreateModel +import com.tangem.core.ui.components.NavigationBar3ButtonsScrim +import com.tangem.core.ui.utils.findActivity +import com.tangem.features.pushnotifications.api.PushNotificationsComponent +import com.tangem.features.pushnotifications.impl.model.PushNotificationsModel +import com.tangem.features.pushnotifications.impl.presentation.ui.PushNotificationsScreen +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject + +internal class DefaultPushNotificationsComponent @AssistedInject constructor( + @Assisted appComponentContext: AppComponentContext, + @Assisted params: Unit, +) : PushNotificationsComponent, AppComponentContext by appComponentContext { + + private val model: PushNotificationsModel = getOrCreateModel(params) + + @Composable + override fun Content(modifier: Modifier) { + val activity = LocalContext.current.findActivity() + BackHandler(onBack = { activity.finish() }) + NavigationBar3ButtonsScrim() + PushNotificationsScreen( + onRequest = model::onRequest, + onNeverRequest = model::onNeverRequest, + onAllowPermission = model::onAllowPermission, + onDenyPermission = model::onDenyPermission, + ) + } + + @AssistedFactory + interface Factory : PushNotificationsComponent.Factory { + override fun create(context: AppComponentContext, params: Unit): DefaultPushNotificationsComponent + } +} \ No newline at end of file diff --git a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/PushNotificationsFragment.kt b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/PushNotificationsFragment.kt deleted file mode 100644 index c7110e411f..0000000000 --- a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/PushNotificationsFragment.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.tangem.features.pushnotifications.impl - -import androidx.activity.compose.BackHandler -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.fragment.app.viewModels -import com.tangem.core.ui.UiDependencies -import com.tangem.core.ui.components.NavigationBar3ButtonsScrim -import com.tangem.core.ui.screen.ComposeFragment -import com.tangem.features.pushnotifications.impl.presentation.ui.PushNotificationsScreen -import com.tangem.features.pushnotifications.impl.presentation.viewmodel.PushNotificationViewModel -import dagger.hilt.android.AndroidEntryPoint -import javax.inject.Inject - -@AndroidEntryPoint -internal class PushNotificationsFragment : ComposeFragment() { - - @Inject - override lateinit var uiDependencies: UiDependencies - - private val viewModel by viewModels() - - @Composable - override fun ScreenContent(modifier: Modifier) { - BackHandler(onBack = requireActivity()::finish) - NavigationBar3ButtonsScrim() - PushNotificationsScreen( - onRequest = viewModel::onRequest, - onNeverRequest = viewModel::onNeverRequest, - onAllowPermission = viewModel::onAllowPermission, - onDenyPermission = viewModel::onDenyPermission, - ) - } - - companion object { - /** Create push notifications fragment instance */ - fun create(): PushNotificationsFragment = PushNotificationsFragment() - } -} \ No newline at end of file diff --git a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/di/PushNotificationsModule.kt b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/di/PushNotificationsModule.kt index b568880483..edbd3dc188 100644 --- a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/di/PushNotificationsModule.kt +++ b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/di/PushNotificationsModule.kt @@ -1,24 +1,25 @@ package com.tangem.features.pushnotifications.impl.di -import com.tangem.common.routing.AppRouter -import com.tangem.features.pushnotifications.api.navigation.PushNotificationsRouter -import com.tangem.features.pushnotifications.impl.navigation.DefaultPushNotificationsRouter +import com.tangem.core.decompose.model.Model +import com.tangem.features.pushnotifications.api.PushNotificationsComponent +import com.tangem.features.pushnotifications.impl.DefaultPushNotificationsComponent +import com.tangem.features.pushnotifications.impl.model.PushNotificationsModel +import dagger.Binds import dagger.Module -import dagger.Provides import dagger.hilt.InstallIn -import dagger.hilt.android.components.ActivityComponent -import dagger.hilt.android.scopes.ActivityScoped +import dagger.hilt.components.SingletonComponent +import dagger.multibindings.ClassKey +import dagger.multibindings.IntoMap -/** - * DI module provides implementation of [PushNotificationsRouter] - */ @Module -@InstallIn(ActivityComponent::class) -object PushNotificationsModule { +@InstallIn(SingletonComponent::class) +internal interface PushNotificationsModule { - @Provides - @ActivityScoped - fun provideDisclaimerRouter(appRouter: AppRouter): PushNotificationsRouter { - return DefaultPushNotificationsRouter(appRouter) - } + @Binds + fun bindComponentFactory(impl: DefaultPushNotificationsComponent.Factory): PushNotificationsComponent.Factory + + @Binds + @IntoMap + @ClassKey(PushNotificationsModel::class) + fun bindModel(model: PushNotificationsModel): Model } \ No newline at end of file diff --git a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/presentation/viewmodel/PushNotificationsClickIntents.kt b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/model/PushNotificationsClickIntents.kt similarity index 67% rename from features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/presentation/viewmodel/PushNotificationsClickIntents.kt rename to features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/model/PushNotificationsClickIntents.kt index 63100190b7..99b02a379c 100644 --- a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/presentation/viewmodel/PushNotificationsClickIntents.kt +++ b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/model/PushNotificationsClickIntents.kt @@ -1,4 +1,4 @@ -package com.tangem.features.pushnotifications.impl.presentation.viewmodel +package com.tangem.features.pushnotifications.impl.model internal interface PushNotificationsClickIntents { fun onRequest() diff --git a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/presentation/viewmodel/PushNotificationViewModel.kt b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/model/PushNotificationsModel.kt similarity index 69% rename from features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/presentation/viewmodel/PushNotificationViewModel.kt rename to features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/model/PushNotificationsModel.kt index b760936b5b..4043db3350 100644 --- a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/presentation/viewmodel/PushNotificationViewModel.kt +++ b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/model/PushNotificationsModel.kt @@ -1,26 +1,29 @@ -package com.tangem.features.pushnotifications.impl.presentation.viewmodel +package com.tangem.features.pushnotifications.impl.model -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope +import androidx.compose.runtime.Stable +import com.tangem.common.routing.AppRoute +import com.tangem.common.routing.AppRouter import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.models.AnalyticsParam +import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.model.Model import com.tangem.domain.settings.NeverRequestPermissionUseCase import com.tangem.domain.settings.NeverToInitiallyAskPermissionUseCase import com.tangem.features.pushnotifications.api.analytics.PushNotificationAnalyticEvents import com.tangem.features.pushnotifications.api.utils.PUSH_PERMISSION -import com.tangem.features.pushnotifications.impl.navigation.DefaultPushNotificationsRouter -import dagger.hilt.android.lifecycle.HiltViewModel +import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.launch import javax.inject.Inject -@Suppress("LongParameterList") -@HiltViewModel -internal class PushNotificationViewModel @Inject constructor( +@Stable +@ComponentScoped +class PushNotificationsModel @Inject constructor( + override val dispatchers: CoroutineDispatcherProvider, private val neverRequestPermissionUseCase: NeverRequestPermissionUseCase, private val neverToInitiallyAskPermissionUseCase: NeverToInitiallyAskPermissionUseCase, - private val router: DefaultPushNotificationsRouter, + private val appRouter: AppRouter, private val analyticHandler: AnalyticsEventHandler, -) : ViewModel(), PushNotificationsClickIntents { +) : Model(), PushNotificationsClickIntents { override fun onRequest() { analyticHandler.send( @@ -32,10 +35,10 @@ internal class PushNotificationViewModel @Inject constructor( analyticHandler.send( PushNotificationAnalyticEvents.ButtonLater(AnalyticsParam.ScreensSources.Stories), ) - viewModelScope.launch { + modelScope.launch { neverRequestPermissionUseCase(PUSH_PERMISSION) neverToInitiallyAskPermissionUseCase(PUSH_PERMISSION) - router.openHome() + appRouter.push(AppRoute.Home) } } @@ -43,10 +46,10 @@ internal class PushNotificationViewModel @Inject constructor( analyticHandler.send( PushNotificationAnalyticEvents.PermissionStatus(isAllowed = true), ) - viewModelScope.launch { + modelScope.launch { neverRequestPermissionUseCase(PUSH_PERMISSION) neverToInitiallyAskPermissionUseCase(PUSH_PERMISSION) - router.openHome() + appRouter.push(AppRoute.Home) } } @@ -54,10 +57,10 @@ internal class PushNotificationViewModel @Inject constructor( analyticHandler.send( PushNotificationAnalyticEvents.PermissionStatus(isAllowed = false), ) - viewModelScope.launch { + modelScope.launch { neverRequestPermissionUseCase(PUSH_PERMISSION) neverToInitiallyAskPermissionUseCase(PUSH_PERMISSION) - router.openHome() + appRouter.push(AppRoute.Home) } } } \ No newline at end of file diff --git a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/navigation/DefaultPushNotificationsRouter.kt b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/navigation/DefaultPushNotificationsRouter.kt deleted file mode 100644 index b2536cfe47..0000000000 --- a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/navigation/DefaultPushNotificationsRouter.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.tangem.features.pushnotifications.impl.navigation - -import androidx.fragment.app.Fragment -import com.tangem.common.routing.AppRoute -import com.tangem.common.routing.AppRouter -import com.tangem.features.pushnotifications.impl.PushNotificationsFragment -import javax.inject.Inject - -internal class DefaultPushNotificationsRouter @Inject constructor( - private val appRouter: AppRouter, -) : InnerPushNotificationsRouter { - - override fun entryFragment(): Fragment = PushNotificationsFragment.create() - - override fun openHome() { - appRouter.push(AppRoute.Home) - } -} \ No newline at end of file diff --git a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/navigation/InnerPushNotificationsRouter.kt b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/navigation/InnerPushNotificationsRouter.kt deleted file mode 100644 index 20050eca1e..0000000000 --- a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/navigation/InnerPushNotificationsRouter.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.tangem.features.pushnotifications.impl.navigation - -import com.tangem.features.pushnotifications.api.navigation.PushNotificationsRouter - -interface InnerPushNotificationsRouter : PushNotificationsRouter { - - fun openHome() -} \ No newline at end of file From 43975742d55b04f4da731f598d07a7fa58f1fa6d Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 24 Feb 2025 16:13:32 +0500 Subject: [PATCH 31/33] Updated on 2026-08-14 --- .../NavigationButtonsState.kt | 2 +- .../data/staking/DefaultStakingRepository.kt | 9 +++-- .../action/StakingActionCommonType.kt | 2 +- .../analytics/utils/StakingAnalyticSender.kt | 2 +- .../impl/presentation/model/StakingModel.kt | 4 +-- .../state/StakingStateController.kt | 2 +- .../presentation/state/StakingStateRouter.kt | 14 ++++---- .../helpers/StakingFeeTransactionLoader.kt | 2 +- .../state/helpers/StakingTransactionSender.kt | 2 +- .../transformers/SetAmountDataTransformer.kt | 2 +- .../SetButtonsStateTransformer.kt | 17 ++++++--- .../SetConfirmationStateEmptyTransformer.kt | 2 +- .../SetConfirmationStateInitTransformer.kt | 22 ++++++++---- .../SetConfirmationStateLoadingTransformer.kt | 16 +++++---- .../state/transformers/SetTitleTransformer.kt | 4 +-- .../AmountRequirementStateTransformer.kt | 36 +++++++++++++------ .../AddStakingNotificationsTransformer.kt | 4 +-- .../StakingInfoNotificationsFactory.kt | 2 +- .../ValidatorSelectChangeTransformer.kt | 2 +- 19 files changed, 93 insertions(+), 53 deletions(-) diff --git a/common/ui/src/main/java/com/tangem/common/ui/navigationButtons/NavigationButtonsState.kt b/common/ui/src/main/java/com/tangem/common/ui/navigationButtons/NavigationButtonsState.kt index c534f12308..e7788a87df 100644 --- a/common/ui/src/main/java/com/tangem/common/ui/navigationButtons/NavigationButtonsState.kt +++ b/common/ui/src/main/java/com/tangem/common/ui/navigationButtons/NavigationButtonsState.kt @@ -8,7 +8,7 @@ sealed class NavigationButtonsState { data object Empty : NavigationButtonsState() data class Data( - val primaryButton: NavigationButton, + val primaryButton: NavigationButton?, val prevButton: NavigationButton?, val extraButtons: ImmutableList, val txUrl: String? = null, diff --git a/data/staking/src/main/java/com/tangem/data/staking/DefaultStakingRepository.kt b/data/staking/src/main/java/com/tangem/data/staking/DefaultStakingRepository.kt index 620bad0ce9..25634c3787 100644 --- a/data/staking/src/main/java/com/tangem/data/staking/DefaultStakingRepository.kt +++ b/data/staking/src/main/java/com/tangem/data/staking/DefaultStakingRepository.kt @@ -237,7 +237,7 @@ internal class DefaultStakingRepository( ): StakingAction { return withContext(dispatchers.io) { val response = when (params.actionCommonType) { - StakingActionCommonType.Enter -> stakeKitApi.createEnterAction( + is StakingActionCommonType.Enter -> stakeKitApi.createEnterAction( createActionRequestBody( userWalletId, network, @@ -267,7 +267,7 @@ internal class DefaultStakingRepository( ): StakingGasEstimate { return withContext(dispatchers.io) { val gasEstimateDTO = when (params.actionCommonType) { - StakingActionCommonType.Enter -> stakeKitApi.estimateGasOnEnter( + is StakingActionCommonType.Enter -> stakeKitApi.estimateGasOnEnter( createActionRequestBody( userWalletId, network, @@ -582,13 +582,14 @@ internal class DefaultStakingRepository( -> TransactionData.Compiled.Data.Bytes(unsignedTransaction.hexToBytes()) Blockchain.BSC, Blockchain.Ethereum, + Blockchain.TON, + Blockchain.Cardano, -> TransactionData.Compiled.Data.RawString(unsignedTransaction) Blockchain.Tron -> { val tronStakeKitTransaction = tronStakeKitTransactionAdapter.fromJson(unsignedTransaction) ?: error("Failed to parse Tron StakeKit transaction") TransactionData.Compiled.Data.RawString(tronStakeKitTransaction.rawDataHex) } - Blockchain.TON -> TransactionData.Compiled.Data.RawString(unsignedTransaction) else -> error("Unsupported blockchain") } } @@ -647,6 +648,7 @@ internal class DefaultStakingRepository( const val KAVA_INTEGRATION_ID = "kava-kava-native-staking" const val NEAR_INTEGRATION_ID = "near-near-native-staking" const val TEZOS_INTEGRATION_ID = "tezos-xtz-native-staking" + const val CARDANO_INTEGRATION_ID = "cardano-ada-native-staking" const val ETHEREUM_POLYGON_APPROVE_SPENDER = "0x5e3Ef299fDDf15eAa0432E6e66473ace8c13D908" @@ -669,6 +671,7 @@ internal class DefaultStakingRepository( // Blockchain.Kava.run { id + toCoinId() } to KAVA_INTEGRATION_ID, // Blockchain.Near.run { id + toCoinId() } to NEAR_INTEGRATION_ID, // Blockchain.Tezos.run { id + toCoinId() } to TEZOS_INTEGRATION_ID, + Blockchain.Cardano.run { id + toCoinId() } to CARDANO_INTEGRATION_ID, ) } } \ No newline at end of file diff --git a/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/stakekit/action/StakingActionCommonType.kt b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/stakekit/action/StakingActionCommonType.kt index 120dfd0c18..605393dfb4 100644 --- a/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/stakekit/action/StakingActionCommonType.kt +++ b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/stakekit/action/StakingActionCommonType.kt @@ -2,7 +2,7 @@ package com.tangem.domain.staking.model.stakekit.action sealed class StakingActionCommonType { - data object Enter : StakingActionCommonType() + data class Enter(val skipEnterAmount: Boolean) : StakingActionCommonType() data class Exit(val partiallyUnstakeDisabled: Boolean) : StakingActionCommonType() sealed class Pending : StakingActionCommonType() { data object Restake : Pending() diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/analytics/utils/StakingAnalyticSender.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/analytics/utils/StakingAnalyticSender.kt index fdc4685953..e5911ef720 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/analytics/utils/StakingAnalyticSender.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/analytics/utils/StakingAnalyticSender.kt @@ -113,7 +113,7 @@ internal class StakingAnalyticSender( val confirmationState = value.confirmationState as? StakingStates.ConfirmationState.Data return when (value.actionType) { - StakingActionCommonType.Enter -> StakingActionType.STAKE + is StakingActionCommonType.Enter -> StakingActionType.STAKE is StakingActionCommonType.Exit -> StakingActionType.UNSTAKE is StakingActionCommonType.Pending -> confirmationState?.pendingAction?.type ?: StakingActionType.UNKNOWN } diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt index bb2c07e2c4..846032569e 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt @@ -397,7 +397,7 @@ internal class StakingModel @Inject constructor( StakingEvent.ShowAlert(StakingAlertUM.NoAvailableValidators), ) } else { - if (uiState.value.actionType == StakingActionCommonType.Enter) { + if (uiState.value.actionType is StakingActionCommonType.Enter) { stateController.updateAll( ValidatorSelectChangeTransformer( selectedValidator = null, @@ -712,7 +712,7 @@ internal class StakingModel @Inject constructor( ): BigDecimal? { // TODO split for different networks val subtractedBalanceAmount = when (actionType) { - StakingActionCommonType.Enter -> checkAndCalculateSubtractedAmount( + is StakingActionCommonType.Enter -> checkAndCalculateSubtractedAmount( isAmountSubtractAvailable = isAmountSubtractAvailable, cryptoCurrencyStatus = cryptoCurrencyStatus, amountValue = amount.orZero(), diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateController.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateController.kt index e66c38a778..328bf590dd 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateController.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateController.kt @@ -85,7 +85,7 @@ internal class StakingStateController @Inject constructor( isBalanceHidden = false, event = consumedEvent(), bottomSheetConfig = null, - actionType = StakingActionCommonType.Enter, + actionType = StakingActionCommonType.Enter(skipEnterAmount = false), buttonsState = NavigationButtonsState.Empty, balanceState = null, ) diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateRouter.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateRouter.kt index 60afd5cfef..622c27808f 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateRouter.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateRouter.kt @@ -23,11 +23,11 @@ internal class StakingStateRouter( fun onNextClick() { when (stateController.value.currentStep) { StakingStep.InitialInfo -> when (val actionType = stateController.value.actionType) { - StakingActionCommonType.Enter -> showAmount() - is StakingActionCommonType.Exit -> if (actionType.partiallyUnstakeDisabled) { - showConfirmation() - } else { - showAmount() + is StakingActionCommonType.Enter -> { + if (actionType.skipEnterAmount) showConfirmation() else showAmount() + } + is StakingActionCommonType.Exit -> { + if (actionType.partiallyUnstakeDisabled) showConfirmation() else showAmount() } StakingActionCommonType.Pending.Other, StakingActionCommonType.Pending.Rewards, @@ -53,7 +53,9 @@ internal class StakingStateRouter( -> showInitial() StakingStep.Confirmation -> { when (val actionType = uiState.actionType) { - StakingActionCommonType.Enter -> showAmount() + is StakingActionCommonType.Enter -> { + if (actionType.skipEnterAmount) showInitial() else showAmount() + } is StakingActionCommonType.Pending -> showInitial() is StakingActionCommonType.Exit -> { if (actionType.partiallyUnstakeDisabled) showInitial() else showAmount() diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingFeeTransactionLoader.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingFeeTransactionLoader.kt index 6ed1669b40..1688f31bdf 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingFeeTransactionLoader.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingFeeTransactionLoader.kt @@ -63,7 +63,7 @@ internal class StakingFeeTransactionLoader @AssistedInject constructor( val validatorAddress = validatorState.chosenValidator.address - val isEnter = state.actionType == StakingActionCommonType.Enter + val isEnter = state.actionType is StakingActionCommonType.Enter val isApprovalNeeded = confirmationState.isApprovalNeeded val isAllowanceNotEnough = confirmationState.allowance < amount if (isEnter && isApprovalNeeded && isAllowanceNotEnough) { diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingTransactionSender.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingTransactionSender.kt index cc4b4686a5..2810a6d3c3 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingTransactionSender.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingTransactionSender.kt @@ -280,7 +280,7 @@ internal class StakingTransactionSender @AssistedInject constructor( private fun getAmount(amountState: AmountState.Data, fee: Fee, reduceAmountBy: BigDecimal?): BigDecimal { val amountValue = amountState.amountTextField.cryptoAmount.value ?: error("No amount value") val feeValue = fee.amount.value ?: error("No fee value") - val isEnterAction = stateController.value.actionType == StakingActionCommonType.Enter + val isEnterAction = stateController.value.actionType is StakingActionCommonType.Enter return checkAndCalculateSubtractedAmount( isAmountSubtractAvailable = isAmountSubtractAvailable && isEnterAction, diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetAmountDataTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetAmountDataTransformer.kt index d33a64975d..4103633ad5 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetAmountDataTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetAmountDataTransformer.kt @@ -32,7 +32,7 @@ internal class SetAmountDataTransformer( stringReference(userWalletProvider().name) } val cryptoBalanceValue = cryptoCurrencyStatusProvider().value - val (amount, fiatAmount) = if (prevState.actionType != StakingActionCommonType.Enter) { + val (amount, fiatAmount) = if (prevState.actionType !is StakingActionCommonType.Enter) { prevState.balanceState?.cryptoAmount to prevState.balanceState?.fiatAmount } else { cryptoBalanceValue.amount to cryptoBalanceValue.fiatAmount diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetButtonsStateTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetButtonsStateTransformer.kt index 61eb924114..6195aea430 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetButtonsStateTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetButtonsStateTransformer.kt @@ -10,6 +10,7 @@ import com.tangem.core.ui.extensions.resourceReference import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType import com.tangem.features.staking.impl.presentation.state.* import com.tangem.features.staking.impl.presentation.state.utils.getPendingActionTitle +import com.tangem.lib.crypto.BlockchainUtils import com.tangem.utils.extensions.orZero import com.tangem.utils.transformer.Transformer import kotlinx.collections.immutable.ImmutableList @@ -37,7 +38,7 @@ internal class SetButtonsStateTransformer( return prevState.copy(buttonsState = buttonsState) } - private fun getPrimaryButton(prevState: StakingUiState): NavigationButton { + private fun getPrimaryButton(prevState: StakingUiState): NavigationButton? { val confirmState = prevState.confirmationState as? StakingStates.ConfirmationState.Data val innerConfirmState = confirmState?.innerState @@ -54,7 +55,7 @@ internal class SetButtonsStateTransformer( showProgress = isInProgress, isEnabled = prevState.isButtonEnabled(), onClick = { prevState.onPrimaryClick() }, - ) + ).takeIf { prevState.isPrimaryButtonVisible() } } private fun getPrevButton(prevState: StakingUiState): NavigationButton? { @@ -125,7 +126,7 @@ internal class SetButtonsStateTransformer( resourceReference(R.string.common_close) } else { when (actionType) { - StakingActionCommonType.Enter -> { + is StakingActionCommonType.Enter -> { val amount = amountState.amountTextField.cryptoAmount.value.orZero() if (confirmationState.isApprovalNeeded && confirmationState.allowance < amount) { resourceReference(R.string.give_permission_title) @@ -162,7 +163,7 @@ internal class SetButtonsStateTransformer( clickIntents.onNextClick() } else { val amount = amountState.amountTextField.cryptoAmount.value.orZero() - val isEnterAction = actionType == StakingActionCommonType.Enter + val isEnterAction = actionType is StakingActionCommonType.Enter if (isEnterAction && confirmationState.isApprovalNeeded && confirmationState.allowance < amount) { clickIntents.showApprovalBottomSheet() } else { @@ -185,6 +186,14 @@ internal class SetButtonsStateTransformer( -> true } + private fun StakingUiState.isPrimaryButtonVisible(): Boolean { + val initialState = initialInfoState as? StakingStates.InitialInfoState.Data + val hasNotStaking = initialState?.yieldBalance == InnerYieldBalanceState.Empty + val isCardano = BlockchainUtils.isCardano(cryptoCurrencyBlockchainId) + + return hasNotStaking || !(isCardano && currentStep == StakingStep.InitialInfo) + } + private fun StakingUiState.isButtonEnabled(): Boolean { return when (currentStep) { StakingStep.InitialInfo -> initialInfoState.isPrimaryButtonEnabled diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateEmptyTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateEmptyTransformer.kt index 4bf8d5ce5d..c1ab24e015 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateEmptyTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateEmptyTransformer.kt @@ -8,7 +8,7 @@ import com.tangem.utils.transformer.Transformer internal object SetConfirmationStateEmptyTransformer : Transformer { override fun transform(prevState: StakingUiState): StakingUiState { return prevState.copy( - actionType = StakingActionCommonType.Enter, + actionType = StakingActionCommonType.Enter(skipEnterAmount = false), validatorState = StakingStates.ValidatorState.Empty(), confirmationState = StakingStates.ConfirmationState.Empty(), balanceState = null, diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateInitTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateInitTransformer.kt index c55fb7a485..8a2f781acc 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateInitTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateInitTransformer.kt @@ -44,11 +44,17 @@ internal class SetConfirmationStateInitTransformer( override fun transform(prevState: StakingUiState): StakingUiState { val actionType = when { - isEnter -> StakingActionCommonType.Enter - isImplicitExit || isExplicitExit -> StakingActionCommonType.Exit(isPartialUnstakeDisabled(prevState)) + isEnter -> StakingActionCommonType.Enter( + skipEnterAmount = isAmountEnterSkipped(prevState), + ) + isImplicitExit || isExplicitExit -> StakingActionCommonType.Exit(isPartiallyUnstakeDisabled(prevState)) else -> when (pendingAction?.type) { - StakingActionType.STAKE -> StakingActionCommonType.Enter - StakingActionType.UNSTAKE -> StakingActionCommonType.Exit(isPartialUnstakeDisabled(prevState)) + StakingActionType.STAKE -> StakingActionCommonType.Enter( + skipEnterAmount = isAmountEnterSkipped(prevState), + ) + StakingActionType.UNSTAKE -> StakingActionCommonType.Exit( + partiallyUnstakeDisabled = isPartiallyUnstakeDisabled(prevState), + ) StakingActionType.CLAIM_REWARDS, StakingActionType.RESTAKE_REWARDS, -> StakingActionCommonType.Pending.Rewards @@ -71,7 +77,7 @@ internal class SetConfirmationStateInitTransformer( transactionDoneState = TransactionDoneState.Empty, isApprovalNeeded = stakingApproval is StakingApproval.Needed, allowance = stakingAllowance, - isAmountEditable = actionType == StakingActionCommonType.Enter || + isAmountEditable = actionType is StakingActionCommonType.Enter || actionType is StakingActionCommonType.Exit && !actionType.partiallyUnstakeDisabled, reduceAmountBy = null, @@ -81,7 +87,7 @@ internal class SetConfirmationStateInitTransformer( ) } - private fun isPartialUnstakeDisabled(state: StakingUiState): Boolean { + private fun isPartiallyUnstakeDisabled(state: StakingUiState): Boolean { val isSolana = BlockchainUtils.isSolana(state.cryptoCurrencyBlockchainId) val isValidatorPreferred = balanceState?.validator?.preferred == true if (isSolana && !isValidatorPreferred) { @@ -94,4 +100,8 @@ internal class SetConfirmationStateInitTransformer( val max = exitAmount.maximum ?: return false return !min.isPositive() && !max.isPositive() } + + private fun isAmountEnterSkipped(state: StakingUiState): Boolean { + return BlockchainUtils.isCardano(state.cryptoCurrencyBlockchainId) + } } \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateLoadingTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateLoadingTransformer.kt index 723a0ffd7c..30fd4ad88e 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateLoadingTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateLoadingTransformer.kt @@ -4,7 +4,8 @@ import com.tangem.common.ui.amountScreen.models.AmountState 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.fiat +import com.tangem.core.ui.format.bigdecimal.format import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.staking.model.stakekit.Yield import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType @@ -35,14 +36,15 @@ internal class SetConfirmationStateLoadingTransformer( private fun getFooter(state: StakingUiState): TextReference { val amountState = state.amountState as? AmountState.Data - val isEnterAction = state.actionType == StakingActionCommonType.Enter + val isEnterAction = state.actionType is StakingActionCommonType.Enter val amountDecimal = amountState?.amountTextField?.fiatAmount?.value - val amountValue = BigDecimalFormatter.formatFiatAmount( - fiatAmount = amountDecimal, - fiatCurrencyCode = appCurrency.code, - fiatCurrencySymbol = appCurrency.symbol, - ) + val amountValue = amountDecimal.format { + fiat( + fiatCurrencyCode = appCurrency.code, + fiatCurrencySymbol = appCurrency.symbol, + ) + } val rewardSchedule = getRewardScheduleText( rewardSchedule = yield.metadata.rewardSchedule, networkId = cryptoCurrency.network.id.value, diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetTitleTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetTitleTransformer.kt index 46258e60a7..d16bb669e4 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetTitleTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetTitleTransformer.kt @@ -31,7 +31,7 @@ internal object SetTitleTransformer : Transformer { StakingStep.Confirmation -> { when (actionType) { - StakingActionCommonType.Enter -> resourceReference( + is StakingActionCommonType.Enter -> resourceReference( R.string.staking_title_stake, wrappedList(prevState.cryptoCurrencyName), ) @@ -53,7 +53,7 @@ internal object SetTitleTransformer : Transformer { } } - val subtitle = if (currentStep == StakingStep.Confirmation && actionType == StakingActionCommonType.Enter) { + val subtitle = if (currentStep == StakingStep.Confirmation && actionType is StakingActionCommonType.Enter) { stringReference(prevState.walletName) } else { null diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/amount/AmountRequirementStateTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/amount/AmountRequirementStateTransformer.kt index 655b39d571..10e96e7b32 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/amount/AmountRequirementStateTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/amount/AmountRequirementStateTransformer.kt @@ -16,6 +16,7 @@ import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.features.staking.impl.R import com.tangem.lib.crypto.BlockchainUtils.isTron +import com.tangem.utils.extensions.isPositive import com.tangem.utils.isNullOrZero import com.tangem.utils.transformer.Transformer import java.math.BigDecimal @@ -57,7 +58,7 @@ internal class AmountRequirementStateTransformer( amountState.amountTextField.isError -> amountState.amountTextField.error requirementError != null -> requirementError isIntegerOnlyError -> when (actionType) { - StakingActionCommonType.Enter -> resourceReference( + is StakingActionCommonType.Enter -> resourceReference( R.string.staking_amount_tron_integer_error, wrappedList(roundedDownCrypto), ) @@ -92,7 +93,7 @@ internal class AmountRequirementStateTransformer( if (isAlreadyErrorState || isAmountZero) return null return when (actionType) { - StakingActionCommonType.Enter -> { + is StakingActionCommonType.Enter -> { val enterRequirements = yield.args.enter.args[Yield.Args.ArgType.AMOUNT] enterRequirements?.getError(amountDecimal, R.string.staking_amount_requirement_error) } @@ -107,7 +108,7 @@ internal class AmountRequirementStateTransformer( private fun isIntegerOnlyError(amountState: AmountState.Data, actionType: StakingActionCommonType): Boolean { val cryptoAmountValue = amountState.amountTextField.cryptoAmount.value ?: return false - val isEnterOrExit = actionType == StakingActionCommonType.Enter || actionType is StakingActionCommonType.Exit + val isEnterOrExit = actionType is StakingActionCommonType.Enter || actionType is StakingActionCommonType.Exit val isTron = isTron(cryptoCurrencyStatus.currency.network.id.value) val isIntegerOnly = cryptoAmountValue.isZero() || cryptoAmountValue.remainder(BigDecimal.ONE).isZero() @@ -116,17 +117,30 @@ internal class AmountRequirementStateTransformer( } private fun AddressArgument.getError(amount: BigDecimal, @StringRes errorTextRes: Int): TextReference? { - val isExceedsRequirements = maximum?.compareTo(amount) == -1 || - minimum?.compareTo(amount) == 1 + val isExceedsMinRequirement = minimum?.compareTo(amount) == 1 + val isExceedsMaxRequirement = if (maximum?.isPositive() == true) { + maximum?.compareTo(amount) == -1 + } else { + cryptoCurrencyStatus.value.amount?.compareTo(amount) == 1 + } - return resourceReference( - errorTextRes, - wrappedList( + val errorText = when { + isExceedsMinRequirement -> { minimum.format { crypto(cryptoCurrencyStatus.currency) - }, - ), - ).takeIf { required && isExceedsRequirements } + } + } + isExceedsMaxRequirement -> { + maximum.format { + crypto(cryptoCurrencyStatus.currency) + } + } + else -> "" + } + return resourceReference( + errorTextRes, + wrappedList(errorText), + ).takeIf { required && (isExceedsMinRequirement || isExceedsMaxRequirement) } } data class Data( diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/AddStakingNotificationsTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/AddStakingNotificationsTransformer.kt index 6aeb94cc74..7e8f2c875d 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/AddStakingNotificationsTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/AddStakingNotificationsTransformer.kt @@ -65,7 +65,7 @@ internal class AddStakingNotificationsTransformer( val feeValue = feeState?.fee?.amount?.value.orZero() val reduceAmountBy = confirmationState.reduceAmountBy.orZero() - val isEnterAction = prevState.actionType == StakingActionCommonType.Enter + val isEnterAction = prevState.actionType is StakingActionCommonType.Enter val isFeeCoverage = checkFeeCoverage( amountValue = amountValue, feeValue = feeValue, @@ -236,7 +236,7 @@ internal class AddStakingNotificationsTransformer( val showNotification = sendingAmount + feeAmount > balance if (showNotification) { - val notification = if (actionType == StakingActionCommonType.Enter) { + val notification = if (actionType is StakingActionCommonType.Enter) { NotificationUM.Error.TotalExceedsBalance } else { with(cryptoCurrencyStatus.currency) { diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/StakingInfoNotificationsFactory.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/StakingInfoNotificationsFactory.kt index aed53b2408..a88e7ace69 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/StakingInfoNotificationsFactory.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/StakingInfoNotificationsFactory.kt @@ -44,7 +44,7 @@ internal class StakingInfoNotificationsFactory( addStakingLowBalanceNotification(prevState, actionAmount) when (prevState.actionType) { - StakingActionCommonType.Enter -> addEnterInfoNotifications(sendingAmount, feeValue) + is StakingActionCommonType.Enter -> addEnterInfoNotifications(sendingAmount, feeValue) is StakingActionCommonType.Exit -> addExitInfoNotifications() is StakingActionCommonType.Pending -> addPendingInfoNotifications(prevState) } diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/validator/ValidatorSelectChangeTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/validator/ValidatorSelectChangeTransformer.kt index 0f79a3ab26..960c928ca8 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/validator/ValidatorSelectChangeTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/validator/ValidatorSelectChangeTransformer.kt @@ -18,7 +18,7 @@ internal class ValidatorSelectChangeTransformer( val confirmationState = prevState.confirmationState as? StakingStates.ConfirmationState.Data val isRestake = prevState.actionType == StakingActionCommonType.Pending.Restake - val isEnter = prevState.actionType == StakingActionCommonType.Enter + val isEnter = prevState.actionType is StakingActionCommonType.Enter val isFromInfoScreen = prevState.currentStep == StakingStep.InitialInfo val isVoteLocked = confirmationState?.pendingAction?.type == StakingActionType.VOTE_LOCKED From 52996292213d26c08a3732121b3f64cd1bc5496a Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 26 Feb 2025 11:46:02 +0300 Subject: [PATCH 32/33] Updated on 2026-08-14 --- core/res/src/main/res/values-ru/strings.xml | 4 ++++ core/res/src/main/res/values/strings.xml | 7 +++++- .../data/visa/utils/VisaApiRequestMaker.kt | 5 ++++ .../utils/WalletWarningsAnalyticsSender.kt | 1 + .../wallet/state/model/WalletNotification.kt | 13 +++++++++++ .../wallet/state/model/WalletState.kt | 23 +++++++++++++++++++ .../CloseBottomSheetTransformer.kt | 3 +++ .../OpenBottomSheetTransformer.kt | 3 +++ .../transformers/RenameWalletsTransformer.kt | 1 + .../SetBalancesAndLimitsTransformer.kt | 15 ++++++++++++ .../SetRefreshStateTransformer.kt | 1 + .../SetTxHistoryCountErrorTransformer.kt | 1 + .../SetTxHistoryCountTransformer.kt | 1 + .../SetTxHistoryItemsErrorTransformer.kt | 18 ++++++++++++++- .../SetTxHistoryItemsTransformer.kt | 1 + .../SetWalletCardDropDownItemsTransformer.kt | 5 ++++ .../transformers/SetWarningsTransformer.kt | 1 + .../transformers/UnlockWalletTransformer.kt | 3 ++- .../UpdateWalletCardsCountTransformer.kt | 1 + .../viewmodels/intents/WalletClickIntents.kt | 1 + .../intents/WalletWarningsClickIntents.kt | 6 +++++ 21 files changed, 111 insertions(+), 3 deletions(-) diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index 04c5129fac..e7e9bccc89 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -694,6 +694,7 @@ Отсканируйте карту или кольцо, чтобы изменить ее настройки. Изменения затронут только ту карту или кольцо, которые вы отсканировали, и не повлияют на другие устройства, привязанные к вашему кошельку. Приготовьте свой Tangem! Уведомление безопасности + Да На вашем балансе недостаточно средств для продажи криптовалюты. Пожалуйста, пополните нужный актив, чтобы продолжить. Недостаточно средств Продажа криптовалюты в вашем регионе временно недоступна. Мы активно работаем над тем, чтобы добавить эту возможность. Следите за нашими новостями! @@ -897,6 +898,8 @@ Встречайте Tangem Обменивайте, покупайте NFT, получайте займы и делайте вклады в более чем 100 различных децентрализованных сервисах Поддержка Web 3.0 + Для отправки требуется входящая транзакция на сумму не менее %1$s + Недостаточно средств Комиссия сети за одобрение токена будет взиматься за подтверждение того, что именно вы разрешаете использовать ваш токен для обмена. Обменивайте больше токенов по лучшим курсам прямо в вашем кошельке. Новый провайдер обмена! @@ -1110,6 +1113,7 @@ Нравится Tangem? Вам необходимо провести ассоциацию токена для того, чтобы иметь возможность принимать его Необходима плата за аренду сети + Вы обращались в службу поддержки через приложение в течение 7 дней после создания кошелька? Если обращались или не уверены, нажмите «Да» и следуйте инструкциям. Спасибо! Всё в порядке! Дальнейшие действия не требуются. Вы будете перенаправлены на официальный сайт Tangem. Пожалуйста, прочитайте и выполните указанные там инструкции. Вы когда-либо обращались в службу поддержки Tangem напрямую из этого приложения? diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index 15e6dcf94d..8efdb73f1b 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -886,6 +886,8 @@ Meet Tangem Exchange, buy NFT\'s, make loans and deposits in more than 100 different decentralized services Web 3.0 Compatible + An incoming transaction of at least %1$s is required to proceed + Insufficient funds The network will charge a token approval fee to verify that you are authorizing the use of your token for the swap. Exchange more tokens at better rates directly in your wallet. New Swap Provider Available! @@ -985,6 +987,9 @@ Rename wallet Unlock all Unlock all with %s + Unlock + Scan your card to unlock access + Needed unlock Blockchain is unreachable. Try later Scan card or ring This wallet has already been activated earlier.\nIf it was not done by you, please contact support.\nTangem never sells wallets along with pre-generated access codes. @@ -1099,7 +1104,7 @@ You must associate your token before receiving tokens Network rent fee required Action required - Did you contact support via the app or email within 7 days of creating a wallet? If you did or are unsure, follow and complete the instructions. + Did you contact support via the app within 7 days of creating your wallet? If yes, or if you\'re unsure, click \'Yes\' and follow the instructions. Thank you! All set! No further actions required. You will now be redirected to the official Tangem website. Please read and follow instructions there. Have you ever contacted the Tangem support team directly through this application? diff --git a/data/visa/src/main/kotlin/com/tangem/data/visa/utils/VisaApiRequestMaker.kt b/data/visa/src/main/kotlin/com/tangem/data/visa/utils/VisaApiRequestMaker.kt index d06d1fb0de..538c665358 100644 --- a/data/visa/src/main/kotlin/com/tangem/data/visa/utils/VisaApiRequestMaker.kt +++ b/data/visa/src/main/kotlin/com/tangem/data/visa/utils/VisaApiRequestMaker.kt @@ -91,6 +91,11 @@ internal class VisaApiRequestMaker @Inject constructor( private suspend fun getAuthTokens(userWalletId: UserWalletId): VisaAuthTokens { val userWallet = findVisaUserWallet(userWalletId) val status = userWallet.scanResponse.visaCardActivationStatus ?: error("Visa card activation status not found") + + if (status is VisaCardActivationStatus.RefreshTokenExpired) { + throw RefreshTokenExpiredException() + } + return (status as? VisaCardActivationStatus.Activated)?.visaAuthTokens ?: error("Visa card is not activated") } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt index cc8e0c9c5e..12a4cf918c 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt @@ -59,6 +59,7 @@ internal class WalletWarningsAnalyticsSender @Inject constructor( is WalletNotification.Warning.SomeNetworksUnreachable, is WalletNotification.Warning.NetworksUnreachable, is WalletNotification.UsedOutdatedData, + is WalletNotification.UnlockVisaAccess, -> null is WalletNotification.Critical.SeedPhraseNotification -> MainScreen.NoticeSeedPhraseSupport is WalletNotification.Critical.SeedPhraseSecondNotification -> MainScreen.NoticeSeedPhraseSupportSecond diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNotification.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNotification.kt index 6cb194fd18..203a35a3a8 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNotification.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNotification.kt @@ -191,6 +191,19 @@ sealed class WalletNotification(val config: NotificationConfig) { ), ) + data class UnlockVisaAccess(val onUnlockClick: () -> Unit) : WalletNotification( + config = NotificationConfig( + title = resourceReference(id = R.string.visa_unlock_notification_title), + subtitle = resourceReference(id = R.string.visa_unlock_notification_subtitle), + iconResId = R.drawable.ic_locked_24, + buttonsState = NotificationConfig.ButtonsState.PrimaryButtonConfig( + text = resourceReference(id = R.string.visa_unlock_notification_button), + iconResId = R.drawable.ic_tangem_24, + onClick = onUnlockClick, + ), + ), + ) + data class RateApp( val onLikeClick: () -> Unit, val onDislikeClick: () -> Unit, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletState.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletState.kt index 885e370725..42b4839fc4 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletState.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletState.kt @@ -12,6 +12,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.model.holder.TxHistor import com.tangem.feature.wallet.presentation.wallet.state.model.holder.WalletStateHolder import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.PersistentList +import kotlinx.collections.immutable.persistentListOf internal const val NOT_INITIALIZED_WALLET_INDEX = -1 @@ -115,5 +116,27 @@ internal sealed interface WalletState : WalletStateHolder { override val balancesAndLimitBlockState: BalancesAndLimitsBlockState? = null } + + data class AccessTokenLocked( + override val walletCardState: WalletCardState, + override val buttons: PersistentList, + override val bottomSheetConfig: TangemBottomSheetConfig?, + val onExploreClick: () -> Unit, + val onUnlockVisaAccessNotificationClick: () -> Unit, + ) : Visa(), + TxHistoryStateHolder by LockedTxHistoryStateHolder(onExploreClick), + WalletStateHolder by LockedWalletStateHolder( + walletCardState = walletCardState, + buttons = buttons, + bottomSheetConfig = bottomSheetConfig, + onUnlockNotificationClick = {}, + ) { + + override val warnings: ImmutableList = persistentListOf( + WalletNotification.UnlockVisaAccess(onUnlockClick = onUnlockVisaAccessNotificationClick), + ) + + override val balancesAndLimitBlockState: BalancesAndLimitsBlockState? = null + } } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/CloseBottomSheetTransformer.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/CloseBottomSheetTransformer.kt index feeea1a264..8bfcd6adaf 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/CloseBottomSheetTransformer.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/CloseBottomSheetTransformer.kt @@ -25,6 +25,9 @@ internal class CloseBottomSheetTransformer(userWalletId: UserWalletId) : WalletS is WalletState.Visa.Locked -> prevState.copy( bottomSheetConfig = updateConfig(prevState), ) + is WalletState.Visa.AccessTokenLocked -> prevState.copy( + bottomSheetConfig = updateConfig(prevState), + ) } } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/OpenBottomSheetTransformer.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/OpenBottomSheetTransformer.kt index 46ffbf9066..1d3bcc9423 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/OpenBottomSheetTransformer.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/OpenBottomSheetTransformer.kt @@ -31,6 +31,9 @@ internal class OpenBottomSheetTransformer( is WalletState.Visa.Locked -> prevState.copy( bottomSheetConfig = updateConfig(), ) + is WalletState.Visa.AccessTokenLocked -> prevState.copy( + bottomSheetConfig = updateConfig(), + ) } } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/RenameWalletsTransformer.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/RenameWalletsTransformer.kt index 9dd8ccb8f9..d9141b8c48 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/RenameWalletsTransformer.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/RenameWalletsTransformer.kt @@ -44,6 +44,7 @@ internal class RenameWalletsTransformer( is WalletState.MultiCurrency.Locked, is WalletState.SingleCurrency.Locked, is WalletState.Visa.Locked, + is WalletState.Visa.AccessTokenLocked, -> { Timber.e("Impossible to rename wallet in locked state") prevState diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetBalancesAndLimitsTransformer.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetBalancesAndLimitsTransformer.kt index cd0675560d..421848db63 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetBalancesAndLimitsTransformer.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetBalancesAndLimitsTransformer.kt @@ -7,6 +7,7 @@ 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.common.util.getCardsCount +import com.tangem.domain.visa.exception.RefreshTokenExpiredException import com.tangem.domain.visa.model.VisaCurrency import com.tangem.domain.wallets.models.UserWallet import com.tangem.feature.wallet.presentation.wallet.state.model.BalancesAndLimitsBlockState @@ -29,6 +30,10 @@ internal class SetBalancesAndLimitsTransformer( override fun transformTyped(prevState: WalletState.Visa.Content): WalletState { val visaCurrency = maybeVisaCurrency.getOrElse { + if (it is RefreshTokenExpiredException) { + return getRefreshTokenExpiredState(prevState) + } + return prevState.copy( walletCardState = getErrorWalletCardState(prevState.walletCardState), depositButtonState = prevState.depositButtonState.copy(isEnabled = false), @@ -100,4 +105,14 @@ internal class SetBalancesAndLimitsTransformer( return WalletAdditionalInfo(hideable = true, infoContent) } + + private fun getRefreshTokenExpiredState(prevState: WalletState.Visa.Content): WalletState { + return WalletState.Visa.AccessTokenLocked( + walletCardState = prevState.walletCardState, + buttons = prevState.buttons, + bottomSheetConfig = prevState.bottomSheetConfig, + onExploreClick = clickIntents::onExploreClick, + onUnlockVisaAccessNotificationClick = clickIntents::onUnlockVisaAccessClick, + ) + } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetRefreshStateTransformer.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetRefreshStateTransformer.kt index 9977790553..08c92c4139 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetRefreshStateTransformer.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetRefreshStateTransformer.kt @@ -35,6 +35,7 @@ internal class SetRefreshStateTransformer( is WalletState.MultiCurrency.Locked, is WalletState.SingleCurrency.Locked, is WalletState.Visa.Locked, + is WalletState.Visa.AccessTokenLocked, -> prevState } } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTxHistoryCountErrorTransformer.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTxHistoryCountErrorTransformer.kt index 9d97991b83..7f7c2f2a2e 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTxHistoryCountErrorTransformer.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTxHistoryCountErrorTransformer.kt @@ -33,6 +33,7 @@ internal class SetTxHistoryCountErrorTransformer( is WalletState.Visa.Content -> prevState.copy(txHistoryState = createErrorState()) is WalletState.SingleCurrency.Locked, is WalletState.Visa.Locked, + is WalletState.Visa.AccessTokenLocked, -> { Timber.w("Impossible to load transactions history for locked wallet") prevState diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTxHistoryCountTransformer.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTxHistoryCountTransformer.kt index f61b4961fe..e1f2e9145d 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTxHistoryCountTransformer.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTxHistoryCountTransformer.kt @@ -26,6 +26,7 @@ internal class SetTxHistoryCountTransformer( ) is WalletState.SingleCurrency.Locked, is WalletState.Visa.Locked, + is WalletState.Visa.AccessTokenLocked, -> { Timber.w("Impossible to load transactions history for locked wallet") prevState diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTxHistoryItemsErrorTransformer.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTxHistoryItemsErrorTransformer.kt index 5eda4b196e..3dad635156 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTxHistoryItemsErrorTransformer.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTxHistoryItemsErrorTransformer.kt @@ -2,6 +2,7 @@ package com.tangem.feature.wallet.presentation.wallet.state.transformers import com.tangem.core.ui.components.transactions.state.TxHistoryState import com.tangem.domain.txhistory.models.TxHistoryListError +import com.tangem.domain.visa.exception.RefreshTokenExpiredException import com.tangem.domain.wallets.models.UserWalletId import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.WalletClickIntents @@ -16,9 +17,10 @@ internal class SetTxHistoryItemsErrorTransformer( override fun transform(prevState: WalletState): WalletState { return when (prevState) { is WalletState.SingleCurrency.Content -> prevState.copy(txHistoryState = createErrorState()) - is WalletState.Visa.Content -> prevState.copy(txHistoryState = createErrorState()) + is WalletState.Visa.Content -> transformVisaContent(prevState) is WalletState.SingleCurrency.Locked, is WalletState.Visa.Locked, + is WalletState.Visa.AccessTokenLocked, -> { Timber.w("Impossible to load transactions history for locked wallet") prevState @@ -30,6 +32,20 @@ internal class SetTxHistoryItemsErrorTransformer( } } + private fun transformVisaContent(prevState: WalletState.Visa.Content): WalletState { + return if (error.cause is RefreshTokenExpiredException) { + WalletState.Visa.AccessTokenLocked( + walletCardState = prevState.walletCardState, + buttons = prevState.buttons, + bottomSheetConfig = prevState.bottomSheetConfig, + onExploreClick = clickIntents::onExploreClick, + onUnlockVisaAccessNotificationClick = clickIntents::onUnlockVisaAccessClick, + ) + } else { + prevState.copy(txHistoryState = createErrorState()) + } + } + private fun createErrorState(): TxHistoryState.Error = when (error) { is TxHistoryListError.DataError -> { TxHistoryState.Error( diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTxHistoryItemsTransformer.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTxHistoryItemsTransformer.kt index 09c90b2841..712edaa421 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTxHistoryItemsTransformer.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetTxHistoryItemsTransformer.kt @@ -26,6 +26,7 @@ internal class SetTxHistoryItemsTransformer( ) is WalletState.SingleCurrency.Locked, is WalletState.Visa.Locked, + is WalletState.Visa.AccessTokenLocked, -> { Timber.w("Impossible to load transactions history for locked wallet") prevState diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetWalletCardDropDownItemsTransformer.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetWalletCardDropDownItemsTransformer.kt index f538e29f90..f9ea74d599 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetWalletCardDropDownItemsTransformer.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetWalletCardDropDownItemsTransformer.kt @@ -54,6 +54,11 @@ internal class SetWalletCardDropDownItemsTransformer( dropDownItems = constructDropDownItems(prevState.walletCardState.id), ), ) + is WalletState.Visa.AccessTokenLocked -> prevState.copy( + walletCardState = prevState.walletCardState.copySealed( + dropDownItems = constructDropDownItems(prevState.walletCardState.id), + ), + ) } } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetWarningsTransformer.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetWarningsTransformer.kt index 7d7246a01e..f47eaa2356 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetWarningsTransformer.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetWarningsTransformer.kt @@ -19,6 +19,7 @@ internal class SetWarningsTransformer( is WalletState.MultiCurrency.Locked, is WalletState.SingleCurrency.Locked, is WalletState.Visa.Locked, + is WalletState.Visa.AccessTokenLocked, -> { Timber.w("Impossible to update notifications for locked wallet") prevState diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/UnlockWalletTransformer.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/UnlockWalletTransformer.kt index 8d4c837f82..32165880b8 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/UnlockWalletTransformer.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/UnlockWalletTransformer.kt @@ -50,8 +50,9 @@ internal class UnlockWalletTransformer( is WalletState.MultiCurrency.Content, is WalletState.SingleCurrency.Content, is WalletState.Visa.Content, + is WalletState.Visa.AccessTokenLocked, -> { - Timber.e("Impossible to unlock wallet with content state") + Timber.e("Impossible to unlock wallet with not locked state") prevState } } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/UpdateWalletCardsCountTransformer.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/UpdateWalletCardsCountTransformer.kt index f350399697..55634425fa 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/UpdateWalletCardsCountTransformer.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/UpdateWalletCardsCountTransformer.kt @@ -27,6 +27,7 @@ internal class UpdateWalletCardsCountTransformer( is WalletState.MultiCurrency.Locked, is WalletState.SingleCurrency.Locked, is WalletState.Visa.Locked, + is WalletState.Visa.AccessTokenLocked, -> { Timber.e("Impossible to update wallet cards count for locked wallet") prevState diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletClickIntents.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletClickIntents.kt index 1c218be754..289e9a955d 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletClickIntents.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletClickIntents.kt @@ -107,6 +107,7 @@ internal class WalletClickIntents @Inject constructor( is WalletState.MultiCurrency.Locked, is WalletState.SingleCurrency.Locked, is WalletState.Visa.Locked, + is WalletState.Visa.AccessTokenLocked, -> Unit } } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletWarningsClickIntents.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletWarningsClickIntents.kt index 115c9535ab..6926361876 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletWarningsClickIntents.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletWarningsClickIntents.kt @@ -55,6 +55,8 @@ internal interface WalletWarningsClickIntents { fun onUnlockWalletClick() + fun onUnlockVisaAccessClick() + fun onScanToUnlockWalletClick() fun onLikeAppClick() @@ -176,6 +178,10 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor( } } + override fun onUnlockVisaAccessClick() { + openScanCardDialog() + } + private fun handleUnlockWalletsError(error: UnlockWalletsError) { val event = when (error) { is UnlockWalletsError.DataError, From 2fb5b86505cfbed6664d1c7411f39da7ec93c7f0 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 26 Feb 2025 13:22:09 +0300 Subject: [PATCH 33/33] Updated on 2026-08-14 --- .../tangem/tap/di/RootAppComponentContextModule.kt | 4 ++-- .../ui/appcurrency/model/AppCurrencySelectorModel.kt | 4 ++-- .../analytics/AppSettingsItemsAnalyticsSender.kt | 4 ++-- .../details/ui/appsettings/model/AppSettingsModel.kt | 4 ++-- .../coderecovery/model/AccessCodeRecoveryModel.kt | 4 ++-- .../ui/cardsettings/model/CardSettingsModel.kt | 4 ++-- .../details/ui/resetcard/model/ResetCardModel.kt | 4 ++-- .../ui/securitymode/model/SecurityModeModel.kt | 4 ++-- .../details/ui/walletconnect/WalletConnectModel.kt | 4 ++-- .../java/com/tangem/tap/features/home/HomeModel.kt | 4 ++-- .../tangem/tap/features/welcome/di/ModelModule.kt | 4 ++-- .../decompose/context/DefaultAppComponentContext.kt | 4 ++-- .../com/tangem/core/decompose/di/ComponentScoped.kt | 9 --------- .../core/decompose/di/HiltComponentBuilderOwner.kt | 2 +- .../di/{DecomposeComponent.kt => ModelComponent.kt} | 8 ++++---- .../com/tangem/core/decompose/di/ModelScoped.kt | 12 ++++++++++++ .../tangem/core/decompose/model/ModelEntryPoint.kt | 4 ++-- .../tangem/core/decompose/model/ParamsContainer.kt | 2 +- .../com/tangem/features/details/di/ModelModule.kt | 4 ++-- .../tangem/features/details/model/DetailsModel.kt | 4 ++-- .../features/details/model/UserWalletListModel.kt | 4 ++-- .../tangem/features/details/utils/ItemsBuilder.kt | 4 ++-- .../tangem/features/details/utils/SocialsBuilder.kt | 4 ++-- .../tangem/features/details/utils/UserWalletSaver.kt | 4 ++-- .../features/details/utils/UserWalletsFetcher.kt | 4 ++-- .../features/disclaimer/impl/di/ModelModule.kt | 4 ++-- .../disclaimer/impl/model/DisclaimerModel.kt | 4 ++-- .../tangem/features/managetokens/di/ModelModule.kt | 4 ++-- .../managetokens/model/CustomTokenFormModel.kt | 4 ++-- .../managetokens/model/CustomTokenSelectorModel.kt | 4 ++-- .../features/managetokens/model/ManageTokensModel.kt | 4 ++-- .../model/OnboardingManageTokensModel.kt | 4 ++-- .../managetokens/utils/CustomCurrencyFormBuilder.kt | 4 ++-- .../managetokens/utils/CustomCurrencyValidator.kt | 4 ++-- .../utils/list/ManageTokensListManager.kt | 4 ++-- .../features/markets/details/impl/di/ModelModule.kt | 4 ++-- .../details/impl/model/MarketsTokenDetailsModel.kt | 4 ++-- .../markets/portfolio/impl/di/ModelModule.kt | 4 ++-- .../portfolio/impl/model/MarketsPortfolioModel.kt | 4 ++-- .../portfolio/impl/model/TokenActionsHandler.kt | 2 -- .../markets/token/block/impl/di/ModelModule.kt | 4 ++-- .../token/block/impl/model/TokenMarketBlockModel.kt | 4 ++-- .../markets/tokenlist/impl/di/ModelModule.kt | 4 ++-- .../markets/tokenlist/impl/model/MarketsListModel.kt | 4 ++-- .../onboarding/v2/entry/impl/di/ComponentModule.kt | 4 ++-- .../v2/entry/impl/model/OnboardingEntryModel.kt | 4 ++-- .../accesscode/model/MultiWalletAccessCodeModel.kt | 4 ++-- .../child/backup/model/MultiWalletBackupModel.kt | 4 ++-- .../chooseoption/model/Wallet1ChooseOptionModel.kt | 4 ++-- .../model/MultiWalletCreateWalletModel.kt | 4 ++-- .../child/finalize/model/MultiWalletFinalizeModel.kt | 4 ++-- .../scanprimary/model/Wallet1ScanPrimaryModel.kt | 4 ++-- .../seedphrase/model/MultiWalletSeedPhraseModel.kt | 4 ++-- .../v2/multiwallet/impl/di/ComponentModule.kt | 4 ++-- .../impl/model/OnboardingMultiWalletModel.kt | 4 ++-- .../model/OnboardingVisaAccessCodeModel.kt | 4 ++-- .../approve/model/OnboardingVisaApproveModel.kt | 4 ++-- .../model/OnboardingVisaChooseWalletModel.kt | 4 ++-- .../model/OnboardingVisaInProgressModel.kt | 4 ++-- .../model/OnboardingVisaOtherWalletModel.kt | 4 ++-- .../pincode/model/OnboardingVisaPinCodeModel.kt | 4 ++-- .../welcome/model/OnboardingVisaWelcomeModel.kt | 4 ++-- .../onboarding/v2/visa/impl/di/ComponentModule.kt | 4 ++-- .../v2/visa/impl/model/OnboardingVisaModel.kt | 4 ++-- .../di/OnrampConfirmResidencyModelModule.kt | 4 ++-- .../confirmresidency/model/ConfirmResidencyModel.kt | 4 ++-- .../onramp/hottokens/di/HotCryptoModelModule.kt | 4 ++-- .../onramp/hottokens/model/HotCryptoModel.kt | 4 ++-- .../portfolio/di/OnrampAddToPortfolioModelModule.kt | 4 ++-- .../portfolio/model/OnrampAddToPortfolioModel.kt | 4 ++-- .../onramp/main/di/OnrampMainComponentModelModule.kt | 4 ++-- .../onramp/providers/di/SelectProviderModelModule.kt | 4 ++-- .../onramp/providers/model/SelectProviderModel.kt | 4 ++-- .../onramp/redirect/di/OnrampRedirectModelModule.kt | 4 ++-- .../di/OnrampSelectCountryModelModule.kt | 4 ++-- .../selectcountry/model/OnrampSelectCountryModel.kt | 4 ++-- .../di/OnrampSelectCurrencyModelModule.kt | 4 ++-- .../model/OnrampSelectCurrencyModel.kt | 4 ++-- .../selecttoken/di/OnrampOperationModelModule.kt | 4 ++-- .../onramp/selecttoken/model/OnrampOperationModel.kt | 4 ++-- .../onramp/settings/di/OnrampSettingsModelModule.kt | 4 ++-- .../onramp/settings/model/OnrampSettingsModel.kt | 4 ++-- .../success/di/OnrampSuccessComponentModelModule.kt | 4 ++-- .../di/AvailableSwapPairsModelModule.kt | 4 ++-- .../onramp/swap/di/SwapSelectTokensModelModule.kt | 4 ++-- .../tokenlist/di/OnrampTokenListModelModule.kt | 4 ++-- .../impl/model/PushNotificationsModel.kt | 4 ++-- .../feature/qrscanning/model/QrScanningModel.kt | 4 ++-- .../referral/domain/di/ReferralDomainModule.kt | 8 ++++---- .../tangem/feature/referral/model/ReferralModel.kt | 4 ++-- .../com/tangem/features/send/impl/di/SendModule.kt | 8 ++++---- .../send/impl/navigation/DefaultSendRouter.kt | 4 ++-- .../send/impl/presentation/model/SendModel.kt | 4 ++-- .../tangem/features/staking/impl/di/StakingModule.kt | 8 ++++---- .../staking/impl/navigation/DefaultStakingRouter.kt | 4 ++-- .../staking/impl/presentation/model/StakingModel.kt | 4 ++-- .../feature/stories/impl/di/StoriesModelModule.kt | 4 ++-- .../com/tangem/feature/swap/di/SwapModelModule.kt | 4 ++-- .../java/com/tangem/feature/swap/model/SwapModel.kt | 4 ++-- .../feature/tokendetails/di/TokenDetailsModule.kt | 8 ++++---- .../presentation/router/DefaultTokenDetailsRouter.kt | 4 ++-- .../tokendetails/model/TokenDetailsModel.kt | 4 ++-- .../component/impl/model/RenameWalletModel.kt | 4 ++-- .../walletsettings/di/WalletSettingsModelModule.kt | 4 ++-- .../walletsettings/model/WalletSettingsModel.kt | 4 ++-- .../feature/walletsettings/utils/ItemsBuilder.kt | 4 ++-- .../feature/wallet/presentation/WalletFragment.kt | 4 ++-- 107 files changed, 228 insertions(+), 227 deletions(-) delete mode 100644 core/decompose/src/main/kotlin/com/tangem/core/decompose/di/ComponentScoped.kt rename core/decompose/src/main/kotlin/com/tangem/core/decompose/di/{DecomposeComponent.kt => ModelComponent.kt} (88%) create mode 100644 core/decompose/src/main/kotlin/com/tangem/core/decompose/di/ModelScoped.kt diff --git a/app/src/main/java/com/tangem/tap/di/RootAppComponentContextModule.kt b/app/src/main/java/com/tangem/tap/di/RootAppComponentContextModule.kt index b59094d579..0d535ff71d 100644 --- a/app/src/main/java/com/tangem/tap/di/RootAppComponentContextModule.kt +++ b/app/src/main/java/com/tangem/tap/di/RootAppComponentContextModule.kt @@ -5,7 +5,7 @@ import androidx.appcompat.app.AppCompatActivity import com.arkivanov.decompose.defaultComponentContext import com.tangem.core.decompose.context.AppComponentContext import com.tangem.core.decompose.context.DefaultAppComponentContext -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.di.GlobalUiMessageSender import com.tangem.core.decompose.di.RootAppComponentContext import com.tangem.core.decompose.ui.UiMessageSender @@ -27,7 +27,7 @@ internal object RootAppComponentContextModule { fun provideRootAppComponentContext( @ActivityContext context: Context, dispatchers: CoroutineDispatcherProvider, - componentBuilder: DecomposeComponent.Builder, + componentBuilder: ModelComponent.Builder, @GlobalUiMessageSender messageSender: UiMessageSender, ): AppComponentContext { return DefaultAppComponentContext( diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/model/AppCurrencySelectorModel.kt b/app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/model/AppCurrencySelectorModel.kt index abddb2896e..f48804c41c 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/model/AppCurrencySelectorModel.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/appcurrency/model/AppCurrencySelectorModel.kt @@ -3,7 +3,7 @@ package com.tangem.tap.features.details.ui.appcurrency.model import androidx.compose.runtime.Stable import com.tangem.common.routing.AppRouter import com.tangem.core.analytics.api.AnalyticsEventHandler -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.domain.appcurrency.GetAvailableCurrenciesUseCase import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase @@ -19,7 +19,7 @@ import kotlinx.coroutines.launch import javax.inject.Inject @Stable -@ComponentScoped +@ModelScoped internal class AppCurrencySelectorModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/analytics/AppSettingsItemsAnalyticsSender.kt b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/analytics/AppSettingsItemsAnalyticsSender.kt index fc0137dca3..64a5832a8c 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/analytics/AppSettingsItemsAnalyticsSender.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/analytics/AppSettingsItemsAnalyticsSender.kt @@ -2,13 +2,13 @@ package com.tangem.tap.features.details.ui.appsettings.analytics import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.models.AnalyticsEvent -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.tap.common.analytics.events.Settings import com.tangem.tap.features.details.ui.appsettings.AppSettingsItemsFactory import com.tangem.tap.features.details.ui.appsettings.AppSettingsScreenState import javax.inject.Inject -@ComponentScoped +@ModelScoped internal class AppSettingsItemsAnalyticsSender @Inject constructor( private val analyticsHandler: AnalyticsEventHandler, ) { diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/model/AppSettingsModel.kt b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/model/AppSettingsModel.kt index 953ad0933c..ee93849f31 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/model/AppSettingsModel.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/model/AppSettingsModel.kt @@ -3,7 +3,7 @@ package com.tangem.tap.features.details.ui.appsettings.model import androidx.compose.runtime.Stable import com.tangem.common.routing.AppRoute import com.tangem.core.analytics.api.AnalyticsEventHandler -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.appcurrency.repository.AppCurrencyRepository @@ -40,7 +40,7 @@ import javax.inject.Inject @Suppress("LongParameterList") @Stable -@ComponentScoped +@ModelScoped internal class AppSettingsModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val appCurrencyRepository: AppCurrencyRepository, diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/coderecovery/model/AccessCodeRecoveryModel.kt b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/coderecovery/model/AccessCodeRecoveryModel.kt index b3c2fb4878..2d90ffa871 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/coderecovery/model/AccessCodeRecoveryModel.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/coderecovery/model/AccessCodeRecoveryModel.kt @@ -4,7 +4,7 @@ import androidx.compose.runtime.Stable import com.tangem.common.doOnSuccess import com.tangem.common.routing.AppRouter import com.tangem.core.analytics.Analytics -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.domain.common.util.cardTypesResolver import com.tangem.sdk.api.TangemSdkManager @@ -22,7 +22,7 @@ import kotlinx.coroutines.launch import javax.inject.Inject @Stable -@ComponentScoped +@ModelScoped internal class AccessCodeRecoveryModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val tangemSdkManager: TangemSdkManager, diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/model/CardSettingsModel.kt b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/model/CardSettingsModel.kt index 11964f58c4..773aa32d80 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/model/CardSettingsModel.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/model/CardSettingsModel.kt @@ -7,7 +7,7 @@ import com.tangem.common.doOnSuccess import com.tangem.common.routing.AppRoute import com.tangem.common.routing.AppRouter import com.tangem.core.analytics.Analytics -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.domain.card.ScanCardProcessor @@ -45,7 +45,7 @@ import javax.inject.Inject @Suppress("LongParameterList") @Stable -@ComponentScoped +@ModelScoped internal class CardSettingsModel @Inject constructor( paramsContainer: ParamsContainer, override val dispatchers: CoroutineDispatcherProvider, diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/model/ResetCardModel.kt b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/model/ResetCardModel.kt index a4108e3ea0..f401bbfc09 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/model/ResetCardModel.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/model/ResetCardModel.kt @@ -5,7 +5,7 @@ import arrow.core.getOrElse import com.tangem.common.routing.AppRoute import com.tangem.common.routing.utils.popTo import com.tangem.core.analytics.api.AnalyticsEventHandler -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.domain.card.DeleteSavedAccessCodesUseCase @@ -37,7 +37,7 @@ import javax.inject.Inject @Suppress("LongParameterList") @Stable -@ComponentScoped +@ModelScoped internal class ResetCardModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, paramsContainer: ParamsContainer, diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/model/SecurityModeModel.kt b/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/model/SecurityModeModel.kt index 5fe21b868c..39ae0e13fb 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/model/SecurityModeModel.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/model/SecurityModeModel.kt @@ -5,7 +5,7 @@ import com.tangem.common.CompletionResult import com.tangem.common.core.TangemSdkError import com.tangem.common.routing.AppRouter import com.tangem.core.analytics.Analytics -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.domain.common.util.cardTypesResolver import com.tangem.sdk.api.TangemSdkManager @@ -25,7 +25,7 @@ import kotlinx.coroutines.launch import javax.inject.Inject @Stable -@ComponentScoped +@ModelScoped internal class SecurityModeModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val tangemSdkManager: TangemSdkManager, diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectModel.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectModel.kt index 6372c2f648..39f27fb752 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectModel.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectModel.kt @@ -2,7 +2,7 @@ package com.tangem.tap.features.details.ui.walletconnect import androidx.compose.runtime.Stable import arrow.core.getOrElse -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.ui.clipboard.ClipboardManager import com.tangem.domain.qrscanning.models.SourceType @@ -18,7 +18,7 @@ import timber.log.Timber import javax.inject.Inject @Stable -@ComponentScoped +@ModelScoped internal class WalletConnectModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val listenToQrScanningUseCase: ListenToQrScanningUseCase, diff --git a/app/src/main/java/com/tangem/tap/features/home/HomeModel.kt b/app/src/main/java/com/tangem/tap/features/home/HomeModel.kt index 91a72ef7ed..8511f53ab2 100644 --- a/app/src/main/java/com/tangem/tap/features/home/HomeModel.kt +++ b/app/src/main/java/com/tangem/tap/features/home/HomeModel.kt @@ -9,7 +9,7 @@ import com.tangem.core.analytics.Analytics import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.models.AnalyticsParam import com.tangem.core.analytics.models.Basic -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.navigation.url.UrlOpener import com.tangem.domain.card.ScanCardProcessor @@ -40,7 +40,7 @@ import javax.inject.Inject @Suppress("LongParameterList") @Stable -@ComponentScoped +@ModelScoped internal class HomeModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val scanCardProcessor: ScanCardProcessor, diff --git a/app/src/main/java/com/tangem/tap/features/welcome/di/ModelModule.kt b/app/src/main/java/com/tangem/tap/features/welcome/di/ModelModule.kt index 1a90bd0bc5..92e347fe26 100644 --- a/app/src/main/java/com/tangem/tap/features/welcome/di/ModelModule.kt +++ b/app/src/main/java/com/tangem/tap/features/welcome/di/ModelModule.kt @@ -1,6 +1,6 @@ package com.tangem.tap.features.welcome.di -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model import com.tangem.tap.features.welcome.model.WelcomeModel import dagger.Binds @@ -10,7 +10,7 @@ import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) internal interface ModelModule { @Binds diff --git a/core/decompose/src/main/kotlin/com/tangem/core/decompose/context/DefaultAppComponentContext.kt b/core/decompose/src/main/kotlin/com/tangem/core/decompose/context/DefaultAppComponentContext.kt index d4453d3e6a..ea9afa04a5 100644 --- a/core/decompose/src/main/kotlin/com/tangem/core/decompose/context/DefaultAppComponentContext.kt +++ b/core/decompose/src/main/kotlin/com/tangem/core/decompose/context/DefaultAppComponentContext.kt @@ -2,7 +2,7 @@ package com.tangem.core.decompose.context import com.arkivanov.decompose.ComponentContext import com.arkivanov.essenty.instancekeeper.getOrCreate -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.navigation.AppNavigationProvider import com.tangem.core.decompose.navigation.DefaultAppNavigationProvider import com.tangem.core.decompose.navigation.DefaultRouter @@ -15,7 +15,7 @@ import kotlinx.coroutines.CoroutineScope class DefaultAppComponentContext( componentContext: ComponentContext, override val dispatchers: CoroutineDispatcherProvider, - override val hiltComponentBuilder: DecomposeComponent.Builder, + override val hiltComponentBuilder: ModelComponent.Builder, override val messageSender: UiMessageSender, private val replaceRouter: Router? = null, ) : AppComponentContext, ComponentContext by componentContext { diff --git a/core/decompose/src/main/kotlin/com/tangem/core/decompose/di/ComponentScoped.kt b/core/decompose/src/main/kotlin/com/tangem/core/decompose/di/ComponentScoped.kt deleted file mode 100644 index b5fde3b58f..0000000000 --- a/core/decompose/src/main/kotlin/com/tangem/core/decompose/di/ComponentScoped.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.tangem.core.decompose.di - -/** - * Annotation for marking a dependency as a component scoped. - * - * This means that the lifecycle of the dependency is limited to the lifecycle of the component it is attached to. - */ -@Retention(AnnotationRetention.SOURCE) -annotation class ComponentScoped \ No newline at end of file diff --git a/core/decompose/src/main/kotlin/com/tangem/core/decompose/di/HiltComponentBuilderOwner.kt b/core/decompose/src/main/kotlin/com/tangem/core/decompose/di/HiltComponentBuilderOwner.kt index d210c58019..99067c8ec4 100644 --- a/core/decompose/src/main/kotlin/com/tangem/core/decompose/di/HiltComponentBuilderOwner.kt +++ b/core/decompose/src/main/kotlin/com/tangem/core/decompose/di/HiltComponentBuilderOwner.kt @@ -8,5 +8,5 @@ interface HiltComponentBuilderOwner { /** * Provides access to the Hilt component builder instance. */ - val hiltComponentBuilder: DecomposeComponent.Builder + val hiltComponentBuilder: ModelComponent.Builder } \ No newline at end of file diff --git a/core/decompose/src/main/kotlin/com/tangem/core/decompose/di/DecomposeComponent.kt b/core/decompose/src/main/kotlin/com/tangem/core/decompose/di/ModelComponent.kt similarity index 88% rename from core/decompose/src/main/kotlin/com/tangem/core/decompose/di/DecomposeComponent.kt rename to core/decompose/src/main/kotlin/com/tangem/core/decompose/di/ModelComponent.kt index 74fba5a48e..6a94065ebf 100644 --- a/core/decompose/src/main/kotlin/com/tangem/core/decompose/di/DecomposeComponent.kt +++ b/core/decompose/src/main/kotlin/com/tangem/core/decompose/di/ModelComponent.kt @@ -10,11 +10,11 @@ import dagger.hilt.components.SingletonComponent /** * Interface for the Decompose component. * - * It is annotated as [ComponentScoped], meaning it has a lifecycle that is scoped to the component. + * It is annotated as [ModelScoped], meaning it has a lifecycle that is scoped to the component. */ -@ComponentScoped +@ModelScoped @DefineComponent(parent = SingletonComponent::class) -interface DecomposeComponent { +interface ModelComponent { /** * Builder interface for the component. @@ -51,6 +51,6 @@ interface DecomposeComponent { * * @return The built Decompose component. */ - fun build(): DecomposeComponent + fun build(): ModelComponent } } \ No newline at end of file diff --git a/core/decompose/src/main/kotlin/com/tangem/core/decompose/di/ModelScoped.kt b/core/decompose/src/main/kotlin/com/tangem/core/decompose/di/ModelScoped.kt new file mode 100644 index 0000000000..ad4308f3d1 --- /dev/null +++ b/core/decompose/src/main/kotlin/com/tangem/core/decompose/di/ModelScoped.kt @@ -0,0 +1,12 @@ +package com.tangem.core.decompose.di + +import javax.inject.Scope + +/** + * Annotation for marking a dependency as a model scoped. + * + * This means that the lifecycle of the dependency is limited to the lifecycle of the component's model + */ +@Scope +@Retention(AnnotationRetention.RUNTIME) +annotation class ModelScoped \ No newline at end of file diff --git a/core/decompose/src/main/kotlin/com/tangem/core/decompose/model/ModelEntryPoint.kt b/core/decompose/src/main/kotlin/com/tangem/core/decompose/model/ModelEntryPoint.kt index 56b718e970..d37de64a00 100644 --- a/core/decompose/src/main/kotlin/com/tangem/core/decompose/model/ModelEntryPoint.kt +++ b/core/decompose/src/main/kotlin/com/tangem/core/decompose/model/ModelEntryPoint.kt @@ -3,7 +3,7 @@ package com.tangem.core.decompose.model import com.arkivanov.essenty.instancekeeper.getOrCreate import com.arkivanov.essenty.instancekeeper.getOrCreateSimple import com.tangem.core.decompose.context.AppComponentContext -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import dagger.hilt.EntryPoint import dagger.hilt.EntryPoints import dagger.hilt.InstallIn @@ -15,7 +15,7 @@ import javax.inject.Provider * It provides a map of model providers. */ @EntryPoint -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) interface ModelsEntryPoint { fun models(): Map, Provider> diff --git a/core/decompose/src/main/kotlin/com/tangem/core/decompose/model/ParamsContainer.kt b/core/decompose/src/main/kotlin/com/tangem/core/decompose/model/ParamsContainer.kt index 910764d661..4ab544bf1b 100644 --- a/core/decompose/src/main/kotlin/com/tangem/core/decompose/model/ParamsContainer.kt +++ b/core/decompose/src/main/kotlin/com/tangem/core/decompose/model/ParamsContainer.kt @@ -3,7 +3,7 @@ package com.tangem.core.decompose.model /** * Lazy container for [Model] params. * - * This contrainer can be accessed by DI because it's provided via [com.tangem.core.decompose.di.DecomposeComponent]. + * This contrainer can be accessed by DI because it's provided via [com.tangem.core.decompose.di.ModelComponent]. * */ interface ParamsContainer { diff --git a/features/details/impl/src/main/kotlin/com/tangem/features/details/di/ModelModule.kt b/features/details/impl/src/main/kotlin/com/tangem/features/details/di/ModelModule.kt index 63481527c2..25599bd30e 100644 --- a/features/details/impl/src/main/kotlin/com/tangem/features/details/di/ModelModule.kt +++ b/features/details/impl/src/main/kotlin/com/tangem/features/details/di/ModelModule.kt @@ -1,6 +1,6 @@ package com.tangem.features.details.di -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model import com.tangem.features.details.model.DetailsModel import com.tangem.features.details.model.UserWalletListModel @@ -11,7 +11,7 @@ import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) internal interface ModelModule { @Binds diff --git a/features/details/impl/src/main/kotlin/com/tangem/features/details/model/DetailsModel.kt b/features/details/impl/src/main/kotlin/com/tangem/features/details/model/DetailsModel.kt index e6694cee44..99def3ec10 100644 --- a/features/details/impl/src/main/kotlin/com/tangem/features/details/model/DetailsModel.kt +++ b/features/details/impl/src/main/kotlin/com/tangem/features/details/model/DetailsModel.kt @@ -2,7 +2,7 @@ package com.tangem.features.details.model import arrow.core.getOrElse import com.tangem.core.analytics.AppInstanceIdProvider -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.navigation.Router @@ -32,7 +32,7 @@ import kotlinx.coroutines.launch import timber.log.Timber import javax.inject.Inject -@ComponentScoped +@ModelScoped @Suppress("LongParameterList") internal class DetailsModel @Inject constructor( socialsBuilder: SocialsBuilder, diff --git a/features/details/impl/src/main/kotlin/com/tangem/features/details/model/UserWalletListModel.kt b/features/details/impl/src/main/kotlin/com/tangem/features/details/model/UserWalletListModel.kt index ef9905ff46..a29ea393b2 100644 --- a/features/details/impl/src/main/kotlin/com/tangem/features/details/model/UserWalletListModel.kt +++ b/features/details/impl/src/main/kotlin/com/tangem/features/details/model/UserWalletListModel.kt @@ -1,7 +1,7 @@ package com.tangem.features.details.model import com.tangem.common.ui.userwallet.state.UserWalletItemUM -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.resourceReference @@ -19,7 +19,7 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.update import javax.inject.Inject -@ComponentScoped +@ModelScoped internal class UserWalletListModel @Inject constructor( userWalletsFetcher: UserWalletsFetcher, shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase, diff --git a/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/ItemsBuilder.kt b/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/ItemsBuilder.kt index 70d3936e99..7cd8933ad5 100644 --- a/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/ItemsBuilder.kt +++ b/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/ItemsBuilder.kt @@ -1,7 +1,7 @@ package com.tangem.features.details.utils import com.tangem.common.routing.AppRoute -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.navigation.Router import com.tangem.core.ui.components.block.model.BlockUM import com.tangem.core.ui.extensions.resourceReference @@ -14,7 +14,7 @@ import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import javax.inject.Inject -@ComponentScoped +@ModelScoped internal class ItemsBuilder @Inject constructor(private val router: Router) { fun buildAll( diff --git a/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/SocialsBuilder.kt b/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/SocialsBuilder.kt index 8282bbd41c..dda4068ab9 100644 --- a/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/SocialsBuilder.kt +++ b/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/SocialsBuilder.kt @@ -1,7 +1,7 @@ package com.tangem.features.details.utils import androidx.compose.ui.text.intl.Locale -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.navigation.url.UrlOpener import com.tangem.features.details.entity.DetailsFooterUM import com.tangem.features.details.impl.R @@ -9,7 +9,7 @@ import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList import javax.inject.Inject -@ComponentScoped +@ModelScoped internal class SocialsBuilder @Inject constructor( private val urlOpener: UrlOpener, ) { diff --git a/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/UserWalletSaver.kt b/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/UserWalletSaver.kt index fd621dbe14..6badebac2d 100644 --- a/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/UserWalletSaver.kt +++ b/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/UserWalletSaver.kt @@ -7,7 +7,7 @@ import arrow.core.raise.fold import arrow.core.raise.recover import com.tangem.common.routing.AppRoute import com.tangem.core.analytics.models.AnalyticsParam -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.navigation.Router import com.tangem.core.decompose.navigation.popTo import com.tangem.core.decompose.ui.UiMessageSender @@ -33,7 +33,7 @@ import kotlinx.coroutines.suspendCancellableCoroutine import javax.inject.Inject import kotlin.coroutines.resume -@ComponentScoped +@ModelScoped @Suppress("LongParameterList") internal class UserWalletSaver @Inject constructor( private val scanCardProcessor: ScanCardProcessor, diff --git a/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/UserWalletsFetcher.kt b/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/UserWalletsFetcher.kt index c9115930ec..8de287944f 100644 --- a/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/UserWalletsFetcher.kt +++ b/features/details/impl/src/main/kotlin/com/tangem/features/details/utils/UserWalletsFetcher.kt @@ -4,7 +4,7 @@ import arrow.core.Either import com.tangem.common.routing.AppRoute import com.tangem.common.ui.userwallet.converter.UserWalletItemUMConverter import com.tangem.common.ui.userwallet.state.UserWalletItemUM -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.navigation.Router import com.tangem.core.decompose.ui.UiMessageSender import com.tangem.core.ui.extensions.resourceReference @@ -31,7 +31,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.* import javax.inject.Inject -@ComponentScoped +@ModelScoped internal class UserWalletsFetcher @Inject constructor( getWalletsUseCase: GetWalletsUseCase, private val getWalletTotalBalanceUseCase: GetWalletTotalBalanceUseCase, diff --git a/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/di/ModelModule.kt b/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/di/ModelModule.kt index a589336c78..4862b935c9 100644 --- a/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/di/ModelModule.kt +++ b/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/di/ModelModule.kt @@ -1,6 +1,6 @@ package com.tangem.features.disclaimer.impl.di -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model import com.tangem.features.disclaimer.impl.model.DisclaimerModel import dagger.Binds @@ -10,7 +10,7 @@ import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) internal interface ModelModule { @Binds diff --git a/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/model/DisclaimerModel.kt b/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/model/DisclaimerModel.kt index e2dffb37f3..f96cb66625 100644 --- a/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/model/DisclaimerModel.kt +++ b/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/model/DisclaimerModel.kt @@ -1,7 +1,7 @@ package com.tangem.features.disclaimer.impl.model import com.tangem.common.routing.AppRoute -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.navigation.Router @@ -17,7 +17,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.launch import javax.inject.Inject -@ComponentScoped +@ModelScoped @Suppress("LongParameterList") internal class DisclaimerModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/di/ModelModule.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/di/ModelModule.kt index 101e51cfdd..d9f4b0cb1d 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/di/ModelModule.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/di/ModelModule.kt @@ -1,6 +1,6 @@ package com.tangem.features.managetokens.di -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model import com.tangem.features.managetokens.model.CustomTokenFormModel import com.tangem.features.managetokens.model.CustomTokenSelectorModel @@ -13,7 +13,7 @@ import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) internal interface ModelModule { @Binds diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/CustomTokenFormModel.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/CustomTokenFormModel.kt index ad5db50c72..58b65ada79 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/CustomTokenFormModel.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/CustomTokenFormModel.kt @@ -2,7 +2,7 @@ package com.tangem.features.managetokens.model import arrow.core.getOrElse import com.tangem.core.analytics.api.AnalyticsEventHandler -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.ui.UiMessageSender @@ -37,7 +37,7 @@ import javax.inject.Inject // TODO: Divide to sub-components: [REDACTED_JIRA] @Suppress("LongParameterList", "LargeClass") -@ComponentScoped +@ModelScoped internal class CustomTokenFormModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val customCurrencyValidator: CustomCurrencyValidator, diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/CustomTokenSelectorModel.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/CustomTokenSelectorModel.kt index 998307191a..b1b01ab5ed 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/CustomTokenSelectorModel.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/CustomTokenSelectorModel.kt @@ -3,7 +3,7 @@ package com.tangem.features.managetokens.model import arrow.core.getOrElse import com.arkivanov.decompose.router.slot.SlotNavigation import com.arkivanov.decompose.router.slot.activate -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.ui.UiMessageSender @@ -33,7 +33,7 @@ import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import javax.inject.Inject -@ComponentScoped +@ModelScoped internal class CustomTokenSelectorModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val getSupportedNetworksUseCase: GetSupportedNetworksUseCase, diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/ManageTokensModel.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/ManageTokensModel.kt index 36916e335d..65be95e384 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/ManageTokensModel.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/ManageTokensModel.kt @@ -5,7 +5,7 @@ import arrow.core.getOrElse import com.arkivanov.decompose.router.slot.SlotNavigation import com.arkivanov.decompose.router.slot.activate import com.tangem.core.analytics.api.AnalyticsEventHandler -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.navigation.Router @@ -42,7 +42,7 @@ import timber.log.Timber import javax.inject.Inject @Suppress("LongParameterList") -@ComponentScoped +@ModelScoped internal class ManageTokensModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val router: Router, diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/OnboardingManageTokensModel.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/OnboardingManageTokensModel.kt index c5bb946e7d..485566a94a 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/OnboardingManageTokensModel.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/OnboardingManageTokensModel.kt @@ -3,7 +3,7 @@ package com.tangem.features.managetokens.model import arrow.core.flatten import arrow.core.getOrElse import com.tangem.core.analytics.api.AnalyticsEventHandler -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.ui.UiMessageSender @@ -37,7 +37,7 @@ import timber.log.Timber import javax.inject.Inject @Suppress("LongParameterList") -@ComponentScoped +@ModelScoped internal class OnboardingManageTokensModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val manageTokensListManager: ManageTokensListManager, diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/CustomCurrencyFormBuilder.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/CustomCurrencyFormBuilder.kt index caf9507cc2..f371da280d 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/CustomCurrencyFormBuilder.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/CustomCurrencyFormBuilder.kt @@ -3,7 +3,7 @@ package com.tangem.features.managetokens.utils import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.ui.text.input.KeyboardCapitalization import androidx.compose.ui.text.input.KeyboardType -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.stringReference @@ -15,7 +15,7 @@ import com.tangem.features.managetokens.impl.R import kotlinx.collections.immutable.persistentMapOf import javax.inject.Inject -@ComponentScoped +@ModelScoped internal class CustomCurrencyFormBuilder @Inject constructor( paramsContainer: ParamsContainer, ) { diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/CustomCurrencyValidator.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/CustomCurrencyValidator.kt index 77a41933ea..fa0f6b6046 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/CustomCurrencyValidator.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/CustomCurrencyValidator.kt @@ -1,7 +1,7 @@ package com.tangem.features.managetokens.utils import arrow.core.getOrElse -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.domain.managetokens.CheckIsCurrencyNotAddedUseCase import com.tangem.domain.managetokens.CreateCurrencyUseCase import com.tangem.domain.managetokens.FindTokenUseCase @@ -20,7 +20,7 @@ import kotlinx.coroutines.launch import timber.log.Timber import javax.inject.Inject -@ComponentScoped +@ModelScoped internal class CustomCurrencyValidator @Inject constructor( private val validateTokenFormUseCase: ValidateTokenFormUseCase, private val createCustomCurrencyUseCase: CreateCurrencyUseCase, diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/list/ManageTokensListManager.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/list/ManageTokensListManager.kt index d3a52095a7..7dde531506 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/list/ManageTokensListManager.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/utils/list/ManageTokensListManager.kt @@ -4,7 +4,7 @@ import androidx.compose.ui.util.fastForEachIndexed import androidx.compose.ui.util.fastMap import arrow.core.getOrElse import com.tangem.core.analytics.api.AnalyticsEventHandler -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.ui.UiMessageSender import com.tangem.core.ui.clipboard.ClipboardManager import com.tangem.core.ui.extensions.resourceReference @@ -40,7 +40,7 @@ import timber.log.Timber import javax.inject.Inject @Suppress("LongParameterList") -@ComponentScoped +@ModelScoped internal class ManageTokensListManager @Inject constructor( private val getManagedTokensUseCase: GetManagedTokensUseCase, private val checkHasLinkedTokensUseCase: CheckHasLinkedTokensUseCase, diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/di/ModelModule.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/di/ModelModule.kt index 83e26ff055..2fda5dee58 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/di/ModelModule.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/di/ModelModule.kt @@ -1,6 +1,6 @@ package com.tangem.features.markets.details.impl.di -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model import com.tangem.features.markets.details.impl.model.MarketsTokenDetailsModel import dagger.Binds @@ -10,7 +10,7 @@ import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) internal interface ModelModule { @Binds diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/model/MarketsTokenDetailsModel.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/model/MarketsTokenDetailsModel.kt index 04d2edcb0c..3ba4dd807e 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/model/MarketsTokenDetailsModel.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/model/MarketsTokenDetailsModel.kt @@ -8,7 +8,7 @@ import com.tangem.common.ui.charts.state.MarketChartData import com.tangem.common.ui.charts.state.MarketChartDataProducer import com.tangem.common.ui.charts.state.sorted import com.tangem.core.analytics.api.AnalyticsEventHandler -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.navigation.url.UrlOpener @@ -53,7 +53,7 @@ import javax.inject.Inject @Suppress("LargeClass", "LongParameterList") @Stable -@ComponentScoped +@ModelScoped internal class MarketsTokenDetailsModel @Inject constructor( paramsContainer: ParamsContainer, override val dispatchers: CoroutineDispatcherProvider, diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/di/ModelModule.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/di/ModelModule.kt index 38ea8f8688..2b35fe3c10 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/di/ModelModule.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/di/ModelModule.kt @@ -1,6 +1,6 @@ package com.tangem.features.markets.portfolio.impl.di -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model import com.tangem.features.markets.portfolio.impl.model.MarketsPortfolioModel import dagger.Binds @@ -10,7 +10,7 @@ import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) internal interface ModelModule { @Binds diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/MarketsPortfolioModel.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/MarketsPortfolioModel.kt index b28d495ac2..e31e23a7be 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/MarketsPortfolioModel.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/MarketsPortfolioModel.kt @@ -3,7 +3,7 @@ package com.tangem.features.markets.portfolio.impl.model import androidx.compose.runtime.Stable import arrow.core.getOrElse import com.tangem.core.analytics.api.AnalyticsEventHandler -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.ui.UiMessageSender @@ -38,7 +38,7 @@ import javax.inject.Inject @Suppress("LongParameterList") @Stable -@ComponentScoped +@ModelScoped internal class MarketsPortfolioModel @Inject constructor( paramsContainer: ParamsContainer, getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/TokenActionsHandler.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/TokenActionsHandler.kt index 471770d6a4..ab2b23c6c0 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/TokenActionsHandler.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/TokenActionsHandler.kt @@ -2,7 +2,6 @@ package com.tangem.features.markets.portfolio.impl.model import com.tangem.common.routing.AppRoute import com.tangem.core.analytics.models.AnalyticsParam -import com.tangem.core.decompose.di.ComponentScoped import com.tangem.core.decompose.navigation.Router import com.tangem.core.decompose.ui.UiMessageSender import com.tangem.core.ui.clipboard.ClipboardManager @@ -31,7 +30,6 @@ import dagger.assisted.AssistedInject import kotlinx.collections.immutable.toImmutableList @Suppress("LongParameterList") -@ComponentScoped internal class TokenActionsHandler @AssistedInject constructor( private val router: Router, private val clipboardManager: ClipboardManager, diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/token/block/impl/di/ModelModule.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/token/block/impl/di/ModelModule.kt index fdb1ba90ba..e50f1793ed 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/token/block/impl/di/ModelModule.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/token/block/impl/di/ModelModule.kt @@ -1,6 +1,6 @@ package com.tangem.features.markets.token.block.impl.di -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model import com.tangem.features.markets.token.block.impl.model.TokenMarketBlockModel import dagger.Binds @@ -10,7 +10,7 @@ import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) internal interface ModelModule { @Binds diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/token/block/impl/model/TokenMarketBlockModel.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/token/block/impl/model/TokenMarketBlockModel.kt index 35346aeb94..372309d5ea 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/token/block/impl/model/TokenMarketBlockModel.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/token/block/impl/model/TokenMarketBlockModel.kt @@ -6,7 +6,7 @@ import com.tangem.common.routing.AppRoute import com.tangem.common.ui.charts.state.MarketChartData import com.tangem.common.ui.charts.state.converter.PriceAndTimePointValuesConverter import com.tangem.common.ui.charts.state.sorted -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.navigation.Router @@ -31,7 +31,7 @@ import kotlinx.coroutines.launch import javax.inject.Inject @Stable -@ComponentScoped +@ModelScoped internal class TokenMarketBlockModel @Inject constructor( paramsContainer: ParamsContainer, override val dispatchers: CoroutineDispatcherProvider, diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/di/ModelModule.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/di/ModelModule.kt index 17aa3f4cd5..fca279c2f6 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/di/ModelModule.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/di/ModelModule.kt @@ -1,6 +1,6 @@ package com.tangem.features.markets.tokenlist.impl.di -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model import com.tangem.features.markets.tokenlist.impl.model.MarketsListModel import dagger.Binds @@ -10,7 +10,7 @@ import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) internal interface ModelModule { @Binds diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/model/MarketsListModel.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/model/MarketsListModel.kt index 7e94d860a3..65622d2f0d 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/model/MarketsListModel.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/model/MarketsListModel.kt @@ -3,7 +3,7 @@ package com.tangem.features.markets.tokenlist.impl.model import androidx.compose.runtime.Stable import arrow.core.getOrElse import com.tangem.core.analytics.api.AnalyticsEventHandler -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.model.AppCurrency @@ -29,7 +29,7 @@ private const val UPDATE_QUOTES_TIMER_MILLIS = 60000L private const val SEARCH_QUERY_DEBOUNCE_MILLIS = 800L @OptIn(FlowPreview::class, ExperimentalCoroutinesApi::class) -@ComponentScoped +@ModelScoped @Stable internal class MarketsListModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/entry/impl/di/ComponentModule.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/entry/impl/di/ComponentModule.kt index 1ea00b3585..4ce0d4c71d 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/entry/impl/di/ComponentModule.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/entry/impl/di/ComponentModule.kt @@ -1,6 +1,6 @@ package com.tangem.features.onboarding.v2.entry.impl.di -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model import com.tangem.features.onboarding.v2.entry.OnboardingEntryComponent import com.tangem.features.onboarding.v2.entry.impl.DefaultOnboardingEntryComponent @@ -25,7 +25,7 @@ internal interface ComponentModule { } @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) internal interface ModelModule { @Binds @IntoMap diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/entry/impl/model/OnboardingEntryModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/entry/impl/model/OnboardingEntryModel.kt index 281ec29e57..a4478d44e3 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/entry/impl/model/OnboardingEntryModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/entry/impl/model/OnboardingEntryModel.kt @@ -3,7 +3,7 @@ package com.tangem.features.onboarding.v2.entry.impl.model import com.arkivanov.decompose.router.stack.StackNavigation import com.arkivanov.decompose.router.stack.navigate import com.tangem.common.routing.AppRoute -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.navigation.Router @@ -25,7 +25,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.launch import javax.inject.Inject -@ComponentScoped +@ModelScoped internal class OnboardingEntryModel @Inject constructor( paramsContainer: ParamsContainer, override val dispatchers: CoroutineDispatcherProvider, diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/accesscode/model/MultiWalletAccessCodeModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/accesscode/model/MultiWalletAccessCodeModel.kt index a2f3f24de7..bd4a37a0b5 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/accesscode/model/MultiWalletAccessCodeModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/accesscode/model/MultiWalletAccessCodeModel.kt @@ -3,7 +3,7 @@ package com.tangem.features.onboarding.v2.multiwallet.impl.child.accesscode.mode import androidx.compose.runtime.Stable import androidx.compose.ui.text.input.TextFieldValue import com.tangem.core.analytics.api.AnalyticsEventHandler -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.features.onboarding.v2.multiwallet.impl.analytics.OnboardingEvent @@ -22,7 +22,7 @@ import javax.inject.Inject private const val MINIMUM_ACCESS_CODE_LENGTH = 4 @Stable -@ComponentScoped +@ModelScoped internal class MultiWalletAccessCodeModel @Inject constructor( paramsContainer: ParamsContainer, override val dispatchers: CoroutineDispatcherProvider, diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/model/MultiWalletBackupModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/model/MultiWalletBackupModel.kt index 48d3ead42a..46f6135d72 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/model/MultiWalletBackupModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/model/MultiWalletBackupModel.kt @@ -7,7 +7,7 @@ import com.tangem.common.core.TangemSdkError import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.models.AnalyticsParam import com.tangem.core.analytics.models.event.OnboardingAnalyticsEvent -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.ui.UiMessageSender @@ -38,7 +38,7 @@ import kotlinx.coroutines.launch import javax.inject.Inject @Stable -@ComponentScoped +@ModelScoped @Suppress("LongParameterList") class MultiWalletBackupModel @Inject constructor( paramsContainer: ParamsContainer, diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/chooseoption/model/Wallet1ChooseOptionModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/chooseoption/model/Wallet1ChooseOptionModel.kt index 69d37f496f..c460852063 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/chooseoption/model/Wallet1ChooseOptionModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/chooseoption/model/Wallet1ChooseOptionModel.kt @@ -2,7 +2,7 @@ package com.tangem.features.onboarding.v2.multiwallet.impl.child.chooseoption.mo import androidx.compose.runtime.Stable import com.tangem.core.analytics.api.AnalyticsEventHandler -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.domain.card.repository.CardRepository @@ -21,7 +21,7 @@ import kotlinx.coroutines.launch import javax.inject.Inject @Stable -@ComponentScoped +@ModelScoped internal class Wallet1ChooseOptionModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, paramsContainer: ParamsContainer, diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/model/MultiWalletCreateWalletModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/model/MultiWalletCreateWalletModel.kt index c41f5bdff9..235a5a45ff 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/model/MultiWalletCreateWalletModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/model/MultiWalletCreateWalletModel.kt @@ -4,7 +4,7 @@ import androidx.compose.runtime.Stable import com.tangem.common.CompletionResult import com.tangem.common.core.TangemSdkError import com.tangem.core.analytics.api.AnalyticsEventHandler -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.ui.extensions.resourceReference @@ -34,7 +34,7 @@ import javax.inject.Inject @Suppress("LongParameterList") @Stable -@ComponentScoped +@ModelScoped internal class MultiWalletCreateWalletModel @Inject constructor( paramsContainer: ParamsContainer, override val dispatchers: CoroutineDispatcherProvider, diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/model/MultiWalletFinalizeModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/model/MultiWalletFinalizeModel.kt index c87784f4ad..a176555bb7 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/model/MultiWalletFinalizeModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/model/MultiWalletFinalizeModel.kt @@ -3,7 +3,7 @@ package com.tangem.features.onboarding.v2.multiwallet.impl.child.finalize.model import androidx.compose.runtime.Stable import com.tangem.common.CompletionResult import com.tangem.common.core.TangemSdkError -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.domain.card.repository.CardRepository @@ -39,7 +39,7 @@ import javax.inject.Inject @Suppress("LongParameterList") @Stable -@ComponentScoped +@ModelScoped internal class MultiWalletFinalizeModel @Inject constructor( paramsContainer: ParamsContainer, override val dispatchers: CoroutineDispatcherProvider, diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/scanprimary/model/Wallet1ScanPrimaryModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/scanprimary/model/Wallet1ScanPrimaryModel.kt index 504e556fbc..621279a14b 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/scanprimary/model/Wallet1ScanPrimaryModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/scanprimary/model/Wallet1ScanPrimaryModel.kt @@ -2,7 +2,7 @@ package com.tangem.features.onboarding.v2.multiwallet.impl.child.scanprimary.mod import androidx.compose.runtime.Stable import com.tangem.common.CompletionResult -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.domain.common.util.cardTypesResolver @@ -15,7 +15,7 @@ import kotlinx.coroutines.launch import javax.inject.Inject @Stable -@ComponentScoped +@ModelScoped internal class Wallet1ScanPrimaryModel @Inject constructor( paramsContainer: ParamsContainer, override val dispatchers: CoroutineDispatcherProvider, diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/model/MultiWalletSeedPhraseModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/model/MultiWalletSeedPhraseModel.kt index 93bc3e193c..7b75b80c4e 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/model/MultiWalletSeedPhraseModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/seedphrase/model/MultiWalletSeedPhraseModel.kt @@ -4,7 +4,7 @@ import androidx.compose.runtime.Stable import com.tangem.common.CompletionResult import com.tangem.common.core.TangemSdkError import com.tangem.core.analytics.api.AnalyticsEventHandler -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.navigation.url.UrlOpener @@ -35,7 +35,7 @@ import javax.inject.Inject // ============================================= @Suppress("LongParameterList") @Stable -@ComponentScoped +@ModelScoped internal class MultiWalletSeedPhraseModel @Inject constructor( paramsContainer: ParamsContainer, override val dispatchers: CoroutineDispatcherProvider, diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/di/ComponentModule.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/di/ComponentModule.kt index 1aee88709b..9054f73faa 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/di/ComponentModule.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/di/ComponentModule.kt @@ -1,6 +1,6 @@ package com.tangem.features.onboarding.v2.multiwallet.impl.di -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model import com.tangem.features.onboarding.v2.multiwallet.api.OnboardingMultiWalletComponent import com.tangem.features.onboarding.v2.multiwallet.impl.DefaultOnboardingMultiWalletComponent @@ -30,7 +30,7 @@ internal interface ComponentModule { } @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) internal interface ModelModule { @Binds diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/model/OnboardingMultiWalletModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/model/OnboardingMultiWalletModel.kt index ad4786a6b7..725d8be92e 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/model/OnboardingMultiWalletModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/model/OnboardingMultiWalletModel.kt @@ -1,7 +1,7 @@ package com.tangem.features.onboarding.v2.multiwallet.impl.model import com.tangem.core.analytics.api.AnalyticsEventHandler -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.navigation.Router @@ -22,7 +22,7 @@ import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import javax.inject.Inject -@ComponentScoped +@ModelScoped internal class OnboardingMultiWalletModel @Inject constructor( paramsContainer: ParamsContainer, override val dispatchers: CoroutineDispatcherProvider, diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/accesscode/model/OnboardingVisaAccessCodeModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/accesscode/model/OnboardingVisaAccessCodeModel.kt index 2f56bd8ddb..086d02041d 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/accesscode/model/OnboardingVisaAccessCodeModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/accesscode/model/OnboardingVisaAccessCodeModel.kt @@ -4,7 +4,7 @@ import androidx.compose.runtime.Stable import androidx.compose.ui.text.input.TextFieldValue import com.tangem.common.CompletionResult import com.tangem.common.extensions.toHexString -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.domain.visa.model.VisaCardActivationStatus @@ -26,7 +26,7 @@ import kotlinx.coroutines.launch import javax.inject.Inject @Stable -@ComponentScoped +@ModelScoped internal class OnboardingVisaAccessCodeModel @Inject constructor( paramsContainer: ParamsContainer, visaActivationRepositoryFactory: VisaActivationRepository.Factory, diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/approve/model/OnboardingVisaApproveModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/approve/model/OnboardingVisaApproveModel.kt index 245dbb83cb..396a8039b2 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/approve/model/OnboardingVisaApproveModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/approve/model/OnboardingVisaApproveModel.kt @@ -3,7 +3,7 @@ package com.tangem.features.onboarding.v2.visa.impl.child.approve.model import androidx.compose.runtime.Stable import com.tangem.common.CompletionResult import com.tangem.common.extensions.toHexString -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.domain.visa.model.VisaCardId @@ -21,7 +21,7 @@ import kotlinx.coroutines.launch import javax.inject.Inject @Stable -@ComponentScoped +@ModelScoped internal class OnboardingVisaApproveModel @Inject constructor( paramsContainer: ParamsContainer, visaActivationRepositoryFactory: VisaActivationRepository.Factory, diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/choosewallet/model/OnboardingVisaChooseWalletModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/choosewallet/model/OnboardingVisaChooseWalletModel.kt index 4f6629cae9..381cfc11aa 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/choosewallet/model/OnboardingVisaChooseWalletModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/choosewallet/model/OnboardingVisaChooseWalletModel.kt @@ -1,7 +1,7 @@ package com.tangem.features.onboarding.v2.visa.impl.child.choosewallet.model import androidx.compose.runtime.Stable -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.ui.extensions.TextReference import com.tangem.features.onboarding.v2.impl.R @@ -18,7 +18,7 @@ import kotlinx.coroutines.launch import javax.inject.Inject @Stable -@ComponentScoped +@ModelScoped internal class OnboardingVisaChooseWalletModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, ) : Model() { diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/inprogress/model/OnboardingVisaInProgressModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/inprogress/model/OnboardingVisaInProgressModel.kt index 48ac5a404d..3d79bce2c1 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/inprogress/model/OnboardingVisaInProgressModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/inprogress/model/OnboardingVisaInProgressModel.kt @@ -2,7 +2,7 @@ package com.tangem.features.onboarding.v2.visa.impl.child.inprogress.model import androidx.compose.runtime.Stable import com.tangem.common.extensions.toHexString -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.datasource.local.visa.VisaAuthTokenStorage @@ -27,7 +27,7 @@ import javax.inject.Inject @Suppress("LongParameterList") @Stable -@ComponentScoped +@ModelScoped internal class OnboardingVisaInProgressModel @Inject constructor( paramsContainer: ParamsContainer, visaActivationRepositoryFactory: VisaActivationRepository.Factory, diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/otherwallet/model/OnboardingVisaOtherWalletModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/otherwallet/model/OnboardingVisaOtherWalletModel.kt index 887cd4759f..53c043fbea 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/otherwallet/model/OnboardingVisaOtherWalletModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/otherwallet/model/OnboardingVisaOtherWalletModel.kt @@ -2,7 +2,7 @@ package com.tangem.features.onboarding.v2.visa.impl.child.otherwallet.model import androidx.compose.runtime.Stable import com.tangem.common.extensions.toHexString -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.navigation.share.ShareManager @@ -22,7 +22,7 @@ import kotlinx.coroutines.launch import javax.inject.Inject @Stable -@ComponentScoped +@ModelScoped internal class OnboardingVisaOtherWalletModel @Inject constructor( paramsContainer: ParamsContainer, visaActivationRepositoryFactory: VisaActivationRepository.Factory, diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/pincode/model/OnboardingVisaPinCodeModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/pincode/model/OnboardingVisaPinCodeModel.kt index deae6ff93c..0b02574d50 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/pincode/model/OnboardingVisaPinCodeModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/pincode/model/OnboardingVisaPinCodeModel.kt @@ -2,7 +2,7 @@ package com.tangem.features.onboarding.v2.visa.impl.child.pincode.model import androidx.compose.runtime.Stable import com.tangem.common.extensions.toHexString -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.datasource.local.visa.VisaAuthTokenStorage @@ -26,7 +26,7 @@ import kotlinx.coroutines.withContext import javax.inject.Inject @Stable -@ComponentScoped +@ModelScoped @Suppress("LongParameterList") internal class OnboardingVisaPinCodeModel @Inject constructor( paramsContainer: ParamsContainer, diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/welcome/model/OnboardingVisaWelcomeModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/welcome/model/OnboardingVisaWelcomeModel.kt index 526e51806f..82a7092b99 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/welcome/model/OnboardingVisaWelcomeModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/child/welcome/model/OnboardingVisaWelcomeModel.kt @@ -2,7 +2,7 @@ package com.tangem.features.onboarding.v2.visa.impl.child.welcome.model import com.tangem.common.CompletionResult import com.tangem.common.extensions.toHexString -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.domain.visa.model.VisaCardId @@ -22,7 +22,7 @@ import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import javax.inject.Inject -@ComponentScoped +@ModelScoped internal class OnboardingVisaWelcomeModel @Inject constructor( paramsContainer: ParamsContainer, override val dispatchers: CoroutineDispatcherProvider, diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/di/ComponentModule.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/di/ComponentModule.kt index 15349b614b..d4421b9169 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/di/ComponentModule.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/di/ComponentModule.kt @@ -1,6 +1,6 @@ package com.tangem.features.onboarding.v2.visa.impl.di -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model import com.tangem.features.onboarding.v2.visa.api.OnboardingVisaComponent import com.tangem.features.onboarding.v2.visa.impl.DefaultOnboardingVisaComponent @@ -30,7 +30,7 @@ internal interface ComponentModule { } @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) internal interface ModelModule { @Binds diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/model/OnboardingVisaModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/model/OnboardingVisaModel.kt index ca2b727f7c..5e98a81f2b 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/model/OnboardingVisaModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/visa/impl/model/OnboardingVisaModel.kt @@ -6,7 +6,7 @@ import com.arkivanov.decompose.router.stack.StackNavigation import com.arkivanov.decompose.router.stack.pop import com.arkivanov.decompose.router.stack.push import com.arkivanov.decompose.router.stack.pushNew -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.domain.common.visa.VisaUtilities @@ -31,7 +31,7 @@ import kotlinx.coroutines.launch import javax.inject.Inject @Stable -@ComponentScoped +@ModelScoped internal class OnboardingVisaModel @Inject constructor( paramsContainer: ParamsContainer, override val dispatchers: CoroutineDispatcherProvider, diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/confirmresidency/di/OnrampConfirmResidencyModelModule.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/confirmresidency/di/OnrampConfirmResidencyModelModule.kt index ab79a46e1c..b58e525556 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/confirmresidency/di/OnrampConfirmResidencyModelModule.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/confirmresidency/di/OnrampConfirmResidencyModelModule.kt @@ -1,6 +1,6 @@ package com.tangem.features.onramp.confirmresidency.di -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model import com.tangem.features.onramp.confirmresidency.model.ConfirmResidencyModel import dagger.Binds @@ -10,7 +10,7 @@ import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) internal interface OnrampConfirmResidencyModelModule { @Binds @IntoMap diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/confirmresidency/model/ConfirmResidencyModel.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/confirmresidency/model/ConfirmResidencyModel.kt index 270c3e6f73..3466152b67 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/confirmresidency/model/ConfirmResidencyModel.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/confirmresidency/model/ConfirmResidencyModel.kt @@ -3,7 +3,7 @@ package com.tangem.features.onramp.confirmresidency.model import com.arkivanov.decompose.router.slot.SlotNavigation import com.arkivanov.decompose.router.slot.activate import com.tangem.core.analytics.api.AnalyticsEventHandler -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.navigation.Router @@ -20,7 +20,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.launch import javax.inject.Inject -@ComponentScoped +@ModelScoped internal class ConfirmResidencyModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val analyticsEventHandler: AnalyticsEventHandler, diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/hottokens/di/HotCryptoModelModule.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/hottokens/di/HotCryptoModelModule.kt index 7757a30590..7ed81b78db 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/hottokens/di/HotCryptoModelModule.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/hottokens/di/HotCryptoModelModule.kt @@ -1,6 +1,6 @@ package com.tangem.features.onramp.hottokens.di -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model import com.tangem.features.onramp.hottokens.model.HotCryptoModel import dagger.Binds @@ -10,7 +10,7 @@ import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) internal interface HotCryptoModelModule { @Binds diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/hottokens/model/HotCryptoModel.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/hottokens/model/HotCryptoModel.kt index 29a5b07946..be622c09d1 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/hottokens/model/HotCryptoModel.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/hottokens/model/HotCryptoModel.kt @@ -4,7 +4,7 @@ import arrow.core.getOrElse import com.arkivanov.decompose.router.slot.SlotNavigation import com.arkivanov.decompose.router.slot.activate import com.arkivanov.decompose.router.slot.dismiss -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.ui.components.token.state.TokenItemState @@ -40,7 +40,7 @@ import javax.inject.Inject * [REDACTED_AUTHOR] */ -@ComponentScoped +@ModelScoped internal class HotCryptoModel @Inject constructor( paramsContainer: ParamsContainer, getHotCryptoUseCase: GetHotCryptoUseCase, diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/hottokens/portfolio/di/OnrampAddToPortfolioModelModule.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/hottokens/portfolio/di/OnrampAddToPortfolioModelModule.kt index 086a66b0d0..4db40ffeca 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/hottokens/portfolio/di/OnrampAddToPortfolioModelModule.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/hottokens/portfolio/di/OnrampAddToPortfolioModelModule.kt @@ -1,6 +1,6 @@ package com.tangem.features.onramp.hottokens.portfolio.di -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model import com.tangem.features.onramp.hottokens.portfolio.model.OnrampAddToPortfolioModel import dagger.Binds @@ -10,7 +10,7 @@ import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) internal interface OnrampAddToPortfolioModelModule { @Binds diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/hottokens/portfolio/model/OnrampAddToPortfolioModel.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/hottokens/portfolio/model/OnrampAddToPortfolioModel.kt index 9ca6e59406..ed8f3c543a 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/hottokens/portfolio/model/OnrampAddToPortfolioModel.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/hottokens/portfolio/model/OnrampAddToPortfolioModel.kt @@ -1,7 +1,7 @@ package com.tangem.features.onramp.hottokens.portfolio.model import arrow.core.getOrElse -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.domain.card.DerivePublicKeysUseCase @@ -29,7 +29,7 @@ import javax.inject.Inject * [REDACTED_AUTHOR] */ -@ComponentScoped +@ModelScoped internal class OnrampAddToPortfolioModel @Inject constructor( paramsContainer: ParamsContainer, override val dispatchers: CoroutineDispatcherProvider, diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/di/OnrampMainComponentModelModule.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/di/OnrampMainComponentModelModule.kt index 99826bae5d..f3bbdba606 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/di/OnrampMainComponentModelModule.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/di/OnrampMainComponentModelModule.kt @@ -1,6 +1,6 @@ package com.tangem.features.onramp.main.di -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model import com.tangem.features.onramp.main.model.OnrampMainComponentModel import dagger.Binds @@ -10,7 +10,7 @@ import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) internal interface OnrampMainComponentModelModule { @Binds diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/providers/di/SelectProviderModelModule.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/providers/di/SelectProviderModelModule.kt index 812d6bd45d..3719bf0fae 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/providers/di/SelectProviderModelModule.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/providers/di/SelectProviderModelModule.kt @@ -1,6 +1,6 @@ package com.tangem.features.onramp.providers.di -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model import com.tangem.features.onramp.providers.model.SelectProviderModel import dagger.Binds @@ -10,7 +10,7 @@ import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) internal interface SelectProviderModelModule { @Binds diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/providers/model/SelectProviderModel.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/providers/model/SelectProviderModel.kt index bc077ed6a3..ea142aa30f 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/providers/model/SelectProviderModel.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/providers/model/SelectProviderModel.kt @@ -4,7 +4,7 @@ import com.arkivanov.decompose.router.slot.SlotNavigation import com.arkivanov.decompose.router.slot.activate import com.arkivanov.decompose.router.slot.dismiss import com.tangem.core.analytics.api.AnalyticsEventHandler -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.ui.extensions.resourceReference @@ -40,7 +40,7 @@ import java.math.BigDecimal import javax.inject.Inject @Suppress("LongParameterList") -@ComponentScoped +@ModelScoped internal class SelectProviderModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val analyticsEventHandler: AnalyticsEventHandler, diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/redirect/di/OnrampRedirectModelModule.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/redirect/di/OnrampRedirectModelModule.kt index 21547db511..619e70ca91 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/redirect/di/OnrampRedirectModelModule.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/redirect/di/OnrampRedirectModelModule.kt @@ -1,6 +1,6 @@ package com.tangem.features.onramp.redirect.di -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model import com.tangem.features.onramp.redirect.model.OnrampRedirectModel import dagger.Binds @@ -10,7 +10,7 @@ import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) internal interface OnrampRedirectModelModule { @Binds diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selectcountry/di/OnrampSelectCountryModelModule.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selectcountry/di/OnrampSelectCountryModelModule.kt index 1230e7174d..8be0024799 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selectcountry/di/OnrampSelectCountryModelModule.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selectcountry/di/OnrampSelectCountryModelModule.kt @@ -1,6 +1,6 @@ package com.tangem.features.onramp.selectcountry.di -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model import com.tangem.features.onramp.selectcountry.model.OnrampSelectCountryModel import dagger.Binds @@ -10,7 +10,7 @@ import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) internal interface OnrampSelectCountryModelModule { @Binds diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selectcountry/model/OnrampSelectCountryModel.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selectcountry/model/OnrampSelectCountryModel.kt index 94296a59e1..e7a8f8dedf 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selectcountry/model/OnrampSelectCountryModel.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selectcountry/model/OnrampSelectCountryModel.kt @@ -1,7 +1,7 @@ package com.tangem.features.onramp.selectcountry.model import com.tangem.core.analytics.api.AnalyticsEventHandler -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.ui.components.fields.entity.SearchBarUM @@ -35,7 +35,7 @@ import kotlinx.coroutines.launch import javax.inject.Inject @Suppress("LongParameterList") -@ComponentScoped +@ModelScoped internal class OnrampSelectCountryModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val analyticsEventHandler: AnalyticsEventHandler, diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selectcurrency/di/OnrampSelectCurrencyModelModule.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selectcurrency/di/OnrampSelectCurrencyModelModule.kt index 3541b9cb45..f699c1205c 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selectcurrency/di/OnrampSelectCurrencyModelModule.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selectcurrency/di/OnrampSelectCurrencyModelModule.kt @@ -1,6 +1,6 @@ package com.tangem.features.onramp.selectcurrency.di -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model import com.tangem.features.onramp.selectcurrency.model.OnrampSelectCurrencyModel import dagger.Binds @@ -10,7 +10,7 @@ import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) internal interface OnrampSelectCurrencyModelModule { @Binds diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selectcurrency/model/OnrampSelectCurrencyModel.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selectcurrency/model/OnrampSelectCurrencyModel.kt index a297ae455a..93d64b7bca 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selectcurrency/model/OnrampSelectCurrencyModel.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selectcurrency/model/OnrampSelectCurrencyModel.kt @@ -1,7 +1,7 @@ package com.tangem.features.onramp.selectcurrency.model import com.tangem.core.analytics.api.AnalyticsEventHandler -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.ui.components.fields.entity.SearchBarUM @@ -35,7 +35,7 @@ import kotlinx.coroutines.launch import javax.inject.Inject @Suppress("LongParameterList") -@ComponentScoped +@ModelScoped internal class OnrampSelectCurrencyModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val analyticsEventHandler: AnalyticsEventHandler, diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selecttoken/di/OnrampOperationModelModule.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selecttoken/di/OnrampOperationModelModule.kt index 9c9eb054d2..7488094564 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selecttoken/di/OnrampOperationModelModule.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selecttoken/di/OnrampOperationModelModule.kt @@ -1,6 +1,6 @@ package com.tangem.features.onramp.selecttoken.di -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model import com.tangem.features.onramp.selecttoken.model.OnrampOperationModel import dagger.Binds @@ -10,7 +10,7 @@ import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) internal interface OnrampOperationModelModule { @Binds diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selecttoken/model/OnrampOperationModel.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selecttoken/model/OnrampOperationModel.kt index b0555c7c63..770e77d257 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selecttoken/model/OnrampOperationModel.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selecttoken/model/OnrampOperationModel.kt @@ -6,7 +6,7 @@ import com.tangem.common.ui.alerts.models.AlertDemoModeUM import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.models.AnalyticsParam import com.tangem.core.analytics.models.event.MainScreenAnalyticsEvent -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.ui.UiMessageSender @@ -33,7 +33,7 @@ import kotlinx.coroutines.launch import javax.inject.Inject @Suppress("LongParameterList") -@ComponentScoped +@ModelScoped internal class OnrampOperationModel @Inject constructor( paramsContainer: ParamsContainer, getWalletsUseCase: GetWalletsUseCase, diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/settings/di/OnrampSettingsModelModule.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/settings/di/OnrampSettingsModelModule.kt index f62678e7ee..8b90098a7f 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/settings/di/OnrampSettingsModelModule.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/settings/di/OnrampSettingsModelModule.kt @@ -1,6 +1,6 @@ package com.tangem.features.onramp.settings.di -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model import com.tangem.features.onramp.settings.model.OnrampSettingsModel import dagger.Binds @@ -10,7 +10,7 @@ import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) internal interface OnrampSettingsModelModule { @Binds diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/settings/model/OnrampSettingsModel.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/settings/model/OnrampSettingsModel.kt index a67426d614..95ed639744 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/settings/model/OnrampSettingsModel.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/settings/model/OnrampSettingsModel.kt @@ -4,7 +4,7 @@ import arrow.core.Either import com.arkivanov.decompose.router.slot.SlotNavigation import com.arkivanov.decompose.router.slot.activate import com.tangem.core.analytics.api.AnalyticsEventHandler -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.domain.onramp.GetOnrampCountryUseCase @@ -21,7 +21,7 @@ import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.flow.* import javax.inject.Inject -@ComponentScoped +@ModelScoped internal class OnrampSettingsModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val analyticsEventHandler: AnalyticsEventHandler, diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/success/di/OnrampSuccessComponentModelModule.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/success/di/OnrampSuccessComponentModelModule.kt index ba6f6664fd..59b1e6f64a 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/success/di/OnrampSuccessComponentModelModule.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/success/di/OnrampSuccessComponentModelModule.kt @@ -1,6 +1,6 @@ package com.tangem.features.onramp.success.di -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model import com.tangem.features.onramp.success.model.OnrampSuccessComponentModel import dagger.Binds @@ -10,7 +10,7 @@ import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) internal interface OnrampSuccessComponentModelModule { @Binds @IntoMap diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/swap/availablepairs/di/AvailableSwapPairsModelModule.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/swap/availablepairs/di/AvailableSwapPairsModelModule.kt index 6bf7c67133..b68b705703 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/swap/availablepairs/di/AvailableSwapPairsModelModule.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/swap/availablepairs/di/AvailableSwapPairsModelModule.kt @@ -1,6 +1,6 @@ package com.tangem.features.onramp.swap.availablepairs.di -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model import com.tangem.features.onramp.swap.availablepairs.model.AvailableSwapPairsModel import dagger.Binds @@ -10,7 +10,7 @@ import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) internal interface AvailableSwapPairsModelModule { @Binds diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/swap/di/SwapSelectTokensModelModule.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/swap/di/SwapSelectTokensModelModule.kt index f7e0741156..01b1201354 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/swap/di/SwapSelectTokensModelModule.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/swap/di/SwapSelectTokensModelModule.kt @@ -1,6 +1,6 @@ package com.tangem.features.onramp.swap.di -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model import com.tangem.features.onramp.swap.model.SwapSelectTokensModel import dagger.Binds @@ -10,7 +10,7 @@ import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) internal interface SwapSelectTokensModelModule { @Binds diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/tokenlist/di/OnrampTokenListModelModule.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/tokenlist/di/OnrampTokenListModelModule.kt index 7977384f55..0f35146dfe 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/tokenlist/di/OnrampTokenListModelModule.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/tokenlist/di/OnrampTokenListModelModule.kt @@ -1,6 +1,6 @@ package com.tangem.features.onramp.tokenlist.di -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model import com.tangem.features.onramp.tokenlist.model.OnrampTokenListModel import dagger.Binds @@ -10,7 +10,7 @@ import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) internal interface OnrampTokenListModelModule { @Binds diff --git a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/model/PushNotificationsModel.kt b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/model/PushNotificationsModel.kt index 4043db3350..fb23fe3946 100644 --- a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/model/PushNotificationsModel.kt +++ b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/model/PushNotificationsModel.kt @@ -5,7 +5,7 @@ import com.tangem.common.routing.AppRoute import com.tangem.common.routing.AppRouter import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.models.AnalyticsParam -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.domain.settings.NeverRequestPermissionUseCase import com.tangem.domain.settings.NeverToInitiallyAskPermissionUseCase @@ -16,7 +16,7 @@ import kotlinx.coroutines.launch import javax.inject.Inject @Stable -@ComponentScoped +@ModelScoped class PushNotificationsModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val neverRequestPermissionUseCase: NeverRequestPermissionUseCase, diff --git a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/model/QrScanningModel.kt b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/model/QrScanningModel.kt index 1ba92657ba..ce3750e0c0 100644 --- a/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/model/QrScanningModel.kt +++ b/features/qr-scanning/impl/src/main/java/com/tangem/feature/qrscanning/model/QrScanningModel.kt @@ -2,7 +2,7 @@ package com.tangem.feature.qrscanning.model import androidx.compose.runtime.Stable import com.tangem.common.routing.AppRouter -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.navigation.settings.SettingsManager @@ -23,7 +23,7 @@ import javax.inject.Inject @Suppress("LongParameterList") @Stable -@ComponentScoped +@ModelScoped internal class QrScanningModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, paramsContainer: ParamsContainer, diff --git a/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/di/ReferralDomainModule.kt b/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/di/ReferralDomainModule.kt index 07ec550009..4e5166e070 100644 --- a/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/di/ReferralDomainModule.kt +++ b/features/referral/domain/src/main/java/com/tangem/feature/referral/domain/di/ReferralDomainModule.kt @@ -1,7 +1,7 @@ package com.tangem.feature.referral.domain.di -import com.tangem.core.decompose.di.ComponentScoped -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelScoped +import com.tangem.core.decompose.di.ModelComponent import com.tangem.domain.card.DerivePublicKeysUseCase import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase import com.tangem.domain.wallets.usecase.GetUserWalletUseCase @@ -14,11 +14,11 @@ import dagger.Provides import dagger.hilt.InstallIn @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) class ReferralDomainModule { @Provides - @ComponentScoped + @ModelScoped fun provideReferralInteractor( referralRepository: ReferralRepository, userWalletManager: UserWalletManager, diff --git a/features/referral/impl/src/main/java/com/tangem/feature/referral/model/ReferralModel.kt b/features/referral/impl/src/main/java/com/tangem/feature/referral/model/ReferralModel.kt index 621ddbe1aa..a2379d3f8a 100644 --- a/features/referral/impl/src/main/java/com/tangem/feature/referral/model/ReferralModel.kt +++ b/features/referral/impl/src/main/java/com/tangem/feature/referral/model/ReferralModel.kt @@ -6,7 +6,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import com.tangem.common.routing.AppRouter import com.tangem.core.analytics.api.AnalyticsEventHandler -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.navigation.share.ShareManager @@ -30,7 +30,7 @@ import javax.inject.Inject @Suppress("LongParameterList") @Stable -@ComponentScoped +@ModelScoped internal class ReferralModel @Inject constructor( paramsContainer: ParamsContainer, override val dispatchers: CoroutineDispatcherProvider, diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/di/SendModule.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/di/SendModule.kt index da5936ec7d..86c1ce5b9f 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/di/SendModule.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/di/SendModule.kt @@ -1,7 +1,7 @@ package com.tangem.features.send.impl.di -import com.tangem.core.decompose.di.ComponentScoped -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelScoped +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model import com.tangem.features.send.api.SendComponent import com.tangem.features.send.impl.DefaultSendComponent @@ -29,10 +29,10 @@ internal interface SendModule { } @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) internal interface SendModelModule { @Binds - @ComponentScoped + @ModelScoped fun bindRouter(router: DefaultSendRouter): InnerSendRouter } \ No newline at end of file diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/navigation/DefaultSendRouter.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/navigation/DefaultSendRouter.kt index fabef6c208..788ea93ba2 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/navigation/DefaultSendRouter.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/navigation/DefaultSendRouter.kt @@ -2,14 +2,14 @@ package com.tangem.features.send.impl.navigation import com.tangem.common.routing.AppRoute import com.tangem.common.routing.AppRouter -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.navigation.url.UrlOpener import com.tangem.domain.qrscanning.models.SourceType import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.wallets.models.UserWalletId import javax.inject.Inject -@ComponentScoped +@ModelScoped internal class DefaultSendRouter @Inject constructor( private val router: AppRouter, private val urlOpener: UrlOpener, diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/model/SendModel.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/model/SendModel.kt index 6c91254744..91af0581fc 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/model/SendModel.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/model/SendModel.kt @@ -13,7 +13,7 @@ import com.tangem.common.ui.amountScreen.models.AmountState import com.tangem.common.ui.amountScreen.models.EnterAmountBoundary import com.tangem.common.ui.notifications.NotificationUM import com.tangem.core.analytics.api.AnalyticsEventHandler -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.navigation.share.ShareManager @@ -75,7 +75,7 @@ import kotlin.properties.Delegates @Suppress("LongParameterList", "TooManyFunctions", "LargeClass") @Stable -@ComponentScoped +@ModelScoped internal class SendModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val getUserWalletUseCase: GetUserWalletUseCase, diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/di/StakingModule.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/di/StakingModule.kt index c2fc6404b9..912662375d 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/di/StakingModule.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/di/StakingModule.kt @@ -1,7 +1,7 @@ package com.tangem.features.staking.impl.di -import com.tangem.core.decompose.di.ComponentScoped -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelScoped +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model import com.tangem.features.staking.api.StakingComponent import com.tangem.features.staking.impl.DefaultStakingComponent @@ -29,10 +29,10 @@ internal interface StakingModule { } @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) internal interface StakingComponentModule { @Binds - @ComponentScoped + @ModelScoped fun bindRouter(impl: DefaultStakingRouter): InnerStakingRouter } \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/navigation/DefaultStakingRouter.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/navigation/DefaultStakingRouter.kt index 9a600a0a93..c149089cad 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/navigation/DefaultStakingRouter.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/navigation/DefaultStakingRouter.kt @@ -2,13 +2,13 @@ package com.tangem.features.staking.impl.navigation import com.tangem.common.routing.AppRoute import com.tangem.common.routing.AppRouter -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.navigation.url.UrlOpener import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.wallets.models.UserWalletId import javax.inject.Inject -@ComponentScoped +@ModelScoped internal class DefaultStakingRouter @Inject constructor( private val urlOpener: UrlOpener, private val router: AppRouter, diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt index 846032569e..b57e0256f7 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt @@ -12,7 +12,7 @@ import com.tangem.common.ui.bottomsheet.permission.state.GiveTxPermissionBottomS import com.tangem.common.ui.notifications.NotificationUM import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.api.ParamsInterceptorHolder -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.navigation.share.ShareManager @@ -89,7 +89,7 @@ import kotlin.properties.Delegates @Suppress("LargeClass", "TooManyFunctions", "LongParameterList") @Stable -@ComponentScoped +@ModelScoped internal class StakingModel @Inject constructor( paramsContainer: ParamsContainer, private val stateController: StakingStateController, diff --git a/features/stories/impl/src/main/java/com/tangem/feature/stories/impl/di/StoriesModelModule.kt b/features/stories/impl/src/main/java/com/tangem/feature/stories/impl/di/StoriesModelModule.kt index de6c20e886..f686729341 100644 --- a/features/stories/impl/src/main/java/com/tangem/feature/stories/impl/di/StoriesModelModule.kt +++ b/features/stories/impl/src/main/java/com/tangem/feature/stories/impl/di/StoriesModelModule.kt @@ -1,6 +1,6 @@ package com.tangem.feature.stories.impl.di -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model import com.tangem.feature.stories.impl.model.StoriesModel import dagger.Binds @@ -10,7 +10,7 @@ import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) internal interface StoriesModelModule { @Binds diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/di/SwapModelModule.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/di/SwapModelModule.kt index 911918e2b6..4a40e11ce5 100644 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/di/SwapModelModule.kt +++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/di/SwapModelModule.kt @@ -1,6 +1,6 @@ package com.tangem.feature.swap.di -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model import com.tangem.feature.swap.model.SwapModel import dagger.Binds @@ -10,7 +10,7 @@ import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) internal interface SwapModelModule { @Binds diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt index 1207f32248..05a89386ef 100644 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt +++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt @@ -12,7 +12,7 @@ import com.tangem.common.ui.bottomsheet.permission.state.GiveTxPermissionState.I import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.models.AnalyticsParam import com.tangem.core.analytics.models.Basic -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.navigation.url.UrlOpener @@ -76,7 +76,7 @@ typealias SuccessLoadedSwapData = Map @Suppress("LongParameterList", "LargeClass") @Stable -@ComponentScoped +@ModelScoped internal class SwapModel @Inject constructor( paramsContainer: ParamsContainer, override val dispatchers: CoroutineDispatcherProvider, diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/di/TokenDetailsModule.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/di/TokenDetailsModule.kt index a7ad3dd026..356a4c6fe4 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/di/TokenDetailsModule.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/di/TokenDetailsModule.kt @@ -1,7 +1,7 @@ package com.tangem.feature.tokendetails.di -import com.tangem.core.decompose.di.ComponentScoped -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelScoped +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model import com.tangem.feature.tokendetails.DefaultTokenDetailsComponent import com.tangem.feature.tokendetails.presentation.router.DefaultTokenDetailsRouter @@ -29,10 +29,10 @@ internal interface TokenDetailsModule { } @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) internal interface StakingComponentModule { @Binds - @ComponentScoped + @ModelScoped fun bindRouter(impl: DefaultTokenDetailsRouter): InnerTokenDetailsRouter } \ No newline at end of file diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/router/DefaultTokenDetailsRouter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/router/DefaultTokenDetailsRouter.kt index 4ffdf4c587..9d48197b61 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/router/DefaultTokenDetailsRouter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/router/DefaultTokenDetailsRouter.kt @@ -2,7 +2,7 @@ package com.tangem.feature.tokendetails.presentation.router import com.tangem.common.routing.AppRoute import com.tangem.common.routing.AppRouter -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.navigation.share.ShareManager import com.tangem.core.navigation.url.UrlOpener import com.tangem.domain.staking.model.stakekit.Yield @@ -10,7 +10,7 @@ import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.wallets.models.UserWalletId import javax.inject.Inject -@ComponentScoped +@ModelScoped internal class DefaultTokenDetailsRouter @Inject constructor( private val router: AppRouter, private val urlOpener: UrlOpener, diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt index 90e3f19c4d..81bc77d74f 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt @@ -10,7 +10,7 @@ import com.tangem.common.ui.expressStatus.ExpressStatusBottomSheetConfig import com.tangem.common.ui.expressStatus.state.ExpressTransactionStateUM import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.models.AnalyticsParam -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.di.GlobalUiMessageSender import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer @@ -89,7 +89,7 @@ import javax.inject.Inject @Suppress("LongParameterList", "LargeClass", "TooManyFunctions") @Stable -@ComponentScoped +@ModelScoped internal class TokenDetailsModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val getCurrencyStatusUpdatesUseCase: GetCurrencyStatusUpdatesUseCase, diff --git a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/component/impl/model/RenameWalletModel.kt b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/component/impl/model/RenameWalletModel.kt index 2579a58329..ea34279a52 100644 --- a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/component/impl/model/RenameWalletModel.kt +++ b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/component/impl/model/RenameWalletModel.kt @@ -1,7 +1,7 @@ package com.tangem.feature.walletsettings.component.impl.model import androidx.compose.ui.text.input.TextFieldValue -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.ui.UiMessageSender @@ -36,7 +36,7 @@ import javax.inject.Inject * [REDACTED_AUTHOR] */ -@ComponentScoped +@ModelScoped internal class RenameWalletModel @Inject constructor( paramsContainer: ParamsContainer, getWalletNamesUseCase: GetWalletNamesUseCase, diff --git a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/di/WalletSettingsModelModule.kt b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/di/WalletSettingsModelModule.kt index 6cc2cd67eb..195e71a172 100644 --- a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/di/WalletSettingsModelModule.kt +++ b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/di/WalletSettingsModelModule.kt @@ -1,6 +1,6 @@ package com.tangem.feature.walletsettings.di -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.model.Model import com.tangem.feature.walletsettings.component.impl.model.RenameWalletModel import com.tangem.feature.walletsettings.model.WalletSettingsModel @@ -11,7 +11,7 @@ import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap @Module -@InstallIn(DecomposeComponent::class) +@InstallIn(ModelComponent::class) internal interface WalletSettingsModelModule { @Binds diff --git a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/model/WalletSettingsModel.kt b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/model/WalletSettingsModel.kt index 7952d3d3a1..388279ff22 100644 --- a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/model/WalletSettingsModel.kt +++ b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/model/WalletSettingsModel.kt @@ -6,7 +6,7 @@ import com.arkivanov.decompose.router.slot.activate import com.tangem.common.routing.AppRoute import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.utils.AnalyticsContextProxy -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.navigation.Router @@ -40,7 +40,7 @@ import timber.log.Timber import javax.inject.Inject @Suppress("LongParameterList") -@ComponentScoped +@ModelScoped internal class WalletSettingsModel @Inject constructor( getWalletUseCase: GetUserWalletUseCase, paramsContainer: ParamsContainer, diff --git a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/ItemsBuilder.kt b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/ItemsBuilder.kt index c6b465997b..e57d76ef57 100644 --- a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/ItemsBuilder.kt +++ b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/ItemsBuilder.kt @@ -3,7 +3,7 @@ package com.tangem.feature.walletsettings.utils import com.tangem.common.routing.AppRoute import com.tangem.common.routing.AppRoute.ManageTokens.Source import com.tangem.core.analytics.api.AnalyticsEventHandler -import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.navigation.Router import com.tangem.core.ui.components.block.model.BlockUM import com.tangem.core.ui.extensions.resourceReference @@ -17,7 +17,7 @@ import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import javax.inject.Inject -@ComponentScoped +@ModelScoped internal class ItemsBuilder @Inject constructor( private val router: Router, private val analyticsEventHandler: AnalyticsEventHandler, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/WalletFragment.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/WalletFragment.kt index d8a119f840..446d5c41bb 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/WalletFragment.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/WalletFragment.kt @@ -8,7 +8,7 @@ import com.arkivanov.decompose.defaultComponentContext import com.tangem.common.routing.AppRouter import com.tangem.common.routing.utils.asRouter import com.tangem.core.decompose.context.DefaultAppComponentContext -import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.di.ModelComponent import com.tangem.core.decompose.di.GlobalUiMessageSender import com.tangem.core.decompose.ui.UiMessageSender import com.tangem.core.ui.UiDependencies @@ -38,7 +38,7 @@ internal class WalletFragment : ComposeFragment() { internal lateinit var coroutineDispatcherProvider: CoroutineDispatcherProvider @Inject - internal lateinit var componentBuilder: DecomposeComponent.Builder + internal lateinit var componentBuilder: ModelComponent.Builder @Inject internal lateinit var appRouter: AppRouter