Updated on 2026-08-14

This commit is contained in:
Tangem 2022-12-23 20:34:08 +04:00
parent d17f046b06
commit fdd2b563bd
121 changed files with 2218 additions and 1594 deletions

View file

@ -3,6 +3,7 @@ package com.tangem.tap.common
import android.content.Intent
import android.nfc.NfcAdapter
import android.nfc.Tag
import com.tangem.tap.common.extensions.removePrefixOrNull
import com.tangem.tap.common.redux.navigation.AppScreen
import com.tangem.tap.common.redux.navigation.NavigationAction
import com.tangem.tap.domain.walletconnect.WalletConnectManager
@ -14,14 +15,20 @@ import timber.log.Timber
class IntentHandler {
private val TRANSACTION_ID_PARAM = "transactionId"
private val CURRENCY_CODE_PARAM = "baseCurrencyCode"
private val CURRENCY_AMOUNT_PARAM = "baseCurrencyAmount"
private val DEPOSIT_WALLET_ADDRESS_PARAM = "depositWalletAddress"
fun handleWalletConnectLink(intent: Intent?) {
if (intent?.scheme == WalletConnectManager.WC_SCHEME) {
store.dispatch(WalletConnectAction.HandleDeepLink(intent.data?.toString()))
val wcUri = when (intent?.scheme) {
WalletConnectManager.WC_SCHEME -> {
intent.data?.toString()
}
TANGEM_SCHEME -> {
intent.data?.toString()?.removePrefixOrNull(TANGEM_WC_PREFIX)
}
else -> {
null
}
}
if (wcUri != null) {
store.dispatch(WalletConnectAction.HandleDeepLink(wcUri))
}
}
@ -54,16 +61,25 @@ class IntentHandler {
Timber.d("MoonPay Sell: $amount $currency to $destinationAddress")
store.dispatch(WalletAction.TradeCryptoAction.SendCrypto(
currencyId = currency,
amount = amount,
destinationAddress = destinationAddress,
transactionId = transactionID
))
store.dispatch(
WalletAction.TradeCryptoAction.SendCrypto(
currencyId = currency,
amount = amount,
destinationAddress = destinationAddress,
transactionId = transactionID,
),
)
} catch (exception: Exception) {
Timber.d("Not MoonPay URL")
}
}
companion object {
private const val TRANSACTION_ID_PARAM = "transactionId"
private const val CURRENCY_CODE_PARAM = "baseCurrencyCode"
private const val CURRENCY_AMOUNT_PARAM = "baseCurrencyAmount"
private const val DEPOSIT_WALLET_ADDRESS_PARAM = "depositWalletAddress"
private const val TANGEM_SCHEME = "tangem"
private const val TANGEM_WC_PREFIX = "tangem://wc?uri="
}
}

View file

