From 9f6e6bcbbfb45d31cdeb972894c8281762e1ee7a Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 16 Feb 2022 13:31:52 +0300 Subject: [PATCH 01/16] Updated on 2026-08-14 --- .../wallet/models/PendingTransaction.kt | 13 ++++++++--- .../middlewares/MultiWalletMiddleware.kt | 23 +++++++++++++++---- .../ui/adapters/PendingTransactionsAdapter.kt | 2 +- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/models/PendingTransaction.kt b/app/src/main/java/com/tangem/tap/features/wallet/models/PendingTransaction.kt index a449bb17ea..722b2c7d03 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/models/PendingTransaction.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/models/PendingTransaction.kt @@ -6,10 +6,12 @@ import com.tangem.blockchain.common.TransactionStatus import com.tangem.blockchain.common.Wallet import com.tangem.tap.common.extensions.toFormattedString import com.tangem.tap.domain.extensions.toSendableAmounts +import java.math.BigDecimal data class PendingTransaction( val address: String?, - val amount: String?, + val amount: BigDecimal?, + val amountUi: String?, val currency: String, val type: PendingTransactionType ) @@ -38,6 +40,7 @@ fun TransactionData.toPendingTransaction(walletAddress: String): PendingTransact return PendingTransaction( if (address == "unknown") null else address, + this.amount.value, this.amount.value?.toFormattedString(amount.decimals), this.amount.currencySymbol, type @@ -61,8 +64,12 @@ fun List.toPendingTransactionsForToken(token: Token, walletAddr return this.mapNotNull { it.toPendingTransactionForToken(token, walletAddress) } } -fun Wallet.getPendingTransactions(): List { - return recentTransactions.toPendingTransactions(address) +fun Wallet.getPendingTransactions(type: PendingTransactionType? = null): List { + val txs = recentTransactions.toPendingTransactions(address) + return when(type) { + null -> txs + else -> txs.filter { it.type == type } + } } fun Wallet.hasPendingTransactions(): Boolean { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt index df4c9120f7..25da5ead8b 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt @@ -13,6 +13,8 @@ import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.currenciesRepository import com.tangem.tap.domain.extensions.makeWalletManagerForApp import com.tangem.tap.domain.extensions.makeWalletManagersForApp +import com.tangem.tap.features.wallet.models.PendingTransactionType +import com.tangem.tap.features.wallet.models.getPendingTransactions import com.tangem.tap.features.wallet.redux.Currency import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.features.wallet.redux.WalletState @@ -22,6 +24,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import java.math.BigDecimal class MultiWalletMiddleware { fun handle( @@ -206,13 +209,25 @@ class MultiWalletMiddleware { scope.launch { when (val result = rentProvider.minimalBalanceForRentExemption()) { is Result.Success -> { + fun isNeedToShowWarning(balance: BigDecimal, rentExempt: BigDecimal): Boolean = balance >= rentExempt + + val balance = walletManager.wallet.fundsAvailable(AmountType.Coin) + val outgoingTxs = walletManager.wallet.getPendingTransactions(PendingTransactionType.Outgoing) + val rentExempt = result.data + val show = if (outgoingTxs.isEmpty()) { + isNeedToShowWarning(balance, rentExempt) + } else { + val outgoingAmount = outgoingTxs.sumOf { it.amount ?: BigDecimal.ZERO } + val rest = balance.minus(outgoingAmount) + isNeedToShowWarning(rest, rentExempt) + } + if (!show) return@launch + val currency = walletManager.wallet.blockchain.currency - val minRent = ("${rentProvider.rentAmount().stripZeroPlainString()} $currency") - val rentExempt = ("${result.data.stripZeroPlainString()} $currency") store.dispatchOnMain(WalletAction.SetWalletRent( blockchain = walletManager.wallet.blockchain, - minRent = minRent, - rentExempt = rentExempt + minRent = ("${rentProvider.rentAmount().stripZeroPlainString()} $currency"), + rentExempt = ("${rentExempt.stripZeroPlainString()} $currency") )) } is Result.Failure -> {} diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/PendingTransactionsAdapter.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/PendingTransactionsAdapter.kt index 09c6094d38..31ab7c4368 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/PendingTransactionsAdapter.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/PendingTransactionsAdapter.kt @@ -62,7 +62,7 @@ class PendingTransactionsAdapter } view.tv_pending_transaction.text = view.context.getString(transactionDescriptionRes) - transaction.amount?.let { view.tv_pending_transaction_amount.text = "$it " } + transaction.amountUi?.let { view.tv_pending_transaction_amount.text = "$it " } view.tv_pending_transaction_currency.text = "${transaction.currency}" if (transaction.address != null) { From 011156ac16e9b8107d8c67c2de12e82978040879 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 17 Feb 2022 12:32:07 +0300 Subject: [PATCH 02/16] Updated on 2026-08-14 --- .../layout/layout_onboarding_container_bottom.xml | 14 +++++++------- app/src/main/res/values-h680dp/dimens.xml | 13 +++++++++++++ app/src/main/res/values/dimens.xml | 12 ++++++++++++ 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/app/src/main/res/layout/layout_onboarding_container_bottom.xml b/app/src/main/res/layout/layout_onboarding_container_bottom.xml index d5e9dbcc4a..5153961feb 100644 --- a/app/src/main/res/layout/layout_onboarding_container_bottom.xml +++ b/app/src/main/res/layout/layout_onboarding_container_bottom.xml @@ -10,14 +10,14 @@ android:id="@+id/linearLayoutCompat" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginBottom="8dp" + android:layout_marginBottom="@dimen/linearLayoutCompat_marginBottom" android:gravity="center" android:orientation="vertical" app:layout_constraintBottom_toTopOf="@+id/fl_scan_card_container" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" - app:layout_constraintVertical_bias="0.1"> + app:layout_constraintVertical_bias="@dimen/linearLayoutCompat_constraintVertical_bias"> 106dp 67dp + + + 16dp + 0.4> + + 10dp + 64dp + 64dp + + 90dp + + 14dp + diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 496ccebf23..273311f2c3 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -41,4 +41,16 @@ 70dp 37dp + + + 8dp + 0.1> + + 14dp + 14dp + 14dp + + 72dp + + 12dp From 13ff70b2709f64507ea7c2d41991af1e4b8ea7fe Mon Sep 17 00:00:00 2001 From: Tangem Date: Sun, 20 Feb 2022 15:22:54 +0300 Subject: [PATCH 03/16] Updated on 2026-08-14 --- .../tap/domain/twins/TwinCardsWidget.kt | 15 +++---- .../products/twins/ui/TwinsCardsFragment.kt | 11 ++++- .../res/layout/fragment_onboarding_main.xml | 4 +- .../layout_onboarding_container_bottom.xml | 14 +++---- .../layout_onboarding_container_top.xml | 2 + .../res/layout/layout_onboarding_home_top.xml | 14 +++++-- .../res/layout/lp_onboarding_topup_wallet.xml | 2 +- .../lp_onboarding_topup_wallet_twins.xml | 2 +- app/src/main/res/values-h680dp/dimens.xml | 39 ++++++++++-------- app/src/main/res/values/dimens.xml | 41 +++++++++++-------- 10 files changed, 90 insertions(+), 54 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/domain/twins/TwinCardsWidget.kt b/app/src/main/java/com/tangem/tap/domain/twins/TwinCardsWidget.kt index becb529e80..3a163149e5 100644 --- a/app/src/main/java/com/tangem/tap/domain/twins/TwinCardsWidget.kt +++ b/app/src/main/java/com/tangem/tap/domain/twins/TwinCardsWidget.kt @@ -16,6 +16,7 @@ import com.tangem.tangem_sdk_new.ui.widget.leapfrogWidget.LeapfrogWidget */ class TwinsCardWidget( val leapfrogWidget: LeapfrogWidget, + private val deviceScaleFactor: Float = 1f, val getTopOfAnchorViewForActivateState: () -> Float ) { @@ -87,20 +88,20 @@ class TwinsCardWidget( return when (cardNumber) { TwinCardNumber.First -> { TwinsCardProperties( - xTranslation = -120f, - yTranslation = -220f, + xTranslation = -120f * deviceScaleFactor, + yTranslation = -220f * deviceScaleFactor, rotation = -3f, elevation = 1f, - scale = 1f, + scale = deviceScaleFactor, ) } TwinCardNumber.Second -> { TwinsCardProperties( - xTranslation = 170f, - yTranslation = 170f, + xTranslation = 170f * deviceScaleFactor, + yTranslation = 170f * deviceScaleFactor, rotation = -3f, elevation = 0f, - scale = 1f, + scale = deviceScaleFactor, ) } } @@ -123,7 +124,7 @@ class TwinsCardWidget( xTranslation = twinProperties.xTranslation, yTranslation = twinProperties.yTranslation - topOfAnchorView, rotation = 0f, - scale = twinProperties.scale - 0.5f, + scale = (twinProperties.scale - 0.5f) * deviceScaleFactor, ) } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/ui/TwinsCardsFragment.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/ui/TwinsCardsFragment.kt index 12e87f2a70..c8482b0624 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/ui/TwinsCardsFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/ui/TwinsCardsFragment.kt @@ -1,6 +1,7 @@ package com.tangem.tap.features.onboarding.products.twins.ui import android.os.Bundle +import android.util.TypedValue import android.view.View import android.view.animation.OvershootInterpolator import androidx.annotation.LayoutRes @@ -38,6 +39,7 @@ import kotlinx.android.synthetic.main.view_bg_twins_welcome.* import kotlinx.android.synthetic.main.view_onboarding_progress.* import kotlinx.android.synthetic.main.view_onboarding_tv_balance.* + class TwinsCardsFragment : BaseOnboardingFragment() { private var previousStep = TwinCardsStep.None @@ -75,7 +77,14 @@ class TwinsCardsFragment : BaseOnboardingFragment() { addBackPressHandler(this) reconfigureLayoutForTwins() - twinsWidget = TwinsCardWidget(LeapfrogWidget(cards_container)) { 285f } + + val typedValue = TypedValue() + resources.getValue(R.dimen.device_scale_factor_for_twins_welcome, typedValue, true) + val deviceScaleFactorForWelcomeState = typedValue.float + + twinsWidget = TwinsCardWidget(LeapfrogWidget(cards_container), deviceScaleFactorForWelcomeState) { + 285f * deviceScaleFactorForWelcomeState + } btnRefreshBalanceWidget = RefreshBalanceWidget(onboarding_main_container) toolbar.title = getText(R.string.twins_recreate_toolbar) diff --git a/app/src/main/res/layout/fragment_onboarding_main.xml b/app/src/main/res/layout/fragment_onboarding_main.xml index 6d567ce91b..fa3d618abc 100644 --- a/app/src/main/res/layout/fragment_onboarding_main.xml +++ b/app/src/main/res/layout/fragment_onboarding_main.xml @@ -37,7 +37,7 @@ android:id="@+id/onboarding_top_container" android:layout_width="match_parent" android:layout_height="0dp" - android:layout_weight="1.2" + android:layout_weight="@dimen/home_top_weight" android:clipChildren="false" /> + android:layout_weight="@dimen/home_bottom_weight" /> diff --git a/app/src/main/res/layout/layout_onboarding_container_bottom.xml b/app/src/main/res/layout/layout_onboarding_container_bottom.xml index 5153961feb..08c351d6fb 100644 --- a/app/src/main/res/layout/layout_onboarding_container_bottom.xml +++ b/app/src/main/res/layout/layout_onboarding_container_bottom.xml @@ -10,14 +10,14 @@ android:id="@+id/linearLayoutCompat" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginBottom="@dimen/linearLayoutCompat_marginBottom" + android:layout_marginBottom="@dimen/home_bottom_llCompat_margin_bottom" android:gravity="center" android:orientation="vertical" app:layout_constraintBottom_toTopOf="@+id/fl_scan_card_container" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" - app:layout_constraintVertical_bias="@dimen/linearLayoutCompat_constraintVertical_bias"> + app:layout_constraintVertical_bias="@dimen/home_bottom_llCompat_constraint_vertical_bias"> - + @@ -29,8 +35,10 @@ android:elevation="1dp" android:rotation="-3" android:scaleType="fitXY" + android:scaleX="@dimen/home_top_front_card_scaleX" + android:scaleY="@dimen/home_top_front_card_scaleY" android:src="@drawable/card_placeholder_black" - android:translationY="@dimen/home_front_card_translationY" + android:translationY="@dimen/home_top_front_card_translationY" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> diff --git a/app/src/main/res/layout/lp_onboarding_topup_wallet.xml b/app/src/main/res/layout/lp_onboarding_topup_wallet.xml index 6b924ea771..dc6efbcc96 100644 --- a/app/src/main/res/layout/lp_onboarding_topup_wallet.xml +++ b/app/src/main/res/layout/lp_onboarding_topup_wallet.xml @@ -25,7 +25,7 @@ - -10dp - 0dp + 1.0 + + + 1.1 + -10dp + 1 + 1 + 0dp + 1 + 1 + + + 1 + 16dp + 0.4> + 14dp + 64dp + 64dp + 90dp + 14dp + + 16dp 106dp + 230dp 67dp - - - - 16dp - 0.4> - - 10dp - 64dp - 64dp - - 90dp - - 14dp - diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 273311f2c3..21d9827305 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -35,22 +35,31 @@ 32sp 16dp - -30dp - -20dp - 8dp - 70dp + 0.85 + + + 0.9 + -60dp + 0.9 + 0.9 + -40dp + 0.9 + 0.9 + + + 1 + 8dp + 0.1> + 10dp + 34dp + 34dp + 72dp + 12dp + + + 0dp + 50dp + 180dp 37dp - - - 8dp - 0.1> - - 14dp - 14dp - 14dp - - 72dp - - 12dp From 71df77dd1015f9c07552bcb78f11e517607f017b Mon Sep 17 00:00:00 2001 From: Tangem Date: Sun, 20 Feb 2022 15:49:05 +0300 Subject: [PATCH 04/16] Updated on 2026-08-14 --- app/src/main/res/values-h680dp/dimens.xml | 12 ++++++------ app/src/main/res/values/dimens.xml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/src/main/res/values-h680dp/dimens.xml b/app/src/main/res/values-h680dp/dimens.xml index bb65b08319..35206f9ed6 100644 --- a/app/src/main/res/values-h680dp/dimens.xml +++ b/app/src/main/res/values-h680dp/dimens.xml @@ -3,18 +3,18 @@ 1.0 - 1.1 + 1.1 -10dp - 1 + 1 1 0dp - 1 - 1 + 1 + 1 - 1 + 1 16dp - 0.4> + 0.4> 14dp 64dp 64dp diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 21d9827305..a4149bd548 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -49,7 +49,7 @@ 1 8dp - 0.1> + 0.1 10dp 34dp 34dp From 8b25bda26635337abef0f6d8ae22120a1e732211 Mon Sep 17 00:00:00 2001 From: Tangem Date: Sun, 20 Feb 2022 16:39:19 +0300 Subject: [PATCH 05/16] Updated on 2026-08-14 --- .../products/wallet/ui/BackupCardsWidget.kt | 55 +++++++------- .../wallet/ui/OnboardingWalletFragment.kt | 7 +- .../res/layout/fragment_onboarding_wallet.xml | 74 +++++++++---------- .../layout_onboarding_buttons_common.xml | 20 ++--- app/src/main/res/values-h680dp/dimens.xml | 2 + app/src/main/res/values/dimens.xml | 1 + 6 files changed, 80 insertions(+), 79 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/BackupCardsWidget.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/BackupCardsWidget.kt index 1b4ecba2a7..07d27cf6ca 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/BackupCardsWidget.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/BackupCardsWidget.kt @@ -12,6 +12,7 @@ import com.tangem.tangem_sdk_new.ui.widget.leapfrogWidget.LeapfrogWidget class BackupCardsWidget( val leapfrogWidget: LeapfrogWidget, + private val deviceScaleFactor: Float = 1f, val getTopOfAnchorViewForActivateState: () -> Float, ) { @@ -98,26 +99,26 @@ class BackupCardsWidget( private fun createWelcomeProperties(cardType: BackupCardType): CardProperties { return when (cardType) { BackupCardType.ORIGIN -> CardProperties( - xTranslation = 440f, - yTranslation = 0f, - rotation = 75f, - elevation = 2f, - scale = .9f, - ) + xTranslation = 440f * deviceScaleFactor, + yTranslation = 70f, + rotation = 75f, + elevation = 2f, + scale = .85f * deviceScaleFactor, + ) BackupCardType.FIRST_BACKUP -> CardProperties( - xTranslation = 10f, - yTranslation = -100f, - rotation = 100f, - elevation = 1f, - scale = .9f, -) + xTranslation = 10f * deviceScaleFactor, + yTranslation = -30f, + rotation = 100f, + elevation = 1f, + scale = .85f * deviceScaleFactor, + ) BackupCardType.SECOND_BACKUP -> CardProperties( - xTranslation = -440f, - yTranslation = -100f, - rotation = 70f, - elevation = 0f, - scale = .9f, - ) + xTranslation = -440f * deviceScaleFactor, + yTranslation = -30f, + rotation = 70f, + elevation = 0f, + scale = .85f * deviceScaleFactor, + ) } } @@ -125,24 +126,24 @@ class BackupCardsWidget( return when (cardType) { BackupCardType.ORIGIN -> CardProperties( xTranslation = 0f, - yTranslation = 0f, + yTranslation = 30f, rotation = 5f, elevation = 2f, - scale = 1f, + scale = 1f * deviceScaleFactor, ) BackupCardType.FIRST_BACKUP -> CardProperties( xTranslation = 0f, - yTranslation = -80f, + yTranslation = -50f, rotation = -5f, elevation = 1f, - scale = 0.9f, + scale = 0.9f * deviceScaleFactor, ) BackupCardType.SECOND_BACKUP -> CardProperties( xTranslation = 10f, - yTranslation = -170f, + yTranslation = -120f, rotation = -20f, elevation = 0f, - scale = 0.8f, + scale = 0.8f * deviceScaleFactor, ) } } @@ -154,21 +155,21 @@ class BackupCardsWidget( yTranslation = 0f, rotation = 0f, elevation = 2f, - scale = 1f, + scale = 1f * deviceScaleFactor, ) BackupCardType.FIRST_BACKUP -> CardProperties( xTranslation = 0f, yTranslation = 0f, rotation = 0f, elevation = 1f, - scale = 0.9f, + scale = 0.9f * deviceScaleFactor, ) BackupCardType.SECOND_BACKUP -> CardProperties( xTranslation = 0f, yTranslation = 0f, rotation = 0f, elevation = 0f, - scale = 0.8f, + scale = 0.8f * deviceScaleFactor, ) } } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt index 398ee44b55..0d1b1b0465 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt @@ -1,6 +1,7 @@ package com.tangem.tap.features.onboarding.products.wallet.ui import android.os.Bundle +import android.util.TypedValue import android.view.* import android.widget.ImageView import androidx.appcompat.app.AppCompatActivity @@ -47,8 +48,12 @@ class OnboardingWalletFragment : Fragment(R.layout.fragment_onboarding_wallet), override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + val typedValue = TypedValue() + resources.getValue(R.dimen.device_scale_factor_for_twins_welcome, typedValue, true) + val deviceScaleFactorForWelcomeState = typedValue.float + val leapfrog = LeapfrogWidget(fl_cards_container) - cardsWidget = BackupCardsWidget(leapfrog) { 200f } + cardsWidget = BackupCardsWidget(leapfrog, deviceScaleFactorForWelcomeState) { 200f * deviceScaleFactorForWelcomeState } startPostponedEnterTransition() view_pager_backup_info.adapter = BackupInfoAdapter() diff --git a/app/src/main/res/layout/fragment_onboarding_wallet.xml b/app/src/main/res/layout/fragment_onboarding_wallet.xml index 5df3b30845..d6dcf19910 100644 --- a/app/src/main/res/layout/fragment_onboarding_wallet.xml +++ b/app/src/main/res/layout/fragment_onboarding_wallet.xml @@ -23,9 +23,9 @@ android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" + app:menu="@menu/shop" app:navigationIcon="@drawable/ic_baseline_arrow_back_24" - app:title="@string/onboarding_getting_started" - app:menu="@menu/shop"/> + app:title="@string/onboarding_getting_started" /> @@ -33,6 +33,7 @@ android:id="@+id/onboarding_main_container" android:layout_width="match_parent" android:layout_height="match_parent" + android:clipChildren="false" app:layout_behavior="@string/appbar_scrolling_view_behavior"> @@ -51,28 +51,25 @@ android:id="@+id/imv_card_background" android:layout_width="236dp" android:layout_height="236dp" - android:layout_gravity="center" android:adjustViewBounds="true" android:background="@drawable/shape_circle" android:backgroundTint="@color/lightGray0" android:elevation="0dp" android:scaleType="fitCenter" - app:layout_constraintStart_toStartOf="@id/fl_cards_container" - app:layout_constraintEnd_toEndOf="@id/fl_cards_container" - app:layout_constraintTop_toTopOf="@id/fl_cards_container" app:layout_constraintBottom_toBottomOf="@id/fl_cards_container" - android:layout_marginBottom="16dp" - /> + app:layout_constraintEnd_toEndOf="@id/fl_cards_container" + app:layout_constraintStart_toStartOf="@id/fl_cards_container" + app:layout_constraintTop_toTopOf="@id/fl_cards_container" /> @@ -81,36 +78,33 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center" - android:src="@drawable/card_placeholder_new" - android:visibility="gone" android:layout_marginStart="32dp" android:layout_marginEnd="32dp" android:scaleType="fitCenter" - - /> + android:src="@drawable/card_placeholder_new" + android:visibility="gone" /> + android:src="@drawable/card_placeholder_new" + android:visibility="gone" /> + android:src="@drawable/card_placeholder_new" + android:transitionName="imv_front_card" /> @@ -119,12 +113,12 @@ android:layout_width="142dp" android:layout_height="142dp" android:src="@drawable/ic_activation_success" + android:visibility="gone" app:layout_constraintBottom_toTopOf="@id/guideline2" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.495" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@id/pb_state" - android:visibility="gone"/> + app:layout_constraintTop_toBottomOf="@id/pb_state" /> + app:layout_constraintTop_toTopOf="@+id/guideline2" + tools:text="Header" /> + app:layout_constraintTop_toBottomOf="@+id/tv_header" + tools:text="Body" /> + app:layout_constraintTop_toTopOf="@+id/guideline2" /> + app:tabPaddingStart="8dp" /> + app:layout_constraintBottom_toBottomOf="parent" /> diff --git a/app/src/main/res/layout/layout_onboarding_buttons_common.xml b/app/src/main/res/layout/layout_onboarding_buttons_common.xml index ff0472d121..e99f7dfe4a 100644 --- a/app/src/main/res/layout/layout_onboarding_buttons_common.xml +++ b/app/src/main/res/layout/layout_onboarding_buttons_common.xml @@ -1,33 +1,33 @@ + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="wrap_content"> + app:layout_constraintStart_toStartOf="parent" + tools:text="Main Action" /> + app:layout_constraintStart_toStartOf="parent" + tools:text="Alternative action" /> \ No newline at end of file diff --git a/app/src/main/res/values-h680dp/dimens.xml b/app/src/main/res/values-h680dp/dimens.xml index 35206f9ed6..5b762af83e 100644 --- a/app/src/main/res/values-h680dp/dimens.xml +++ b/app/src/main/res/values-h680dp/dimens.xml @@ -26,4 +26,6 @@ 106dp 230dp 67dp + 0.6 + diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index a4149bd548..39e1f215d0 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -61,5 +61,6 @@ 50dp 180dp 37dp + 0.5> From f161da5fbd0408d60b1557da0c734fdd19320a14 Mon Sep 17 00:00:00 2001 From: Tangem Date: Sun, 20 Feb 2022 17:29:12 +0300 Subject: [PATCH 06/16] Updated on 2026-08-14 --- .../products/wallet/ui/BackupCardsWidget.kt | 4 ++-- .../wallet/ui/OnboardingWalletFragment.kt | 15 +++++++++------ .../res/layout/fragment_onboarding_wallet.xml | 3 ++- app/src/main/res/values-h680dp/dimens.xml | 2 +- app/src/main/res/values/dimens.xml | 2 +- 5 files changed, 15 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/BackupCardsWidget.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/BackupCardsWidget.kt index 07d27cf6ca..99519fb349 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/BackupCardsWidget.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/BackupCardsWidget.kt @@ -43,7 +43,7 @@ class BackupCardsWidget( createAnimator(BackupCardType.FIRST_BACKUP, createLeapfrogProperties(BackupCardType.FIRST_BACKUP)), createAnimator(BackupCardType.SECOND_BACKUP, createLeapfrogProperties(BackupCardType.SECOND_BACKUP)) ) - leapfrogWidget.fold { animator.start() } + leapfrogWidget.fold(animate) { animator.start() } } fun toFan(animate: Boolean = true, onEnd: () -> Unit = {}) { @@ -71,7 +71,7 @@ class BackupCardsWidget( ) leapfrogWidget.fold { animator.doOnEnd { - leapfrogWidget.initViews() +// leapfrogWidget.initViews() leapfrogWidget.unfold() } animator.start() diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt index 0d1b1b0465..b9b31b5495 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt @@ -14,6 +14,7 @@ import com.squareup.picasso.Picasso import com.tangem.common.CardIdFormatter import com.tangem.common.core.CardIdDisplayFormat import com.tangem.tangem_sdk_new.ui.widget.leapfrogWidget.LeapfrogWidget +import com.tangem.tangem_sdk_new.ui.widget.leapfrogWidget.PropertyCalculator import com.tangem.tap.common.extensions.hide import com.tangem.tap.common.extensions.show import com.tangem.tap.features.FragmentOnBackPressedHandler @@ -50,10 +51,13 @@ class OnboardingWalletFragment : Fragment(R.layout.fragment_onboarding_wallet), val typedValue = TypedValue() resources.getValue(R.dimen.device_scale_factor_for_twins_welcome, typedValue, true) - val deviceScaleFactorForWelcomeState = typedValue.float + val deviceScaleFactor = typedValue.float - val leapfrog = LeapfrogWidget(fl_cards_container) - cardsWidget = BackupCardsWidget(leapfrog, deviceScaleFactorForWelcomeState) { 200f * deviceScaleFactorForWelcomeState } + val leapfrogCalculator = PropertyCalculator( + yTranslationFactor = 25f * deviceScaleFactor, + ) + val leapfrog = LeapfrogWidget(fl_cards_container, leapfrogCalculator) + cardsWidget = BackupCardsWidget(leapfrog, deviceScaleFactor) { 200f * deviceScaleFactor } startPostponedEnterTransition() view_pager_backup_info.adapter = BackupInfoAdapter() @@ -126,8 +130,7 @@ class OnboardingWalletFragment : Fragment(R.layout.fragment_onboarding_wallet), tv_header.setText(R.string.onboarding_create_wallet_header) tv_body.setText(R.string.onboarding_create_wallet_body) - cardsWidget.toFolded() - startPostponedEnterTransition() + cardsWidget.toFolded(false) { startPostponedEnterTransition() } } @@ -384,7 +387,7 @@ class OnboardingWalletFragment : Fragment(R.layout.fragment_onboarding_wallet), val shopMenuShouldBeVisible = (backupStep == BackupStep.ScanOriginCard || backupStep == BackupStep.AddBackupCards) && - backupState.buyAdditionalCardsUrl != null + backupState.buyAdditionalCardsUrl != null menu.getItem(0).isVisible = shopMenuShouldBeVisible } diff --git a/app/src/main/res/layout/fragment_onboarding_wallet.xml b/app/src/main/res/layout/fragment_onboarding_wallet.xml index d6dcf19910..db8df977bb 100644 --- a/app/src/main/res/layout/fragment_onboarding_wallet.xml +++ b/app/src/main/res/layout/fragment_onboarding_wallet.xml @@ -140,13 +140,14 @@ android:layout_height="wrap_content" android:layout_marginTop="12dp" android:fontFamily="sans-serif-medium" + android:textAlignment="center" android:textColor="#060606" android:textSize="24sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.504" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@+id/guideline2" - tools:text="Header" /> + tools:text="Добавлена одна резервная карта" /> 106dp 230dp 67dp - 0.6 + 0.56 diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 39e1f215d0..9d09f6bcbb 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -61,6 +61,6 @@ 50dp 180dp 37dp - 0.5> + 0.48> From cb9a82d544b177f4dee513b7080315688f4a6b85 Mon Sep 17 00:00:00 2001 From: Tangem Date: Sun, 20 Feb 2022 18:11:16 +0300 Subject: [PATCH 07/16] Updated on 2026-08-14 --- .../res/layout/layout_backup_access_code.xml | 56 +++++++++---------- .../layout/layout_backup_access_code_info.xml | 14 ++--- .../layout_backup_access_code_submit.xml | 19 +++---- app/src/main/res/values-h680dp/dimens.xml | 7 +++ app/src/main/res/values/dimens.xml | 9 +++ 5 files changed, 60 insertions(+), 45 deletions(-) diff --git a/app/src/main/res/layout/layout_backup_access_code.xml b/app/src/main/res/layout/layout_backup_access_code.xml index de45562ba3..d8c721b7f6 100644 --- a/app/src/main/res/layout/layout_backup_access_code.xml +++ b/app/src/main/res/layout/layout_backup_access_code.xml @@ -8,36 +8,36 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - + - + - + diff --git a/app/src/main/res/layout/layout_backup_access_code_info.xml b/app/src/main/res/layout/layout_backup_access_code_info.xml index ac5a98171f..3ef7ba57fb 100644 --- a/app/src/main/res/layout/layout_backup_access_code_info.xml +++ b/app/src/main/res/layout/layout_backup_access_code_info.xml @@ -8,18 +8,18 @@ android:id="@+id/iv_access_code_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginTop="25dp" + android:layout_marginTop="@dimen/access_code_info_protect_margin_top" android:src="@drawable/ic_access_code" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" /> \ No newline at end of file diff --git a/app/src/main/res/values-h680dp/dimens.xml b/app/src/main/res/values-h680dp/dimens.xml index 9e11e3d73e..7a03c1b4cf 100644 --- a/app/src/main/res/values-h680dp/dimens.xml +++ b/app/src/main/res/values-h680dp/dimens.xml @@ -28,4 +28,11 @@ 67dp 0.56 + + 80dp + 24dp + 20dp + 32dp + 80dp + diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 9d09f6bcbb..ce2c35b5fb 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -63,4 +63,13 @@ 37dp 0.48> + + 40dp + 12dp + 8dp + 16dp + 38dp + 78dp + 78dp + From 514c1740410cc7387f8e72e1ee2e9e2b55280186 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 23 Feb 2022 10:30:42 +0300 Subject: [PATCH 08/16] Updated on 2026-08-14 --- .../tangem/tap/domain/topup/TopUpManager.kt | 3 +- .../walletconnect/WalletConnectSdkHelper.kt | 12 ++----- .../middlewares/MultiWalletMiddleware.kt | 36 +++++++++---------- 3 files changed, 23 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/domain/topup/TopUpManager.kt b/app/src/main/java/com/tangem/tap/domain/topup/TopUpManager.kt index 9dd6e91960..c5e74334a4 100644 --- a/app/src/main/java/com/tangem/tap/domain/topup/TopUpManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/topup/TopUpManager.kt @@ -6,6 +6,7 @@ import com.tangem.blockchain.common.Amount import com.tangem.blockchain.common.AmountType import com.tangem.blockchain.common.Token import com.tangem.blockchain.extensions.Result +import com.tangem.tap.common.extensions.safeUpdate import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.domain.TangemSigner import com.tangem.tap.store @@ -14,7 +15,7 @@ import java.math.BigDecimal class TopUpManager { suspend fun topUpTestErc20Tokens(walletManager: EthereumWalletManager, token: Token) { - walletManager.update() + walletManager.safeUpdate() val amountToSend = Amount(walletManager.wallet.blockchain) val destinationAddress = token.contractAddress diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt index e56b4d9ce6..1d0dc4a9e0 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt @@ -15,6 +15,7 @@ import com.tangem.common.extensions.toHexString import com.tangem.crypto.CryptoUtils import com.tangem.operations.sign.SignHashCommand import com.tangem.tap.common.analytics.Analytics +import com.tangem.tap.common.extensions.safeUpdate import com.tangem.tap.common.extensions.toFormattedString import com.tangem.tap.features.details.redux.walletconnect.* import com.tangem.tap.features.details.ui.walletconnect.dialogs.PersonalSignDialogData @@ -35,18 +36,11 @@ class WalletConnectSdkHelper { id: Long, type: WcTransactionType, ): WcTransactionData? { - val walletManager = getWalletManager(session) ?: return null - try { - walletManager.update() - } catch (exception: Exception) { - Timber.e(exception) - return null - } + walletManager.safeUpdate() val wallet = walletManager.wallet - val balance = - wallet.amounts[AmountType.Coin]?.value ?: return null + val balance = wallet.amounts[AmountType.Coin]?.value ?: return null val gas = transaction.gas?.hexToBigDecimal() ?: transaction.gasLimit?.hexToBigDecimal() diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt index df4c9120f7..82f43f9812 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt @@ -13,6 +13,8 @@ import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.currenciesRepository import com.tangem.tap.domain.extensions.makeWalletManagerForApp import com.tangem.tap.domain.extensions.makeWalletManagersForApp +import com.tangem.tap.features.demo.DemoHelper +import com.tangem.tap.features.demo.isDemoCard import com.tangem.tap.features.wallet.redux.Currency import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.features.wallet.redux.WalletState @@ -22,6 +24,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import java.math.BigDecimal class MultiWalletMiddleware { fun handle( @@ -99,28 +102,25 @@ class MultiWalletMiddleware { scope.launch { walletManagers.map { walletManager -> async(Dispatchers.IO) { - try { - walletManager.update() - val wallet = walletManager.wallet - val coinAmount = wallet.amounts[AmountType.Coin]?.value - if (coinAmount != null && !coinAmount.isZero()) { - scope.launch(Dispatchers.Main) { - if (walletState?.getWalletData(wallet.blockchain) == null) { - store.dispatch( - WalletAction.MultiWallet.AddWalletManagers( - listOfNotNull(walletManager) - ) + walletManager.safeUpdate() + val wallet = walletManager.wallet + val coinAmount = wallet.amounts[AmountType.Coin]?.value + if (coinAmount != null && !coinAmount.isZero()) { + scope.launch(Dispatchers.Main) { + if (walletState?.getWalletData(wallet.blockchain) == null) { + store.dispatch( + WalletAction.MultiWallet.AddWalletManagers( + listOfNotNull(walletManager) ) - store.dispatch( - WalletAction.MultiWallet.AddBlockchain( - wallet.blockchain - ) + ) + store.dispatch( + WalletAction.MultiWallet.AddBlockchain( + wallet.blockchain ) - store.dispatch(WalletAction.LoadWallet.Success(wallet)) - } + ) + store.dispatch(WalletAction.LoadWallet.Success(wallet)) } } - } catch (exception: Exception) { } } } From f5e59453e1fd2d68f44beb85dfb192cc42090dc2 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 23 Feb 2022 10:32:28 +0300 Subject: [PATCH 09/16] Updated on 2026-08-14 --- .../tasks/product/CreateProductWalletTask.kt | 54 +++++++++++-------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletTask.kt index e75da7ca72..29ae9d45bc 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletTask.kt @@ -5,8 +5,10 @@ import com.tangem.common.card.EllipticCurve import com.tangem.common.core.CardSession import com.tangem.common.core.CardSessionRunnable import com.tangem.common.core.TangemSdkError +import com.tangem.common.extensions.ByteArrayKey import com.tangem.common.extensions.guard import com.tangem.common.extensions.toMapKey +import com.tangem.common.hdWallet.DerivationPath import com.tangem.operations.CommandResponse import com.tangem.operations.backup.PrimaryCard import com.tangem.operations.backup.StartPrimaryCardLinkingTask @@ -16,10 +18,12 @@ import com.tangem.operations.wallet.CreateWalletResponse import com.tangem.operations.wallet.CreateWalletTask import com.tangem.tap.domain.ProductType import com.tangem.tap.domain.TapWorkarounds.getTangemNoteBlockchain +import com.tangem.tap.domain.TapWorkarounds.isTestCard import com.tangem.tap.domain.tasks.product.CreateWalletsTask import com.tangem.tap.domain.tasks.product.KeyWalletPublicKey import com.tangem.tap.domain.tasks.product.ProductCommandProcessor import com.tangem.tap.domain.tasks.product.getCurvesForNonCreatedWallets +import com.tangem.tap.features.demo.DemoHelper data class CreateProductWalletTaskResponse( @@ -96,25 +100,27 @@ private class CreateWalletTangemNote : ProductCommandProcessor { + private lateinit var card: Card private var primaryCard: PrimaryCard? = null - private var createWalletResponse: CreateWalletResponse? = null override fun proceed( card: Card, session: CardSession, callback: (result: CompletionResult) -> Unit, ) { + this.card = card val curves = card.getCurvesForNonCreatedWallets() + CreateWalletsTask(curves).run(session) { result -> when (result) { is CompletionResult.Success -> { - createWalletResponse = result.data.createWalletResponses[0] + val createWalletResponses = result.data.createWalletResponses when { card.settings.isBackupAllowed -> { - linkPrimaryCard(session, callback) + linkPrimaryCard(createWalletResponses, session, callback) } card.settings.isHDWalletAllowed -> { - deriveKeys(session, callback) + deriveKeys(createWalletResponses, session, callback) } else -> { callback( @@ -124,7 +130,6 @@ private class CreateWalletTangemWallet : ProductCommandProcessor callback(CompletionResult.Failure(result.error)) } @@ -132,6 +137,7 @@ private class CreateWalletTangemWallet : ProductCommandProcessor, session: CardSession, callback: (result: CompletionResult) -> Unit, ) { @@ -139,7 +145,7 @@ private class CreateWalletTangemWallet : ProductCommandProcessor { primaryCard = result.data - deriveKeys(session, callback) + deriveKeys(createWalletResponse, session, callback) } is CompletionResult.Failure -> { callback(CompletionResult.Failure(result.error)) @@ -149,28 +155,26 @@ private class CreateWalletTangemWallet : ProductCommandProcessor, session: CardSession, callback: (result: CompletionResult) -> Unit, ) { - val derivationPaths = listOf(Blockchain.Bitcoin, Blockchain.Ethereum) - .mapNotNull { it.derivationPath() } - val response = createWalletResponse.guard { + val map = mutableMapOf>() + createWalletResponse.forEach { response -> + val blockchainsForCurve = getBlockchains(response.cardId).filter { + it.getSupportedCurves().contains(response.wallet.curve) + } + val derivationPaths = blockchainsForCurve.mapNotNull { it.derivationPath() } + if (derivationPaths.isNotEmpty()) { + map[response.wallet.publicKey.toMapKey()] = derivationPaths + } + } + if (map.isEmpty()) { callback(CompletionResult.Failure(TangemSdkError.UnknownError())) return } - if (derivationPaths.isNullOrEmpty()) { - callback( - CompletionResult.Success( - CreateProductWalletTaskResponse( - card = session.environment.card!!, primaryCard = primaryCard - ) - ) - ) - return - } - - DeriveMultipleWalletPublicKeysTask(mapOf(response.wallet.publicKey.toMapKey() to derivationPaths)) + DeriveMultipleWalletPublicKeysTask(map) .run(session) { result -> when (result) { is CompletionResult.Success -> { @@ -188,4 +192,12 @@ private class CreateWalletTangemWallet : ProductCommandProcessor { + return when { + DemoHelper.isDemoCardId(cardId) -> DemoHelper.config.demoBlockchains + card.isTestCard -> listOf(Blockchain.BitcoinTestnet, Blockchain.EthereumTestnet) + else -> listOf(Blockchain.Bitcoin, Blockchain.Ethereum) + } + } } \ No newline at end of file From b22dd433eabeaa3cab4d6abf3b9b6d5339c7365e Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 23 Feb 2022 10:33:27 +0300 Subject: [PATCH 10/16] Updated on 2026-08-14 --- .../com/tangem/tap/common/DialogManager.kt | 3 ++ .../tangem/tap/common/redux/StateDialog.kt | 2 ++ .../wallet/ui/dialogs/SimpleOkDialog.kt | 35 +++++++++++++++++++ 3 files changed, 40 insertions(+) create mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/SimpleOkDialog.kt diff --git a/app/src/main/java/com/tangem/tap/common/DialogManager.kt b/app/src/main/java/com/tangem/tap/common/DialogManager.kt index 7f3bf094a7..56ce4dd062 100644 --- a/app/src/main/java/com/tangem/tap/common/DialogManager.kt +++ b/app/src/main/java/com/tangem/tap/common/DialogManager.kt @@ -15,6 +15,7 @@ import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.BackupInPro import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.ConfirmDiscardingBackupDialog import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.UnfinishedBackupFoundDialog import com.tangem.tap.features.wallet.ui.dialogs.ScanFailsDialog +import com.tangem.tap.features.wallet.ui.dialogs.SimpleOkDialog import com.tangem.tap.store import com.tangem.wallet.R import org.rekotlin.StoreSubscriber @@ -48,6 +49,8 @@ class DialogManager : StoreSubscriber { if (dialog != null) return dialog = when (state.dialog) { + is AppDialog.SimpleOkDialog -> SimpleOkDialog.create(state.dialog, context) + is AppDialog.SimpleOkDialogRes -> SimpleOkDialog.create(state.dialog, context) is AppDialog.ScanFailsDialog -> ScanFailsDialog.create(context) is AppDialog.AddressInfoDialog -> AddressInfoBottomSheetDialog(state.dialog, context) is TwinCardsAction.Wallet.ShowInterruptDialog -> CreateWalletInterruptDialog.create(state.dialog, context) diff --git a/app/src/main/java/com/tangem/tap/common/redux/StateDialog.kt b/app/src/main/java/com/tangem/tap/common/redux/StateDialog.kt index bcde7dae3b..ecec5fb9f4 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/StateDialog.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/StateDialog.kt @@ -9,6 +9,8 @@ import com.tangem.tap.features.wallet.redux.Currency interface StateDialog sealed class AppDialog : StateDialog { + data class SimpleOkDialog(val header: String, val message: String) : AppDialog() + data class SimpleOkDialogRes(val headerId: Int, val messageId: Int) : AppDialog() object ScanFailsDialog : AppDialog() data class AddressInfoDialog( val currency: Currency, diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/SimpleOkDialog.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/SimpleOkDialog.kt new file mode 100644 index 0000000000..aa15f94e9f --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/SimpleOkDialog.kt @@ -0,0 +1,35 @@ +package com.tangem.tap.features.wallet.ui.dialogs + +import android.content.Context +import androidx.appcompat.app.AlertDialog +import com.tangem.tap.common.extensions.dispatchDialogHide +import com.tangem.tap.common.redux.AppDialog +import com.tangem.tap.store +import com.tangem.wallet.R + +/** +[REDACTED_AUTHOR] + */ +class SimpleOkDialog { + + companion object { + fun create(dialog: AppDialog.SimpleOkDialog, context: Context): AlertDialog { + return AlertDialog.Builder(context).apply { + setTitle(dialog.header) + setMessage(dialog.message) + setPositiveButton(R.string.common_ok) { _, _ -> } + setOnDismissListener { store.dispatchDialogHide() } + }.create() + } + + fun create(dialog: AppDialog.SimpleOkDialogRes, context: Context): AlertDialog { + return AlertDialog.Builder(context).apply { + setTitle(context.getString(dialog.headerId)) + setMessage(dialog.messageId) + setPositiveButton(R.string.common_ok) { _, _ -> } + setOnDismissListener { store.dispatchDialogHide() } + }.create() + } + } + +} \ No newline at end of file From 1f80755686b6a0435541eff57083197c9c154851 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 23 Feb 2022 12:55:51 +0300 Subject: [PATCH 11/16] Updated on 2026-08-14 --- app/src/main/res/values-de/strings_final.xml | 37 ++++++++++++++++++++ app/src/main/res/values-fr/strings_final.xml | 37 ++++++++++++++++++++ app/src/main/res/values-it/strings_final.xml | 37 ++++++++++++++++++++ app/src/main/res/values-ru/strings_final.xml | 37 ++++++++++++++++++++ app/src/main/res/values/strings_final.xml | 37 ++++++++++++++++++++ 5 files changed, 185 insertions(+) create mode 100644 app/src/main/res/values-de/strings_final.xml create mode 100644 app/src/main/res/values-fr/strings_final.xml create mode 100644 app/src/main/res/values-it/strings_final.xml create mode 100644 app/src/main/res/values-ru/strings_final.xml create mode 100644 app/src/main/res/values/strings_final.xml diff --git a/app/src/main/res/values-de/strings_final.xml b/app/src/main/res/values-de/strings_final.xml new file mode 100644 index 0000000000..339691d69b --- /dev/null +++ b/app/src/main/res/values-de/strings_final.xml @@ -0,0 +1,37 @@ + + + One Wallet + 3 cards + 2 cards + Shipping + Free + I have a promo code… + Total + Other payment methods + Buy now + Placing your order + Your order + Meet\nTangem + Buy + Store + Send + Pay + Exchange + Lend + Borrow + Stake + Revolutionary Hardware Wallet + Store your crypto assets secure while keeping private keys contained in your card + Ultra Secure Backup + Up to 3 physical cards to one wallet + Thousands of Currencies + A hardware wallet for your Bitcoin, Ethereum and many more currencies simultaneously – all in one card + Web3 Compatible + Exchange, buy NFT’s, make loans and deposits in more than 100 different decentralized services + The Wallet for Everyone + Use it on the go, anywhere, anytime. No wires or batteries. Just tap the card to your phone when you need your crypto. + Order card + You are currently running in Demo mode. All funds are not real. + This feature is disabled in Demo mode. + The transaction has been successfully signed, but not sent to the blockchain because of Demo mode. + \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings_final.xml b/app/src/main/res/values-fr/strings_final.xml new file mode 100644 index 0000000000..339691d69b --- /dev/null +++ b/app/src/main/res/values-fr/strings_final.xml @@ -0,0 +1,37 @@ + + + One Wallet + 3 cards + 2 cards + Shipping + Free + I have a promo code… + Total + Other payment methods + Buy now + Placing your order + Your order + Meet\nTangem + Buy + Store + Send + Pay + Exchange + Lend + Borrow + Stake + Revolutionary Hardware Wallet + Store your crypto assets secure while keeping private keys contained in your card + Ultra Secure Backup + Up to 3 physical cards to one wallet + Thousands of Currencies + A hardware wallet for your Bitcoin, Ethereum and many more currencies simultaneously – all in one card + Web3 Compatible + Exchange, buy NFT’s, make loans and deposits in more than 100 different decentralized services + The Wallet for Everyone + Use it on the go, anywhere, anytime. No wires or batteries. Just tap the card to your phone when you need your crypto. + Order card + You are currently running in Demo mode. All funds are not real. + This feature is disabled in Demo mode. + The transaction has been successfully signed, but not sent to the blockchain because of Demo mode. + \ No newline at end of file diff --git a/app/src/main/res/values-it/strings_final.xml b/app/src/main/res/values-it/strings_final.xml new file mode 100644 index 0000000000..339691d69b --- /dev/null +++ b/app/src/main/res/values-it/strings_final.xml @@ -0,0 +1,37 @@ + + + One Wallet + 3 cards + 2 cards + Shipping + Free + I have a promo code… + Total + Other payment methods + Buy now + Placing your order + Your order + Meet\nTangem + Buy + Store + Send + Pay + Exchange + Lend + Borrow + Stake + Revolutionary Hardware Wallet + Store your crypto assets secure while keeping private keys contained in your card + Ultra Secure Backup + Up to 3 physical cards to one wallet + Thousands of Currencies + A hardware wallet for your Bitcoin, Ethereum and many more currencies simultaneously – all in one card + Web3 Compatible + Exchange, buy NFT’s, make loans and deposits in more than 100 different decentralized services + The Wallet for Everyone + Use it on the go, anywhere, anytime. No wires or batteries. Just tap the card to your phone when you need your crypto. + Order card + You are currently running in Demo mode. All funds are not real. + This feature is disabled in Demo mode. + The transaction has been successfully signed, but not sent to the blockchain because of Demo mode. + \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings_final.xml b/app/src/main/res/values-ru/strings_final.xml new file mode 100644 index 0000000000..dac3254b83 --- /dev/null +++ b/app/src/main/res/values-ru/strings_final.xml @@ -0,0 +1,37 @@ + + + Один Кошелек + 3 карты + 2 карты + Доставка + Бесплатно + У меня есть промо-код… + Итого + Другие способы оплаты + Купить сейчас + Оформление вашего заказа + Ваш заказ + Встречайте\nTangem + Покупайте + Храните + Отправляйте + Расплачивайтесь + Обменивайте + Одалживайте + Занимайте + Вкладывайте + Революционный аппаратный кошелек + Держите свои криптосбережения в безопасности - приватные ключи надежно хранятся на карте + Ультрабезопасная резервная копия + До трех карт с одним кошельком + Тысячи криптовалют + Аппаратный кошелек для ваших биткоинов, эфира и многих других валют одновременно — все в одной карте + Поддерживает Web3 + Обменивайте, покупайте NFT, получайте займы и вклады в более чем 100 различных децентрализованных сервисах + Кошелек для каждого + Используйте его на ходу, в любом месте, в любое время. Без проводов и аккумуляторов. Как только понадобится крипта, просто приложите карту к телефону. + Заказать карту + Приложение работает в демонстрационном режиме. Средства на всех счетах ненастоящие. + Эта функция недоступна в демонстрационном режиме + Транзакция успешно подписана, но не отправлена в блокчейн, потому что активирован демонстрационный режим. + \ No newline at end of file diff --git a/app/src/main/res/values/strings_final.xml b/app/src/main/res/values/strings_final.xml new file mode 100644 index 0000000000..339691d69b --- /dev/null +++ b/app/src/main/res/values/strings_final.xml @@ -0,0 +1,37 @@ + + + One Wallet + 3 cards + 2 cards + Shipping + Free + I have a promo code… + Total + Other payment methods + Buy now + Placing your order + Your order + Meet\nTangem + Buy + Store + Send + Pay + Exchange + Lend + Borrow + Stake + Revolutionary Hardware Wallet + Store your crypto assets secure while keeping private keys contained in your card + Ultra Secure Backup + Up to 3 physical cards to one wallet + Thousands of Currencies + A hardware wallet for your Bitcoin, Ethereum and many more currencies simultaneously – all in one card + Web3 Compatible + Exchange, buy NFT’s, make loans and deposits in more than 100 different decentralized services + The Wallet for Everyone + Use it on the go, anywhere, anytime. No wires or batteries. Just tap the card to your phone when you need your crypto. + Order card + You are currently running in Demo mode. All funds are not real. + This feature is disabled in Demo mode. + The transaction has been successfully signed, but not sent to the blockchain because of Demo mode. + \ No newline at end of file From ab6346fc629f804e7ce6f2748351708c18ea8540 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 23 Feb 2022 12:58:00 +0300 Subject: [PATCH 12/16] Updated on 2026-08-14 --- .../tap/common/extensions/WalletManager.kt | 12 +- .../com/tangem/tap/domain/TapWalletManager.kt | 7 +- .../warningMessage/WarningMessagesManager.kt | 106 +++---- .../tap/domain/tokens/CurrenciesRepository.kt | 11 +- .../tangem/tap/features/demo/DemoHelper.kt | 154 +++++++++++ .../tap/features/demo/DemoMiddlewares.kt | 58 ++++ .../tangem/tap/features/demo/Extentions.kt | 12 + .../walletconnect/WalletConnectMiddleware.kt | 259 +++++++++--------- .../note/redux/OnboardingNoteMiddleware.kt | 7 +- .../redux/OnboardingWalletMiddleware.kt | 7 +- .../send/redux/middlewares/SendMiddleware.kt | 17 +- .../middlewares/MultiWalletMiddleware.kt | 11 + .../middlewares/TradeCryptoMiddleware.kt | 6 +- .../redux/middlewares/WalletMiddleware.kt | 18 +- .../redux/middlewares/WarningsMiddleware.kt | 4 + 15 files changed, 492 insertions(+), 197 deletions(-) create mode 100644 app/src/main/java/com/tangem/tap/features/demo/DemoHelper.kt create mode 100644 app/src/main/java/com/tangem/tap/features/demo/DemoMiddlewares.kt create mode 100644 app/src/main/java/com/tangem/tap/features/demo/Extentions.kt diff --git a/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt b/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt index 3d33ceeaa8..f552e835f6 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt @@ -8,18 +8,26 @@ import com.tangem.tap.domain.TapError import com.tangem.tap.domain.extensions.amountToCreateAccount import com.tangem.tap.domain.getFirstToken import com.tangem.tap.domain.topup.TradeCryptoHelper +import com.tangem.tap.features.demo.isDemoWallet import com.tangem.tap.features.wallet.redux.AddressData import com.tangem.tap.features.wallet.redux.reducers.createAddressesData import com.tangem.tap.network.NetworkConnectivity import com.tangem.tap.store +import timber.log.Timber /** [REDACTED_AUTHOR] */ suspend fun WalletManager.safeUpdate(): Result = try { - update() - Result.Success(wallet) + if (isDemoWallet()) { + Result.Success(wallet) + } else { + update() + Result.Success(wallet) + } } catch (exception: Exception) { + Timber.e(exception) + if (!NetworkConnectivity.getInstance().isOnlineOrConnecting()) { Result.Failure(TapError.NoInternetConnection) } else { diff --git a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt index cfd628a093..9e6fcd5de6 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt @@ -10,9 +10,11 @@ import com.tangem.tap.currenciesRepository import com.tangem.tap.domain.TapWorkarounds.isStart2Coin import com.tangem.tap.domain.TapWorkarounds.isTestCard import com.tangem.tap.domain.configurable.config.ConfigManager -import com.tangem.tap.domain.extensions.* +import com.tangem.tap.domain.extensions.makePrimaryWalletManager +import com.tangem.tap.domain.extensions.makeWalletManagersForApp import com.tangem.tap.domain.tasks.product.ScanResponse import com.tangem.tap.domain.tokens.CardCurrencies +import com.tangem.tap.features.demo.isDemoCard import com.tangem.tap.features.wallet.redux.Currency import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.network.NetworkConnectivity @@ -207,6 +209,9 @@ class TapWalletManager { data.getBlockchain() == Blockchain.Unknown && !data.card.isMultiwalletAllowed -> { WalletAction.LoadData.Failure(TapError.UnknownBlockchain) } + data.isDemoCard() -> { + return null + } data.card.wallets.isEmpty() -> { WalletAction.EmptyWallet } diff --git a/app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningMessagesManager.kt b/app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningMessagesManager.kt index 3cdf14dfea..663bbcbd6c 100644 --- a/app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningMessagesManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningMessagesManager.kt @@ -10,7 +10,7 @@ import com.tangem.wallet.R [REDACTED_AUTHOR] */ class WarningMessagesManager( - private val warningLoader: RemoteWarningLoader, + private val warningLoader: RemoteWarningLoader, ) { private val warningsList: MutableList = mutableListOf() @@ -33,15 +33,15 @@ class WarningMessagesManager( fun getWarnings(location: WarningMessage.Location, forBlockchains: List = emptyList()): List { return warningsList - .filter { !it.isHidden && it.location.contains(location) } - .filter { - val list = it.blockchainList - when { - list == null -> true - list.containsAny(forBlockchains) -> true - else -> false - } + .filter { !it.isHidden && it.location.contains(location) } + .filter { + val list = it.blockchainList + when { + list == null -> true + list.containsAny(forBlockchains) -> true + else -> false } + } } fun hideWarning(warning: WarningMessage): Boolean { @@ -49,7 +49,7 @@ class WarningMessagesManager( return when { foundWarning == null -> false foundWarning.type == WarningMessage.Type.Temporary - || foundWarning.type == WarningMessage.Type.AppRating -> { + || foundWarning.type == WarningMessage.Type.AppRating -> { if (foundWarning.isHidden) { false } else { @@ -80,32 +80,32 @@ class WarningMessagesManager( companion object { fun devCardWarning(): WarningMessage = WarningMessage( - "", - "", - type = WarningMessage.Type.Permanent, - priority = WarningMessage.Priority.Critical, - listOf(WarningMessage.Location.MainScreen), - null, - R.string.alert_title, - R.string.alert_developer_card, - WarningMessage.Origin.Local + "", + "", + type = WarningMessage.Type.Permanent, + priority = WarningMessage.Priority.Critical, + listOf(WarningMessage.Location.MainScreen), + null, + R.string.alert_title, + R.string.alert_developer_card, + WarningMessage.Origin.Local ) fun alreadySignedHashesWarning(): WarningMessage = WarningMessage( - "", - "", - type = WarningMessage.Type.Temporary, - priority = WarningMessage.Priority.Info, - listOf(WarningMessage.Location.MainScreen), - null, - R.string.alert_title, - R.string.alert_card_signed_transactions, - WarningMessage.Origin.Local + "", + "", + type = WarningMessage.Type.Temporary, + priority = WarningMessage.Priority.Info, + listOf(WarningMessage.Location.MainScreen), + null, + R.string.alert_title, + R.string.alert_card_signed_transactions, + WarningMessage.Origin.Local ) fun signedHashesMultiWalletWarning(): WarningMessage = WarningMessage( title = "", - message = "", + message = "", type = WarningMessage.Type.Temporary, priority = WarningMessage.Priority.Info, location = listOf(WarningMessage.Location.MainScreen), @@ -117,15 +117,15 @@ class WarningMessagesManager( ) fun appRatingWarning(): WarningMessage = WarningMessage( - "", - "", - WarningMessage.Type.AppRating, - WarningMessage.Priority.Info, - listOf(WarningMessage.Location.MainScreen), - null, - R.string.warning_rate_app_title, - R.string.warning_rate_app_message, - WarningMessage.Origin.Local + "", + "", + WarningMessage.Type.AppRating, + WarningMessage.Priority.Info, + listOf(WarningMessage.Location.MainScreen), + null, + R.string.warning_rate_app_title, + R.string.warning_rate_app_message, + WarningMessage.Origin.Local ) fun isAlreadySignedHashesWarning(warning: WarningMessage): Boolean { @@ -133,15 +133,15 @@ class WarningMessagesManager( } fun onlineVerificationFailed(): WarningMessage = WarningMessage( - "", - "", - type = WarningMessage.Type.Permanent, - priority = WarningMessage.Priority.Critical, - listOf(WarningMessage.Location.MainScreen), - null, - R.string.warning_failed_to_verify_card_title, - R.string.warning_failed_to_verify_card_message, - WarningMessage.Origin.Local + "", + "", + type = WarningMessage.Type.Permanent, + priority = WarningMessage.Priority.Critical, + listOf(WarningMessage.Location.MainScreen), + null, + R.string.warning_failed_to_verify_card_title, + R.string.warning_failed_to_verify_card_message, + WarningMessage.Origin.Local ) fun remainingSignaturesNotEnough(remainingSignatures: Int): WarningMessage = WarningMessage( @@ -169,6 +169,18 @@ class WarningMessagesManager( WarningMessage.Origin.Local ) + fun demoCardWarning(): WarningMessage = WarningMessage( + "", + "", + type = WarningMessage.Type.Permanent, + priority = WarningMessage.Priority.Critical, + listOf(WarningMessage.Location.MainScreen), + null, + R.string.alert_title, + R.string.alert_demo_message, + WarningMessage.Origin.Local + ) + const val REMAINING_SIGNATURES_WARNING = 10 } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/tokens/CurrenciesRepository.kt b/app/src/main/java/com/tangem/tap/domain/tokens/CurrenciesRepository.kt index f56e6f7bc8..4817a87b36 100644 --- a/app/src/main/java/com/tangem/tap/domain/tokens/CurrenciesRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/tokens/CurrenciesRepository.kt @@ -13,9 +13,11 @@ import com.tangem.tap.common.extensions.appendIf import com.tangem.tap.common.extensions.readJsonFileToString import com.tangem.tap.domain.extensions.getCustomIconUrl import com.tangem.tap.domain.extensions.setCustomIconUrl +import com.tangem.tap.features.demo.DemoHelper import com.tangem.tap.network.createMoshi -class CurrenciesRepository(val context: Application) { +open class CurrenciesRepository(val context: Application) { + private val moshi = createMoshi() private val blockchainsAdapter: JsonAdapter> = moshi.adapter( Types.newParameterizedType(List::class.java, Blockchain::class.java) @@ -28,10 +30,13 @@ class CurrenciesRepository(val context: Application) { ) fun loadCardCurrencies(cardId: String): CardCurrencies? { - val blockchains = loadSavedBlockchains(cardId) + val blockchains = loadSavedBlockchains(cardId).toMutableSet() + if (DemoHelper.isDemoCardId(cardId)) { + blockchains.addAll(DemoHelper.config.demoBlockchains) + } if (blockchains.isEmpty()) return null - return CardCurrencies(loadSavedTokens(cardId), blockchains) + return CardCurrencies(loadSavedTokens(cardId), blockchains.toList()) } fun saveCardCurrencies(cardId: String, currencies: CardCurrencies) { diff --git a/app/src/main/java/com/tangem/tap/features/demo/DemoHelper.kt b/app/src/main/java/com/tangem/tap/features/demo/DemoHelper.kt new file mode 100644 index 0000000000..8f1038b60f --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/demo/DemoHelper.kt @@ -0,0 +1,154 @@ +package com.tangem.tap.features.demo + +import com.tangem.blockchain.common.* +import com.tangem.blockchain.extensions.Result +import com.tangem.blockchain.extensions.SimpleResult +import com.tangem.tap.common.extensions.dispatchNotification +import com.tangem.tap.common.redux.AppState +import com.tangem.tap.domain.tasks.product.ScanResponse +import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction +import com.tangem.tap.features.onboarding.products.wallet.redux.BackupAction +import com.tangem.tap.features.wallet.redux.WalletAction +import com.tangem.tap.store +import com.tangem.wallet.BuildConfig +import com.tangem.wallet.R +import org.rekotlin.Action +import java.math.BigDecimal + +/** +[REDACTED_AUTHOR] + */ +interface DemoMiddleware { + fun tryHandle(config: DemoConfig, scanResponse: ScanResponse, action: Action): Boolean +} + +object DemoHelper { + val config = DemoConfig() + + private val demoMiddlewares = listOf( + DemoOnboardingNoteMiddleware(), + ) + + private val disabledActionFeatures = listOf( + WalletConnectAction.StartWalletConnect::class.java, + WalletAction.TradeCryptoAction.Buy::class.java, + WalletAction.TradeCryptoAction.Sell::class.java, + BackupAction.StartBackup::class.java, + WalletAction.ExploreAddress::class.java + ) + + fun isDemoCard(scanResponse: ScanResponse): Boolean = isDemoCardId(scanResponse.card.cardId) + + fun isDemoCardId(cardId: String): Boolean = config.isDemoCardId(cardId) + + fun tryHandle(appState: () -> AppState?, action: Action): Boolean { + val scanResponse = getScanResponse(appState) ?: return false + if (!scanResponse.isDemoCard()) return false + + demoMiddlewares.forEach { + if (it.tryHandle(config, scanResponse, action)) return true + } + + disabledActionFeatures.firstOrNull { it == action::class.java }?.let { + store.dispatchNotification(R.string.alert_demo_feature_disabled) + return true + } + + return false + } + + fun injectDemoBalance(walletManager: WalletManager?) { + val manager = walletManager ?: return + + val blockchain = walletManager.wallet.blockchain + val amount = config.getBalance(blockchain) + manager.wallet.setAmount(amount) + } + + private fun getScanResponse(appState: () -> AppState?): ScanResponse? { + val state = appState() ?: return null + + return state.globalState.onboardingState.onboardingManager?.scanResponse + ?: state.globalState.scanResponse + } +} + +class DemoConfig { + + val demoBlockchains = listOf( + Blockchain.Bitcoin, + Blockchain.Ethereum, + Blockchain.XRP, + Blockchain.Dogecoin, + Blockchain.Solana, + ) + + val demoCardIds: List by lazy { + val demoIds = (releaseDemoCardIds + testDemoCardIds).toMutableList() + if (BuildConfig.DEBUG) demoIds.addAll(debugTestDemoCardIds) + + return@lazy demoIds + } + + private val walletBalances: Map = mapOf( + Blockchain.Bitcoin to Amount(0.028.toBigDecimal(), Blockchain.Bitcoin), + Blockchain.Ethereum to Amount(0.2311.toBigDecimal(), Blockchain.Ethereum), + Blockchain.XRP to Amount(1248.56.toBigDecimal(), Blockchain.XRP), + Blockchain.Dogecoin to Amount(1450.025.toBigDecimal(), Blockchain.Dogecoin), + Blockchain.Solana to Amount(13.246.toBigDecimal(), Blockchain.Solana), + ) + + fun isDemoCardId(cardId: String): Boolean = demoCardIds.contains(cardId) + + fun getBalance(blockchain: Blockchain): Amount = walletBalances[blockchain]?.copy() + ?: Amount(BigDecimal.ZERO, blockchain).copy() + + private val releaseDemoCardIds = mutableListOf( + + ) + + private val testDemoCardIds = listOf( + "FB30000000000176", + "FB20000000000186", + "FB10000000000196", + ) + + private val debugTestDemoCardIds = listOf( + "AB06000000018575", // Note XRP + "AB04000000011036", // Note Doge + "AB01000000045060", // Note BTC + "AB02000000045028", // Note ETH + "AC01000000200003", // Wallet 4.52 + "AC79000000000004", // Wallet 4.46 + ) +} + +class DemoTransactionSender( + private val walletManager: WalletManager, + private val sender: TransactionSender = walletManager as TransactionSender +) : TransactionSender { + + override suspend fun getFee(amount: Amount, destination: String): Result> = + sender.getFee(amount, destination) + + override suspend fun send(transactionData: TransactionData, signer: TransactionSigner): SimpleResult { + val dataToSign = randomString(32).toByteArray() + val signerResponse = signer.sign(dataToSign, walletManager.wallet.cardId, walletManager.wallet.publicKey) + return SimpleResult.Failure(Exception(ID)) + } + + private fun randomInt(from: Int, to: Int): Int = kotlin.random.Random.nextInt(from, to) + + private fun randomString(length: Int): String { + val charPool: List = ('a'..'z') + ('A'..'Z') + ('0'..'9') + return (1..length) + .map { randomInt(0, charPool.size) } + .map(charPool::get) + .joinToString("") + } + + companion object{ + val ID = DemoTransactionSender::class.java.simpleName + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/demo/DemoMiddlewares.kt b/app/src/main/java/com/tangem/tap/features/demo/DemoMiddlewares.kt new file mode 100644 index 0000000000..7537d54bdd --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/demo/DemoMiddlewares.kt @@ -0,0 +1,58 @@ +package com.tangem.tap.features.demo + +import com.tangem.common.extensions.guard +import com.tangem.tap.common.extensions.withMainContext +import com.tangem.tap.domain.extensions.makePrimaryWalletManager +import com.tangem.tap.domain.tasks.product.ScanResponse +import com.tangem.tap.features.onboarding.products.note.redux.OnboardingNoteAction +import com.tangem.tap.features.wallet.redux.Currency +import com.tangem.tap.features.wallet.redux.ProgressState +import com.tangem.tap.scope +import com.tangem.tap.store +import kotlinx.coroutines.launch +import org.rekotlin.Action + +/** +[REDACTED_AUTHOR] + */ +internal class DemoOnboardingNoteMiddleware : DemoMiddleware { + + override fun tryHandle(config: DemoConfig, scanResponse: ScanResponse, action: Action): Boolean { + val globalState = store.state.globalState + val noteState = store.state.onboardingNoteState + + when (action) { + is OnboardingNoteAction.Balance.Update -> { + val walletManager = if (noteState.walletManager != null) { + noteState.walletManager + } else { + val wmFactory = globalState.tapWalletManager.walletManagerFactory + val walletManager = wmFactory.makePrimaryWalletManager(scanResponse).guard { + return false + } + store.dispatch(OnboardingNoteAction.SetWalletManager(walletManager)) + walletManager + } + val balanceAmount = config.getBalance(walletManager.wallet.blockchain) + val loadedBalance = noteState.walletBalance.copy( + value = balanceAmount.value!!, + currency = Currency.Blockchain(walletManager.wallet.blockchain), + state = ProgressState.Done, + error = null, + criticalError = null + ) + walletManager.wallet.setAmount(balanceAmount) + + scope.launch { + withMainContext { + store.dispatch(OnboardingNoteAction.Balance.Set(loadedBalance)) + store.dispatch(OnboardingNoteAction.Balance.SetCriticalError(loadedBalance.criticalError)) + store.dispatch(OnboardingNoteAction.Balance.SetNonCriticalError(loadedBalance.error)) + } + } + return true + } + } + return false + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/demo/Extentions.kt b/app/src/main/java/com/tangem/tap/features/demo/Extentions.kt new file mode 100644 index 0000000000..f32c079efc --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/demo/Extentions.kt @@ -0,0 +1,12 @@ +package com.tangem.tap.features.demo + +import com.tangem.blockchain.common.Wallet +import com.tangem.blockchain.common.WalletManager +import com.tangem.tap.domain.tasks.product.ScanResponse + +/** +[REDACTED_AUTHOR] + */ +fun ScanResponse.isDemoCard(): Boolean = DemoHelper.isDemoCardId(card.cardId) +fun WalletManager.isDemoWallet(): Boolean = DemoHelper.isDemoCardId(wallet.cardId) +fun Wallet.isDemoWallet(): Boolean = DemoHelper.isDemoCardId(cardId) \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt index a8517bd1bc..6db0bf1a97 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt @@ -17,9 +17,11 @@ import com.tangem.tap.domain.tasks.product.ScanResponse import com.tangem.tap.domain.walletconnect.BnbHelper import com.tangem.tap.domain.walletconnect.WalletConnectManager import com.tangem.tap.domain.walletconnect.WalletConnectNetworkUtils +import com.tangem.tap.features.demo.DemoHelper import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.store import com.tangem.wallet.R +import org.rekotlin.Action import org.rekotlin.Middleware class WalletConnectMiddleware { @@ -28,138 +30,131 @@ class WalletConnectMiddleware { val walletConnectMiddleware: Middleware = { dispatch, state -> { next -> { action -> - when (action) { + handle(state, action) + next(action) + } + } + } - is WalletConnectAction.RestoreSessions -> { - walletConnectManager.restoreSessions() - } + private fun handle(state: () -> AppState?, action: Action) { + if (DemoHelper.tryHandle(state, action)) return - is WalletConnectAction.HandleDeepLink -> { - if (!action.wcUri.isNullOrBlank()) { - if (WalletConnectManager.isCorrectWcUri(action.wcUri)) { - store.dispatchOnMain(WalletConnectAction.OpenSession(action.wcUri)) - } - } - } - - is WalletConnectAction.StartWalletConnect -> { - val uri = action.activity.getFromClipboard()?.toString() - if (uri != null && WalletConnectManager.isCorrectWcUri(uri)) { - store.dispatchOnMain(WalletConnectAction.ShowClipboardOrScanQrDialog(uri)) - } else { - store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.QrScan)) - } - } - - is WalletConnectAction.ShowClipboardOrScanQrDialog -> { - store.dispatchOnMain( - GlobalAction.ShowDialog( - WalletConnectDialog.ClipboardOrScanQr( - action.wcUri - ) - ) - ) - } - - is WalletConnectAction.OpeningSessionTimeout -> { - store.dispatchOnMain(GlobalAction.ShowDialog(WalletConnectDialog.SessionTimeout)) - } - - is WalletConnectAction.FailureEstablishingSession -> { - if (action.session != null) { - walletConnectManager.disconnect(action.session) - } - } - - is WalletConnectAction.UnsupportedCard -> { - store.dispatchOnMain(GlobalAction.ShowDialog(WalletConnectDialog.UnsupportedCard)) - } - - is WalletConnectAction.OpenSession -> { - walletConnectManager.connect( - wcUri = action.wcUri, - ) - } - - is WalletConnectAction.RefuseOpeningSession -> { - store.dispatch( - GlobalAction.ShowDialog( - WalletConnectDialog.OpeningSessionRejected - ) - ) - } - - is WalletConnectAction.ScanCard -> { - scanCard(action.session, action.chainId) - } - - is WalletConnectAction.ApproveSession -> { - walletConnectManager.approve(action.session) - } - - is WalletConnectAction.DisconnectSession -> { - walletConnectManager.disconnect(action.session) - } - - is WalletConnectAction.HandleTransactionRequest -> { - walletConnectManager.handleTransactionRequest( - transaction = action.transaction, - session = action.session, - id = action.id, - type = action.type - ) - } - is WalletConnectAction.HandlePersonalSignRequest -> { - walletConnectManager.handlePersonalSignRequest( - message = action.message, - session = action.session, - id = action.id - ) - } - is WalletConnectAction.RejectRequest -> { - walletConnectManager.rejectRequest(action.session, action.id) - } - is WalletConnectAction.SendTransaction -> { - walletConnectManager.completeTransaction(action.session) - } - is WalletConnectAction.SignMessage -> { - walletConnectManager.sendSignedMessage(action.session) - } - is WalletConnectAction.BinanceTransaction.Trade -> { - val messageData = BnbHelper.createMessageData(action.order) - store.dispatchOnMain( - GlobalAction.ShowDialog( - WalletConnectDialog.BnbTransactionDialog( - data = messageData, - session = action.sessionData.session, - sessionId = action.id, - cardId = action.sessionData.wallet.cardId, - dAppName = action.sessionData.peerMeta.name - ) - ) - ) - } - is WalletConnectAction.BinanceTransaction.Transfer -> { - val messageData = BnbHelper.createMessageData(action.order) - store.dispatchOnMain( - GlobalAction.ShowDialog( - WalletConnectDialog.BnbTransactionDialog( - data = messageData, - session = action.sessionData.session, - sessionId = action.id, - cardId = action.sessionData.wallet.cardId, - dAppName = action.sessionData.peerMeta.name - ) - ) - ) - } - is WalletConnectAction.BinanceTransaction.Sign -> { - walletConnectManager.signBnb( - action.id, action.data, action.sessionData - ) + when (action) { + is WalletConnectAction.RestoreSessions -> { + walletConnectManager.restoreSessions() + } + is WalletConnectAction.HandleDeepLink -> { + if (!action.wcUri.isNullOrBlank()) { + if (WalletConnectManager.isCorrectWcUri(action.wcUri)) { + store.dispatchOnMain(WalletConnectAction.OpenSession(action.wcUri)) } } - next(action) + } + is WalletConnectAction.StartWalletConnect -> { + val uri = action.activity.getFromClipboard()?.toString() + if (uri != null && WalletConnectManager.isCorrectWcUri(uri)) { + store.dispatchOnMain(WalletConnectAction.ShowClipboardOrScanQrDialog(uri)) + } else { + store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.QrScan)) + } + } + is WalletConnectAction.ShowClipboardOrScanQrDialog -> { + store.dispatchOnMain( + GlobalAction.ShowDialog( + WalletConnectDialog.ClipboardOrScanQr( + action.wcUri + ) + ) + ) + } + is WalletConnectAction.OpeningSessionTimeout -> { + store.dispatchOnMain(GlobalAction.ShowDialog(WalletConnectDialog.SessionTimeout)) + } + is WalletConnectAction.FailureEstablishingSession -> { + if (action.session != null) { + walletConnectManager.disconnect(action.session) + } + } + is WalletConnectAction.UnsupportedCard -> { + store.dispatchOnMain(GlobalAction.ShowDialog(WalletConnectDialog.UnsupportedCard)) + } + is WalletConnectAction.OpenSession -> { + walletConnectManager.connect( + wcUri = action.wcUri, + ) + } + is WalletConnectAction.RefuseOpeningSession -> { + store.dispatch( + GlobalAction.ShowDialog( + WalletConnectDialog.OpeningSessionRejected + ) + ) + } + is WalletConnectAction.ScanCard -> { + scanCard(action.session, action.chainId) + } + is WalletConnectAction.ApproveSession -> { + walletConnectManager.approve(action.session) + } + is WalletConnectAction.DisconnectSession -> { + walletConnectManager.disconnect(action.session) + } + is WalletConnectAction.HandleTransactionRequest -> { + walletConnectManager.handleTransactionRequest( + transaction = action.transaction, + session = action.session, + id = action.id, + type = action.type + ) + } + is WalletConnectAction.HandlePersonalSignRequest -> { + walletConnectManager.handlePersonalSignRequest( + message = action.message, + session = action.session, + id = action.id + ) + } + is WalletConnectAction.RejectRequest -> { + walletConnectManager.rejectRequest(action.session, action.id) + } + is WalletConnectAction.SendTransaction -> { + walletConnectManager.completeTransaction(action.session) + } + is WalletConnectAction.SignMessage -> { + walletConnectManager.sendSignedMessage(action.session) + } + is WalletConnectAction.BinanceTransaction.Trade -> { + val messageData = BnbHelper.createMessageData(action.order) + store.dispatchOnMain( + GlobalAction.ShowDialog( + WalletConnectDialog.BnbTransactionDialog( + data = messageData, + session = action.sessionData.session, + sessionId = action.id, + cardId = action.sessionData.wallet.cardId, + dAppName = action.sessionData.peerMeta.name + ) + ) + ) + } + is WalletConnectAction.BinanceTransaction.Transfer -> { + val messageData = BnbHelper.createMessageData(action.order) + store.dispatchOnMain( + GlobalAction.ShowDialog( + WalletConnectDialog.BnbTransactionDialog( + data = messageData, + session = action.sessionData.session, + sessionId = action.id, + cardId = action.sessionData.wallet.cardId, + dAppName = action.sessionData.peerMeta.name + ) + ) + ) + } + is WalletConnectAction.BinanceTransaction.Sign -> { + walletConnectManager.signBnb( + action.id, action.data, action.sessionData + ) } } } @@ -190,9 +185,9 @@ class WalletConnectMiddleware { } val walletManager = getWalletManager(scanResponse, blockchain).guard { - store.dispatchOnMain(WalletConnectAction.FailureEstablishingSession(null)) - return - } + store.dispatchOnMain(WalletConnectAction.FailureEstablishingSession(null)) + return + } val wallet = walletManager.wallet val derivedKey = @@ -227,7 +222,7 @@ class WalletConnectMiddleware { ): WalletManager? { val card = scanResponse.card val factory = store.state.globalState.tapWalletManager.walletManagerFactory - val blockchainToMake = if (blockchain == Blockchain.Ethereum && card.isTestCard) { + val blockchainToMake = if (blockchain == Blockchain.Ethereum && card.isTestCard) { Blockchain.EthereumTestnet } else { blockchain diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt index 6a8cc146b7..a611b435d6 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt @@ -13,6 +13,7 @@ import com.tangem.tap.domain.DELAY_SDK_DIALOG_CLOSE import com.tangem.tap.domain.TapError import com.tangem.tap.domain.extensions.hasWallets import com.tangem.tap.domain.extensions.makePrimaryWalletManager +import com.tangem.tap.features.demo.DemoHelper import com.tangem.tap.features.wallet.redux.Currency import com.tangem.tap.features.wallet.redux.ProgressState import com.tangem.tap.scope @@ -33,14 +34,16 @@ class OnboardingNoteMiddleware { private val onboardingNoteMiddleware: Middleware = { dispatch, state -> { next -> { action -> - handleNoteAction(action, dispatch) + handleNoteAction(state, action, dispatch) next(action) } } } -private fun handleNoteAction(action: Action, dispatch: DispatchFunction) { +private fun handleNoteAction(appState: () -> AppState?, action: Action, dispatch: DispatchFunction) { if (action !is OnboardingNoteAction) return + if (DemoHelper.tryHandle(appState, action)) return + val globalState = store.state.globalState val onboardingManager = globalState.onboardingState.onboardingManager ?: return diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt index 29cdd561b2..9c61e0c402 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt @@ -16,6 +16,7 @@ import com.tangem.tap.common.redux.navigation.AppScreen import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.domain.extensions.hasWallets import com.tangem.tap.domain.tasks.product.ScanResponse +import com.tangem.tap.features.demo.DemoHelper import com.tangem.tap.features.home.redux.HomeAction import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletMiddleware.Companion.BUY_WALLET_URL import com.tangem.tap.features.wallet.redux.Artwork @@ -164,14 +165,16 @@ class BackupMiddleware { val backupMiddleware: Middleware = { dispatch, state -> { next -> { action -> - if (action is BackupAction) handleBackupAction(action) + if (action is BackupAction) handleBackupAction(state, action) next(action) } } } } -private fun handleBackupAction(action: BackupAction) { +private fun handleBackupAction(appState: () -> AppState?, action: BackupAction) { + if (DemoHelper.tryHandle(appState, action)) return + val backupState = store.state.onboardingWalletState.backupState val globalState = store.state.globalState diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt index 572658b793..34a63dd905 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt @@ -13,6 +13,7 @@ import com.tangem.tap.common.analytics.Analytics import com.tangem.tap.common.analytics.AnalyticsEvent import com.tangem.tap.common.analytics.AnalyticsParam import com.tangem.tap.common.extensions.* +import com.tangem.tap.common.redux.AppDialog import com.tangem.tap.common.redux.AppState import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.common.redux.navigation.NavigationAction @@ -22,6 +23,8 @@ import com.tangem.tap.domain.TapError import com.tangem.tap.domain.TapWorkarounds.isStart2Coin import com.tangem.tap.domain.configurable.warningMessage.WarningMessage import com.tangem.tap.domain.extensions.minimalAmount +import com.tangem.tap.features.demo.DemoTransactionSender +import com.tangem.tap.features.demo.isDemoWallet import com.tangem.tap.features.send.redux.* import com.tangem.tap.features.send.redux.FeeAction.RequestFee import com.tangem.tap.features.send.redux.states.ButtonState @@ -32,6 +35,7 @@ import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.scope import com.tangem.tap.store import com.tangem.tap.tangemSdk +import com.tangem.wallet.R import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.launch @@ -164,9 +168,12 @@ private fun sendTransaction( ) ) } - val sendResult = try { - (walletManager as TransactionSender).send(txData, signer) + if (walletManager.isDemoWallet()) { + DemoTransactionSender(walletManager).send(txData, signer) + } else { + (walletManager as TransactionSender).send(txData, signer) + } } catch (ex: Exception) { FirebaseCrashlytics.getInstance().recordException(ex) delay(DELAY_SDK_DIALOG_CLOSE) @@ -238,6 +245,12 @@ private fun sendTransaction( message.contains("Target account is not created. To create account send 1+ XLM.") -> { dispatch(SendAction.SendError(TapError.XmlError.AssetAccountNotCreated)) } + message.contains(DemoTransactionSender.ID) -> { + store.dispatchDialogShow(AppDialog.SimpleOkDialogRes( + R.string.common_done, + R.string.alert_demo_tx_send + )) + } else -> { (sendResult.error as? TangemSdkError)?.let { error -> store.state.globalState.analyticsHandlers?.logCardSdkError( diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt index 82f43f9812..5af387319d 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt @@ -37,6 +37,9 @@ class MultiWalletMiddleware { is WalletAction.MultiWallet.AddWalletManagers -> { globalState.feedbackManager?.infoHolder?.setWalletsInfo(action.walletManagers) action.walletManagers.forEach { checkForRentWarning(it) } + if (globalState.scanResponse?.isDemoCard() == true) { + addDummyBalances(action.walletManagers) + } } is WalletAction.MultiWallet.SelectWallet -> { if (action.walletData != null) { @@ -167,6 +170,14 @@ class MultiWalletMiddleware { } } + private fun addDummyBalances(walletManagers: List) { + walletManagers.forEach { + if (it.wallet.fundsAvailable(AmountType.Coin) == BigDecimal.ZERO) { + DemoHelper.injectDemoBalance(it) + } + } + } + private fun addToken(token: Token, walletState: WalletState?, globalState: GlobalState?) { val scanResponse = globalState?.scanResponse ?: return diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt index 2cd5627545..fdf3312ab0 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt @@ -3,10 +3,12 @@ package com.tangem.tap.features.wallet.redux.middlewares import com.tangem.blockchain.blockchains.ethereum.EthereumWalletManager import com.tangem.blockchain.common.AmountType import com.tangem.tap.common.extensions.dispatchOnMain +import com.tangem.tap.common.redux.AppState import com.tangem.tap.common.redux.navigation.AppScreen import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.domain.topup.TopUpManager import com.tangem.tap.domain.topup.TradeCryptoHelper +import com.tangem.tap.features.demo.DemoHelper import com.tangem.tap.features.send.redux.PrepareSendScreen import com.tangem.tap.features.send.redux.SendAction import com.tangem.tap.features.wallet.redux.Currency @@ -18,7 +20,9 @@ import timber.log.Timber class TradeCryptoMiddleware { - fun handle(action: WalletAction.TradeCryptoAction) { + fun handle(state: () -> AppState?, action: WalletAction.TradeCryptoAction) { + if (DemoHelper.tryHandle(state, action)) return + when (action) { is WalletAction.TradeCryptoAction.Buy -> startExchange(action) is WalletAction.TradeCryptoAction.Sell -> startExchange(action) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt index 37b71f1c2a..088fe72d40 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt @@ -3,13 +3,15 @@ package com.tangem.tap.features.wallet.redux.middlewares import android.content.Intent import android.net.Uri import androidx.core.content.ContextCompat -import com.tangem.blockchain.common.* +import com.tangem.blockchain.common.Amount +import com.tangem.blockchain.common.AmountType +import com.tangem.blockchain.common.Wallet +import com.tangem.blockchain.common.WalletManager import com.tangem.common.CompletionResult import com.tangem.common.core.TangemSdkError import com.tangem.common.extensions.isZero import com.tangem.common.services.Result import com.tangem.operations.attestation.OnlineCardVerifier -import com.tangem.tap.* import com.tangem.tap.common.analytics.Analytics import com.tangem.tap.common.extensions.* import com.tangem.tap.common.redux.AppDialog @@ -18,10 +20,14 @@ import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.common.redux.navigation.AppScreen import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.domain.extensions.toSendableAmounts +import com.tangem.tap.features.demo.DemoHelper import com.tangem.tap.features.home.redux.HomeAction import com.tangem.tap.features.send.redux.PrepareSendScreen import com.tangem.tap.features.wallet.redux.* import com.tangem.tap.network.NetworkStateChanged +import com.tangem.tap.scope +import com.tangem.tap.store +import com.tangem.tap.tangemSdkManager import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.launch @@ -37,18 +43,20 @@ class WalletMiddleware { val walletMiddleware: Middleware = { dispatch, state -> { next -> { action -> - handleAction(action, dispatch) + handleAction(state, action, dispatch) next(action) } } } - private fun handleAction(action: Action, dispatch: DispatchFunction) { + private fun handleAction(state: () -> AppState?, action: Action, dispatch: DispatchFunction) { + if (DemoHelper.tryHandle(state, action)) return + val globalState = store.state.globalState val walletState = store.state.walletState when (action) { - is WalletAction.TradeCryptoAction -> tradeCryptoMiddleware.handle(action) + is WalletAction.TradeCryptoAction -> tradeCryptoMiddleware.handle(state, action) is WalletAction.Warnings -> warningsMiddleware.handle(action, globalState) is WalletAction.MultiWallet -> multiWalletMiddleware.handle(action, walletState, globalState) is WalletAction.LoadWallet -> { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WarningsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WarningsMiddleware.kt index 408f0ef8a3..b7c104861d 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WarningsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WarningsMiddleware.kt @@ -17,6 +17,7 @@ import com.tangem.tap.domain.extensions.hasSignedHashes import com.tangem.tap.domain.extensions.remainingSignatures import com.tangem.tap.domain.isMultiwalletAllowed import com.tangem.tap.domain.tasks.product.ScanResponse +import com.tangem.tap.features.demo.isDemoCard import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.network.NetworkConnectivity import com.tangem.tap.preferencesStorage @@ -99,6 +100,9 @@ class WarningsMiddleware { addWarningMessage(WarningMessagesManager.onlineVerificationFailed()) } } + if (scanResponse.isDemoCard()){ + addWarningMessage(WarningMessagesManager.demoCardWarning()) + } setWarningMessages() } } From 9a21908d21eb25cdb98b49ffc7f4736892289496 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 23 Feb 2022 13:05:44 +0300 Subject: [PATCH 13/16] Updated on 2026-08-14 --- .../com/tangem/tap/features/demo/DemoHelper.kt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/demo/DemoHelper.kt b/app/src/main/java/com/tangem/tap/features/demo/DemoHelper.kt index 8f1038b60f..017a9a189e 100644 --- a/app/src/main/java/com/tangem/tap/features/demo/DemoHelper.kt +++ b/app/src/main/java/com/tangem/tap/features/demo/DemoHelper.kt @@ -87,13 +87,12 @@ class DemoConfig { val demoIds = (releaseDemoCardIds + testDemoCardIds).toMutableList() if (BuildConfig.DEBUG) demoIds.addAll(debugTestDemoCardIds) - return@lazy demoIds + return@lazy demoIds.distinct() } private val walletBalances: Map = mapOf( Blockchain.Bitcoin to Amount(0.028.toBigDecimal(), Blockchain.Bitcoin), Blockchain.Ethereum to Amount(0.2311.toBigDecimal(), Blockchain.Ethereum), - Blockchain.XRP to Amount(1248.56.toBigDecimal(), Blockchain.XRP), Blockchain.Dogecoin to Amount(1450.025.toBigDecimal(), Blockchain.Dogecoin), Blockchain.Solana to Amount(13.246.toBigDecimal(), Blockchain.Solana), ) @@ -108,17 +107,18 @@ class DemoConfig { ) private val testDemoCardIds = listOf( - "FB30000000000176", - "FB20000000000186", - "FB10000000000196", + "FB20000000000186", // Note ETH + "FB10000000000196", // Note BTC + "FB30000000000176", // Wallet + //TODO: delete bellow ids before 3.28 release + "AB01000000045060", // Note BTC + "AB02000000045028", // Note ETH + "AC79000000000004", // Wallet 4.46 ) private val debugTestDemoCardIds = listOf( - "AB06000000018575", // Note XRP - "AB04000000011036", // Note Doge "AB01000000045060", // Note BTC "AB02000000045028", // Note ETH - "AC01000000200003", // Wallet 4.52 "AC79000000000004", // Wallet 4.46 ) } @@ -147,7 +147,7 @@ class DemoTransactionSender( .joinToString("") } - companion object{ + companion object { val ID = DemoTransactionSender::class.java.simpleName } From 09d9c766bc83eb494b93421ec54ae7c5fabc0567 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 23 Feb 2022 13:13:55 +0300 Subject: [PATCH 14/16] Updated on 2026-08-14 --- .../onboarding/products/wallet/ui/OnboardingWalletFragment.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt index ef82fcd394..65d8a935a8 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt @@ -57,7 +57,6 @@ class OnboardingWalletFragment : Fragment(R.layout.fragment_onboarding_wallet), yTranslationFactor = 25f * deviceScaleFactor, ) val leapfrog = LeapfrogWidget(fl_cards_container, leapfrogCalculator) -// cardsWidget = BackupCardsWidget(leapfrog, deviceScaleFactor) { 200f * deviceScaleFactor } cardsWidget = WalletCardsWidget(leapfrog, deviceScaleFactor) { 200f * deviceScaleFactor } startPostponedEnterTransition() From 1b77a6782f6b153dae8c1355adc630f8819a7910 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 23 Feb 2022 13:28:00 +0300 Subject: [PATCH 15/16] Updated on 2026-08-14 --- app/src/main/res/layout/fragment_shop.xml | 2 +- app/src/main/res/values/strings_untranslated.xml | 12 ------------ 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/app/src/main/res/layout/fragment_shop.xml b/app/src/main/res/layout/fragment_shop.xml index ef4297ba3d..9ad04edbdd 100644 --- a/app/src/main/res/layout/fragment_shop.xml +++ b/app/src/main/res/layout/fragment_shop.xml @@ -26,7 +26,7 @@ android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:navigationIcon="@drawable/ic_clear_24" - app:title="@string/shop_title" + app:title="@string/home_button_order" app:titleCentered="true" /> diff --git a/app/src/main/res/values/strings_untranslated.xml b/app/src/main/res/values/strings_untranslated.xml index d52e9f1f7b..f746827108 100644 --- a/app/src/main/res/values/strings_untranslated.xml +++ b/app/src/main/res/values/strings_untranslated.xml @@ -331,16 +331,4 @@ Amount to pay: %s Please tell us more about your issue. Every small detail can help. Following information is optional. You can erase it if you don’t want to share it. - One Wallet - 3 cards - 2 cards - Shipping - Free - I have a promo code... - Total - Other payment methods - Buy now - Order card - Delivery (Free shipping) - From fa9cbfa791641083d8acf6f79bc16284a2618aff Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 23 Feb 2022 14:29:39 +0300 Subject: [PATCH 16/16] Updated on 2026-08-14 --- .../com/tangem/tap/domain/tokens/CurrenciesRepository.kt | 5 ++--- app/src/main/java/com/tangem/tap/features/demo/DemoHelper.kt | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/domain/tokens/CurrenciesRepository.kt b/app/src/main/java/com/tangem/tap/domain/tokens/CurrenciesRepository.kt index 4817a87b36..114746a06f 100644 --- a/app/src/main/java/com/tangem/tap/domain/tokens/CurrenciesRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/tokens/CurrenciesRepository.kt @@ -16,7 +16,7 @@ import com.tangem.tap.domain.extensions.setCustomIconUrl import com.tangem.tap.features.demo.DemoHelper import com.tangem.tap.network.createMoshi -open class CurrenciesRepository(val context: Application) { +class CurrenciesRepository(val context: Application) { private val moshi = createMoshi() private val blockchainsAdapter: JsonAdapter> = moshi.adapter( @@ -169,11 +169,10 @@ open class CurrenciesRepository(val context: Application) { return excludeUnsupportedBlockchains(blockchains) } - //TODO: move to the App settings private fun excludeUnsupportedBlockchains(blockchains: List): List { return blockchains.toMutableList().apply { removeAll(listOf( - Blockchain.Fantom, Blockchain.FantomTestnet +// Blockchain.Fantom, Blockchain.FantomTestnet )) } } diff --git a/app/src/main/java/com/tangem/tap/features/demo/DemoHelper.kt b/app/src/main/java/com/tangem/tap/features/demo/DemoHelper.kt index 017a9a189e..f80e04df6b 100644 --- a/app/src/main/java/com/tangem/tap/features/demo/DemoHelper.kt +++ b/app/src/main/java/com/tangem/tap/features/demo/DemoHelper.kt @@ -78,7 +78,6 @@ class DemoConfig { val demoBlockchains = listOf( Blockchain.Bitcoin, Blockchain.Ethereum, - Blockchain.XRP, Blockchain.Dogecoin, Blockchain.Solana, )