@ -25,7 +25,7 @@ class BasicSignInEventConverter(
val cardCurrency = ParamCardCurrencyConverter().convert(scanResponse) ?: return null
return Basic.SignedIn(
state = AnalyticsParam.CardBalanceState.from(value.walletsData),
state = AnalyticsParam.CardBalanceState.from(value.walletsDataFromStores),
currency = cardCurrency,
batch = scanResponse.card.batchId,
).apply {
@ -44,7 +44,7 @@ class BasicTopUpEventConverter(
val data = BasicTopUpFilter.Data(
walletId = scanResponse.card.userWalletId.stringValue,
cardBalanceState = AnalyticsParam.CardBalanceState.from(value.walletsData),
cardBalanceState = AnalyticsParam.CardBalanceState.from(value.walletsDataFromStores),
)
return Basic.ToppedUp(cardCurrency).apply { filterData = data }
@ -61,16 +61,16 @@ private fun AnalyticsParam.CardBalanceState.Companion.from(walletsData: List<Wal
private fun statesIsReadyToCreateEvent(scanResponse: ScanResponse, state: WalletState): Boolean {
if (scanResponse.card.isMultiwalletAllowed && state.missingDerivations.isNotEmpty()) return false
if (state.walletsData.isEmpty()) return false
if (state.walletsDataFromStores.isEmpty()) return false
val totalBalanceState = state.totalBalance?.state ?: return false
if (totalBalanceState == ProgressState.Loading || totalBalanceState == ProgressState.Refreshing) return false
val balancesCount = state.walletsData.map {
val balancesCount = state.walletsDataFromStores.map {
if (it.currencyData.amount == null) 0 else 1
}.reduce { acc, i -> acc + i }
if (balancesCount != state.wallets.size) return false
if (balancesCount != state.walletsStores.size) return false
return true
}

View file

@ -62,4 +62,9 @@ fun String.toQrCode(): Bitmap {
return bmp
}
fun String.urlEncode(): String = Uri.encode(this)
fun String.urlEncode(): String = Uri.encode(this)
fun String.removePrefixOrNull(prefix: String): String? = when {
startsWith(prefix) -> substring(prefix.length)
else -> null
}

View file

@ -0,0 +1,27 @@
package com.tangem.tap.common.redux
import com.tangem.domain.common.ScanResponse
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.preferencesStorage
import com.tangem.tap.tangemSdkManager
import org.rekotlin.Middleware
class AccessCodeRequestPolicyMiddleware {
val middleware: Middleware<AppState> = { _, _ ->
{ next ->
{ action ->
if (action is GlobalAction.SaveScanResponse) {
updateAccessCodeRequestPolicy(action.scanResponse)
}
next(action)
}
}
}
private fun updateAccessCodeRequestPolicy(scanResponse: ScanResponse) {
tangemSdkManager.setAccessCodeRequestPolicy(
useBiometricsForAccessCode = preferencesStorage.shouldSaveAccessCodes &&
scanResponse.card.isAccessCodeSet,
)
}
}

View file

@ -93,6 +93,7 @@ data class AppState(
SaveWalletMiddleware().middleware,
WalletSelectorMiddleware().middleware,
LockUserWalletsTimerMiddleware().middleware,
AccessCodeRequestPolicyMiddleware().middleware,
)
}
}

View file

@ -64,7 +64,7 @@ sealed class GlobalAction : Action {
object Increment : GlobalAction()
}
data class SaveScanNoteResponse(val scanResponse: ScanResponse) : GlobalAction()
data class SaveScanResponse(val scanResponse: ScanResponse) : GlobalAction()
data class SetIfCardVerifiedOnline(val verified: Boolean) : GlobalAction()

View file

@ -33,7 +33,7 @@ fun globalReducer(action: Action, state: AppState, appStateHolder: AppStateHolde
is GlobalAction.ScanFailsCounter.Reset -> {
globalState.copy(scanCardFailsCounter = 0)
}
is GlobalAction.SaveScanNoteResponse -> {
is GlobalAction.SaveScanResponse -> {
appStateHolder.scanResponse = action.scanResponse
domainStore.dispatch(DomainGlobalAction.SaveScanNoteResponse(action.scanResponse))
globalState.copy(scanResponse = action.scanResponse)

View file

@ -28,15 +28,17 @@ val navigationMiddleware: Middleware<AppState> = { _, state ->
)
}
is NavigationAction.PopBackTo -> {
when (val screen = action.screen) {
AppScreen.Home,
AppScreen.Welcome,
-> {
navState?.activity?.get()?.popBackTo(screen, inclusive = true)
store.dispatchOnMain(NavigationAction.NavigateTo(screen))
}
else -> {
navState?.activity?.get()?.popBackTo(screen, action.inclusive)
if (navState?.backStack?.lastOrNull() != action.screen) {
when (val screen = action.screen) {
AppScreen.Home,
AppScreen.Welcome,
-> {
navState?.activity?.get()?.popBackTo(screen, inclusive = true)
store.dispatchOnMain(NavigationAction.NavigateTo(screen))
}
else -> {
navState?.activity?.get()?.popBackTo(screen, action.inclusive)
}
}
}
}

View file

@ -20,6 +20,8 @@ private fun internalReduce(action: Action, state: AppState): NavigationState {
navState.copy(backStack = navState.backStack + navigationAction.screen)
}
is NavigationAction.PopBackTo -> {
if (navState.backStack.lastOrNull() == navigationAction.screen) return navState
val screen = navigationAction.screen ?: navState.activity?.get()?.getPreviousScreen()
val index = navState.backStack.lastIndexOf(screen) + 1
state.navigationState.copy(backStack = navState.backStack.subList(0, index))

View file

@ -208,8 +208,8 @@ class TangemShopService(application: Application, shopifyShop: ShopifyShop) {
}
companion object {
const val TANGEM_WALLET_2_CARDS_SKU = "TG115x2"
const val TANGEM_WALLET_3_CARDS_SKU = "TG115x3"
const val TANGEM_WALLET_2_CARDS_SKU = "TG115X2-S"
const val TANGEM_WALLET_3_CARDS_SKU = "TG115X3-S"
val SKUS_TO_DISPLAY = listOf(TANGEM_WALLET_2_CARDS_SKU, TANGEM_WALLET_3_CARDS_SKU)
}
}