Updated on 2026-08-14

This commit is contained in:
Tangem 2022-07-11 11:36:59 +03:00
commit 35ea3aa2ec
29 changed files with 354 additions and 48 deletions

@ -1 +1 @@
Subproject commit 59ee0bff06ee54f3202421c28f7fb6e3d421dad8
Subproject commit f50133547b5e19fb7ad32e64370573d60f6791fd

View file

@ -22,6 +22,7 @@ import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.UnfinishedB
import com.tangem.tap.features.wallet.redux.WalletDialog
import com.tangem.tap.features.wallet.ui.dialogs.AmountToSendBottomSheetDialog
import com.tangem.tap.features.wallet.ui.dialogs.ChooseTradeActionBottomSheetDialog
import com.tangem.tap.features.wallet.ui.dialogs.RussianCardholdersWarningBottomSheetDialog
import com.tangem.tap.features.wallet.ui.dialogs.ScanFailsDialog
import com.tangem.tap.features.wallet.ui.dialogs.SignedHashesWarningDialog
import com.tangem.tap.features.wallet.ui.dialogs.SimpleOkDialog
@ -115,6 +116,8 @@ class DialogManager : StoreSubscriber<GlobalState> {
AmountToSendBottomSheetDialog(context, state.dialog)
is WalletDialog.SignedHashesMultiWalletDialog ->
SignedHashesWarningDialog.create(context)
is WalletDialog.RussianCardholdersWarningDialog ->
RussianCardholdersWarningBottomSheetDialog(context)
else -> null
}
dialog?.show()

View file

@ -85,4 +85,8 @@ sealed class GlobalAction : Action {
object Update : GlobalAction()
}
object FetchUserCountry : GlobalAction() {
data class Success(val countryCode: String) : GlobalAction()
}
}

View file

@ -4,13 +4,14 @@ import com.tangem.common.CompletionResult
import com.tangem.common.core.TangemSdkError
import com.tangem.common.extensions.guard
import com.tangem.common.extensions.ifNotNull
import com.tangem.common.services.Result
import com.tangem.domain.common.extensions.withMainContext
import com.tangem.tap.*
import com.tangem.tap.common.extensions.dispatchDebugErrorNotification
import com.tangem.tap.common.extensions.dispatchDialogShow
import com.tangem.tap.common.extensions.dispatchOnMain
import com.tangem.tap.common.redux.AppDialog
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.currenciesRepository
import com.tangem.tap.domain.configurable.warningMessage.WarningMessagesManager
import com.tangem.tap.features.send.redux.SendAction
import com.tangem.tap.features.wallet.redux.WalletAction
@ -18,6 +19,11 @@ import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager
import com.tangem.tap.network.exchangeServices.mercuryo.MercuryoApi
import com.tangem.tap.network.exchangeServices.mercuryo.MercuryoService
import com.tangem.tap.network.exchangeServices.moonpay.MoonPayService
import com.tangem.tap.preferencesStorage
import com.tangem.tap.scope
import com.tangem.tap.store
import com.tangem.tap.tangemSdkManager
import java.util.Locale
import kotlinx.coroutines.launch
import org.rekotlin.Action
import org.rekotlin.DispatchFunction
@ -134,5 +140,26 @@ private fun handleAction(action: Action, appState: () -> AppState?, dispatch: Di
}
}
}
is GlobalAction.FetchUserCountry -> {
scope.launch {
val techService = store.state.domainNetworks.tangemTechService
when (val result = techService.userCountry()) {
is Result.Success -> {
store.dispatch(
GlobalAction.FetchUserCountry.Success(
countryCode = result.data.code.lowercase()
)
)
}
is Result.Failure -> {
store.dispatch(
GlobalAction.FetchUserCountry.Success(
countryCode = Locale.getDefault().country.lowercase()
)
)
}
}
}
}
}
}

View file

@ -75,7 +75,9 @@ fun globalReducer(action: Action, state: AppState): GlobalState {
}
is GlobalAction.SetIfCardVerifiedOnline ->
globalState.copy(cardVerifiedOnline = action.verified)
is GlobalAction.FetchUserCountry.Success -> globalState.copy(
userCountryCode = action.countryCode
)
else -> globalState
}
}

View file

@ -28,6 +28,7 @@ data class GlobalState(
val exchangeManager: CurrencyExchangeManager? = null,
val resources: AndroidResources = AndroidResources(),
val analyticsHandlers: AnalyticsHandler? = null,
val userCountryCode: String? = null,
) : StateType

View file

@ -44,5 +44,7 @@ class TelephonyManagerRegionProvider(context: Context) : RegionProvider {
}
class LocaleRegionProvider : RegionProvider {
override fun getRegion(): String? = Locale.current.region
}
override fun getRegion(): String = Locale.current.region
}
const val RUSSIA_COUNTRY_CODE = "ru"

View file

@ -15,6 +15,7 @@ import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.common.redux.navigation.AppScreen
import com.tangem.tap.common.redux.navigation.FragmentShareTransition
import com.tangem.tap.common.redux.navigation.NavigationAction
import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE
import com.tangem.tap.features.home.redux.HomeMiddleware.Companion.BUY_WALLET_URL
import com.tangem.tap.features.onboarding.OnboardingHelper
import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsAction
@ -35,7 +36,7 @@ class HomeMiddleware {
}
}
private val homeMiddleware: Middleware<AppState> = { dispatch, state ->
private val homeMiddleware: Middleware<AppState> = { _, _ ->
{ next ->
{ action ->
when (action) {
@ -43,6 +44,7 @@ private val homeMiddleware: Middleware<AppState> = { dispatch, state ->
store.dispatch(GlobalAction.RestoreAppCurrency)
store.dispatch(GlobalAction.ExchangeManager.Init)
store.dispatch(HomeAction.SetTermsOfUseState(preferencesStorage.wasDisclaimerAccepted()))
store.dispatch(GlobalAction.FetchUserCountry)
}
is HomeAction.ShouldScanCardOnResume -> {
if (action.shouldScanCard) {
@ -55,8 +57,8 @@ private val homeMiddleware: Middleware<AppState> = { dispatch, state ->
// store.dispatch(NavigationAction.NavigateTo(AppScreen.AddCustomTokens))
}
is HomeAction.GoToShop -> {
when (action.regionProvider.getRegion()?.toLowerCase()) {
"ru" -> store.dispatchOpenUrl(BUY_WALLET_URL)
when (action.regionProvider.getRegion()?.lowercase()) {
RUSSIA_COUNTRY_CODE -> store.dispatchOpenUrl(BUY_WALLET_URL)
else -> store.dispatch(NavigationAction.NavigateTo(AppScreen.Shop))
}
store.state.globalState.analyticsHandlers?.triggerEvent(

View file

@ -145,6 +145,7 @@ sealed class WalletAction : Action {
object SignedHashesMultiWalletDialog : DialogAction()
object ChooseTradeActionDialog : DialogAction()
data class ChooseCurrency(val amounts: List<Amount>?) : DialogAction()
object RussianCardholdersWarningDialog : DialogAction()
object Hide : DialogAction()
}
@ -155,8 +156,10 @@ sealed class WalletAction : Action {
object EmptyWallet : WalletAction()
sealed class TradeCryptoAction : WalletAction() {
object Buy : TradeCryptoAction()
object Sell : TradeCryptoAction()
data class Buy(
val checkUserLocation: Boolean = true,
) : TradeCryptoAction()
data class FinishSelling(val transactionId: String) : TradeCryptoAction()
data class SendCrypto(
val currencyId: String,

View file

@ -1,7 +1,12 @@
package com.tangem.tap.features.wallet.redux
import android.graphics.Bitmap
import com.tangem.blockchain.common.*
import com.tangem.blockchain.common.Amount
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.DerivationStyle
import com.tangem.blockchain.common.Token
import com.tangem.blockchain.common.Wallet
import com.tangem.blockchain.common.WalletManager
import com.tangem.blockchain.common.address.AddressType
import com.tangem.common.extensions.isZero
import com.tangem.domain.common.extensions.canHandleToken
@ -17,15 +22,21 @@ import com.tangem.tap.domain.configurable.warningMessage.WarningMessage
import com.tangem.tap.domain.tokens.models.BlockchainNetwork
import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsState
import com.tangem.tap.features.tokens.redux.TokenWithBlockchain
import com.tangem.tap.features.wallet.models.*
import com.tangem.tap.features.wallet.models.PendingTransaction
import com.tangem.tap.features.wallet.models.TotalBalance
import com.tangem.tap.features.wallet.models.WalletRent
import com.tangem.tap.features.wallet.models.WalletWarning
import com.tangem.tap.features.wallet.models.hasPendingTransactions
import com.tangem.tap.features.wallet.models.hasSendableAmounts
import com.tangem.tap.features.wallet.models.isSendableAmount
import com.tangem.tap.features.wallet.redux.reducers.calculateTotalFiatAmount
import com.tangem.tap.features.wallet.redux.reducers.findProgressState
import com.tangem.tap.features.wallet.ui.BalanceStatus
import com.tangem.tap.features.wallet.ui.BalanceWidgetData
import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager
import com.tangem.tap.store
import org.rekotlin.StateType
import java.math.BigDecimal
import org.rekotlin.StateType
import kotlin.properties.ReadOnlyProperty
data class WalletState(
@ -317,6 +328,7 @@ sealed interface WalletDialog : StateDialog {
val currenciesList: List<FiatCurrency>,
val currentAppCurrency: FiatCurrency,
) : WalletDialog
object RussianCardholdersWarningDialog : WalletDialog
}
enum class ProgressState : WidgetState { Loading, Refreshing, Done, Error }

View file

@ -8,6 +8,7 @@ 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.features.demo.DemoHelper
import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE
import com.tangem.tap.features.send.redux.PrepareSendScreen
import com.tangem.tap.features.send.redux.SendAction
import com.tangem.tap.features.wallet.redux.Currency
@ -24,33 +25,34 @@ class TradeCryptoMiddleware {
if (DemoHelper.tryHandle(state, action)) return
when (action) {
is WalletAction.TradeCryptoAction.Buy -> startExchange(action)
is WalletAction.TradeCryptoAction.Sell -> startExchange(action)
is WalletAction.TradeCryptoAction.Buy -> proceedBuyAction(state, action)
is WalletAction.TradeCryptoAction.Sell -> proceedSellAction()
is WalletAction.TradeCryptoAction.SendCrypto -> preconfigureAndOpenSendScreen(action)
is WalletAction.TradeCryptoAction.FinishSelling -> openReceiptUrl(action.transactionId)
}
}
private fun startExchange(action: WalletAction.TradeCryptoAction) {
val selectedWalletData = store.state.walletState.getSelectedWalletData()
val exchangeManager = store.state.globalState.exchangeManager ?: return
val addresses = selectedWalletData?.walletAddresses ?: return
if (addresses.list.isEmpty()) return
val appCurrency = store.state.globalState.appCurrency
val defaultAddress = addresses.list[0].address
val currency = selectedWalletData.currency
val currencySymbol = selectedWalletData.currency.currencySymbol
val exchangeAction = if (action is WalletAction.TradeCryptoAction.Buy) {
CurrencyExchangeManager.Action.Buy
} else {
CurrencyExchangeManager.Action.Sell
private fun proceedBuyAction(
state: () -> AppState?,
action: WalletAction.TradeCryptoAction.Buy,
) {
if (action.checkUserLocation && state()?.globalState?.userCountryCode == RUSSIA_COUNTRY_CODE) {
store.dispatchOnMain(
WalletAction.DialogAction.RussianCardholdersWarningDialog
)
return
}
if (exchangeAction == CurrencyExchangeManager.Action.Buy &&
currency is Currency.Token && currency.blockchain.isTestnet()
) {
val selectedWalletData = store.state.walletState.getSelectedWalletData() ?: return
val exchangeManager = store.state.globalState.exchangeManager ?: return
val appCurrency = store.state.globalState.appCurrency
val addresses = selectedWalletData.walletAddresses?.list.orEmpty()
if (addresses.isEmpty()) return
val currency = selectedWalletData.currency
if (currency is Currency.Token && currency.blockchain.isTestnet()) {
val walletManager = store.state.walletState.getWalletManager(currency)
if (walletManager !is EthereumWalletManager) {
store.dispatchDebugErrorNotification("Testnet tokens available only for the Ethereum")
@ -62,13 +64,31 @@ class TradeCryptoMiddleware {
}
exchangeManager.getUrl(
action = exchangeAction,
action = CurrencyExchangeManager.Action.Buy,
blockchain = currency.blockchain,
cryptoCurrencyName = currencySymbol,
cryptoCurrencyName = currency.currencySymbol,
fiatCurrencyName = appCurrency.code,
walletAddress = defaultAddress
walletAddress = addresses[0].address
)?.let { store.dispatchOnMain(NavigationAction.OpenUrl(it)) }
}
private fun proceedSellAction() {
val selectedWalletData = store.state.walletState.getSelectedWalletData() ?: return
val exchangeManager = store.state.globalState.exchangeManager ?: return
val appCurrency = store.state.globalState.appCurrency
val addresses = selectedWalletData.walletAddresses?.list.orEmpty()
if (addresses.isEmpty()) return
val currency = selectedWalletData.currency
exchangeManager.getUrl(
action = CurrencyExchangeManager.Action.Sell,
blockchain = currency.blockchain,
cryptoCurrencyName = currency.currencySymbol,
fiatCurrencyName = appCurrency.code,
walletAddress = addresses[0].address
)?.let { store.dispatchOnMain(NavigationAction.OpenUrl(it)) }
}
private fun preconfigureAndOpenSendScreen(action: WalletAction.TradeCryptoAction.SendCrypto) {

View file

@ -27,10 +27,13 @@ class WalletDialogsMiddleware {
is WalletAction.DialogAction.ChooseCurrency -> {
store.dispatchDialogShow(
WalletDialog.SelectAmountToSendDialog(
amounts = action.amounts
amounts = action.amounts
)
)
}
is WalletAction.DialogAction.RussianCardholdersWarningDialog -> {
store.dispatchDialogShow(WalletDialog.RussianCardholdersWarningDialog)
}
is WalletAction.DialogAction.Hide -> {
store.dispatchDialogHide()
}

View file

@ -91,7 +91,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details),
private fun setupButtons() = with(binding) {
rowButtons.onBuyClick = {
store.dispatch(WalletAction.TradeCryptoAction.Buy)
store.dispatch(WalletAction.TradeCryptoAction.Buy())
}
rowButtons.onSellClick = {
store.dispatch(WalletAction.TradeCryptoAction.Sell)

View file

@ -27,7 +27,7 @@ class ChooseTradeActionBottomSheetDialog(context: Context) : BottomSheetDialog(c
}
binding!!.dialogBtnBuy.setOnClickListener {
store.dispatch(WalletAction.TradeCryptoAction.Buy)
store.dispatch(WalletAction.TradeCryptoAction.Buy())
dismiss()
}
binding!!.dialogBtnSell.setOnClickListener {

View file

@ -0,0 +1,44 @@
package com.tangem.tap.features.wallet.ui.dialogs
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.tangem.tap.common.extensions.dispatchDialogHide
import com.tangem.tap.common.redux.navigation.NavigationAction
import com.tangem.tap.features.wallet.redux.WalletAction
import com.tangem.tap.store
import com.tangem.wallet.databinding.DialogRussiansCardholdersWarningBinding
class RussianCardholdersWarningBottomSheetDialog(context: Context) : BottomSheetDialog(context) {
private var binding: DialogRussiansCardholdersWarningBinding? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DialogRussiansCardholdersWarningBinding
.inflate(LayoutInflater.from(context))
.also { setContentView(it.root) }
}
override fun show() {
super.show()
setOnDismissListener {
binding = null
store.dispatchDialogHide()
}
binding?.btnYes?.setOnClickListener {
store.dispatch(WalletAction.TradeCryptoAction.Buy(checkUserLocation = false))
dismiss()
}
binding?.btnNo?.setOnClickListener {
store.dispatch(NavigationAction.OpenUrl(INSTRUCTION_URL))
dismiss()
}
}
companion object {
private const val INSTRUCTION_URL = "https://tangem.com/howtobuy.html"
}
}

View file

@ -149,7 +149,7 @@ class SingleWalletView : WalletView {
val allowedToBuy = tradeCryptoState.isAvailableToBuy()
val allowedToSell = tradeCryptoState.isAvailableToSell()
val action = when {
allowedToBuy && !allowedToSell -> WalletAction.TradeCryptoAction.Buy
allowedToBuy && !allowedToSell -> WalletAction.TradeCryptoAction.Buy()
!allowedToBuy && allowedToSell -> WalletAction.TradeCryptoAction.Sell
allowedToBuy && allowedToSell -> WalletAction.DialogAction.ChooseTradeActionDialog
else -> null

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="22"
android:viewportHeight="22">
<path
android:fillColor="#000"
android:pathData="M16.3,16.3C16.7,15.9 16.7,15.3 16.3,14.9L12.4,11L16.3,7.1C16.7,6.7 16.7,6.1 16.3,5.7C15.9,5.3 15.3,5.3 14.9,5.7L11,9.6L7.1,5.7C6.7,5.3 6.1,5.3 5.7,5.7C5.3,6.1 5.3,6.7 5.7,7.1L9.6,11L5.7,14.9C5.3,15.3 5.3,15.9 5.7,16.3C6.1,16.7 6.7,16.7 7.1,16.3L11,12.4L14.9,16.3C15.3,16.7 15.9,16.7 16.3,16.3Z" />
</vector>

View file

@ -0,0 +1,18 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="60"
android:viewportHeight="60">
<group>
<clip-path android:pathData="M0,0h60v60h-60z" />
<path
android:fillColor="#F0F0F0"
android:pathData="M30,60C46.569,60 60,46.569 60,30C60,13.432 46.569,0 30,0C13.432,0 0,13.432 0,30C0,46.569 13.432,60 30,60Z" />
<path
android:fillColor="#0052B4"
android:pathData="M58.134,40.435C59.34,37.185 60,33.67 60,30C60,26.33 59.34,22.815 58.134,19.565H1.866C0.66,22.815 0,26.33 0,30C0,33.67 0.66,37.185 1.866,40.435L30,43.044L58.134,40.435Z" />
<path
android:fillColor="#D80027"
android:pathData="M30,60C42.899,60 53.895,51.859 58.134,40.435H1.866C6.105,51.859 17.101,60 30,60Z" />
</group>
</vector>

View file

@ -0,0 +1,114 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/backgroundWhite"
android:minHeight="420dp"
tools:layout_gravity="bottom">
<ImageView
android:id="@+id/iv_flag"
android:layout_width="68dp"
android:layout_height="68dp"
android:contentDescription="@null"
android:src="@drawable/img_flag_ru_24"
app:layout_constraintBottom_toTopOf="@id/tv_title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed" />
<View
android:id="@+id/view_cross_outline"
android:layout_width="32dp"
android:layout_height="32dp"
android:background="@drawable/shape_circle"
android:backgroundTint="@color/backgroundWhite"
app:layout_constraintBottom_toBottomOf="@id/iv_cross"
app:layout_constraintEnd_toEndOf="@id/iv_cross"
app:layout_constraintStart_toStartOf="@id/iv_cross"
app:layout_constraintTop_toTopOf="@id/iv_cross" />
<ImageView
android:id="@+id/iv_cross"
android:layout_width="28dp"
android:layout_height="28dp"
android:layout_marginEnd="-4dp"
android:layout_marginBottom="-4dp"
android:background="@drawable/shape_circle"
android:backgroundTint="#FFEBEE"
android:contentDescription="@null"
android:scaleType="center"
android:src="@drawable/ic_cross_rounded_24"
app:layout_constraintBottom_toBottomOf="@id/iv_flag"
app:layout_constraintEnd_toEndOf="@id/iv_flag"
app:tint="#D80027" />
<TextView
android:id="@+id/tv_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="38dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="38dp"
android:text="@string/russian_bank_card_warning_title"
android:textAlignment="center"
android:textColor="@color/textBlack"
android:textSize="20sp"
app:layout_constraintBottom_toTopOf="@id/tv_description"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/iv_flag" />
<TextView
android:id="@+id/tv_description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="38dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="38dp"
android:layout_marginBottom="38dp"
android:text="@string/russian_bank_card_warning_subtitle"
android:textAlignment="center"
android:textColor="@color/textBlack"
android:textSize="14sp"
app:layout_constraintBottom_toTopOf="@id/btn_yes"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintVertical_bias="0" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_yes"
style="@style/OnboardingButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="6dp"
android:layout_marginBottom="38dp"
android:backgroundTint="@color/tapButtonColorBlack"
android:text="@string/common_yes"
android:textColor="@color/white"
app:cornerRadius="14dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/btn_no"
app:layout_constraintStart_toStartOf="parent" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_no"
style="@style/OnboardingButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_marginEnd="16dp"
android:backgroundTint="@color/buttonGray"
android:text="@string/common_no"
android:textColor="@color/textBlack"
app:cornerRadius="14dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/btn_yes"
app:layout_constraintTop_toTopOf="@id/btn_yes" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="common_no">Nein</string>
<string name="common_save_changes">Änderungen speichern</string>
<string name="common_warning">Warnung</string>
<string name="common_retry">Erneut versuchen</string>
@ -196,4 +195,4 @@ RECHTLICHER HAFTUNGSAUSSCHLUSS
<string name="xtz_withdrawal_message_reduce">Um %s XTZ reduzieren</string>
<string name="xtz_withdrawal_message_ignore">Nein, alles senden</string>
</resources>
</resources>

View file

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="common_no">Non </string>
<string name="common_save_changes">Sauvegarder les modifications </string>
<string name="common_warning"> Alerte </string>
<string name="common_retry"> Réessayer </string>
@ -188,4 +187,4 @@ Avertissement
<string name="xtz_withdrawal_message_reduce">Réduire de% s XTZ</string>
<string name="xtz_withdrawal_message_ignore">Non, envoyer toute la somme</string>
</resources>
</resources>

View file

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="common_no">No</string>
<string name="common_save_changes">Mantieni le modifiche</string>
<string name="common_warning">Avviso</string>
<string name="common_retry">Riprova</string>
@ -195,4 +194,4 @@ Questa nota legale è stata modificata l\'ultima volta 01.10.2020.
<string name="xtz_withdrawal_message_reduce">Riduci di %s XTZ</string>
<string name="xtz_withdrawal_message_ignore">No, invia l\'intero importo</string>
</resources>
</resources>

View file

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<string name="app_name">Tangem</string>
<string name="common_no">Нет</string>
<string name="common_save_changes">Сохранить изменения</string>
<string name="common_warning">Предупреждение</string>
<string name="common_retry">Повторить попытку</string>
@ -382,4 +381,5 @@
<string name="feedback_preface_support">Привет, команда поддержки,</string>
<string name="feedback_preface_tx_push_failed">Пожалуйста, расскажите нам больше о Вашей проблеме. Каждая деталь может быть полезной.</string>
<string name="feedback_data_collection_message">Информация ниже не является обязательной. Вы можете стереть её, если хотите.</string>
<string name="common_no">Нет</string>
</resources>

View file

@ -50,4 +50,21 @@
<string name="main_processing_full_amount">В сумме учтены не все монеты</string>
<string name="main_manage_tokens">Управление токенами</string>
<string name="token_item_no_rate">Нет цены</string>
<string name="token_details_hide_token">Скрыть токен</string>
<string name="token_details_hide_alert_title">Скрыть %s</string>
<string name="token_details_hide_alert_hide">Скрыть</string>
<string name="token_details_hide_alert_message">Вы скрываете токен с главного экрана, но в любой момент сможете добавить его обратно.</string>
<string name="token_details_unable_hide_alert_title">Невозможно скрыть %s</string>
<string name="token_details_unable_hide_alert_message">Токен %s является основной валютой в сети %s и не может быть скрыт, до тех пор пока у вас в списке есть другие токены этой сети.</string>
<string name="wallet_connect_network_not_found_format">Сеть %s не найдена. Пожалуйста, добавьте её и попробуйте заново.</string>
<string name="wallet_currency_subtitle">Сеть %s</string>
<string name="main_no_backup_warning_title">Бэкап кошелька не был произведен</string>
<string name="main_no_backup_warning_subtitle">Чтобы защитить свои активы, мы советуем вам выполнить эту процедуру</string>
<string name="russian_bank_card_warning_title">Карты банков РФ в данный момент не принимаются</string>
<string name="russian_bank_card_warning_subtitle">У вас есть карта банка другой страны или платежной системы UnionPay?</string>
<string name="common_yes">Да</string>
</resources>

View file

@ -2,7 +2,6 @@
<string name="app_name" translatable="false">Tangem</string>
<string name="common_no">No</string>
<string name="common_save_changes">Save changes</string>
<string name="common_warning">Warning</string>
<string name="common_retry">Retry</string>

View file

@ -50,4 +50,23 @@
<string name="main_processing_full_amount">The amount does not include some of your funds</string>
<string name="main_manage_tokens">Manage tokens</string>
<string name="token_item_no_rate">No rate</string>
<string name="token_details_hide_token">Hide token</string>
<string name="token_details_hide_alert_title">Hide %s</string>
<string name="token_details_hide_alert_hide">Hide</string>
<string name="token_details_hide_alert_message">You are about to hide this token from the main screen. You can add it back anytime.</string>
<string name="token_details_unable_hide_alert_title">Unable to hide %s</string>
<string name="token_details_unable_hide_alert_message">The %s token is the main currency on the %s network and cannot be hidden as long as you have other tokens on this network in the list.</string>
<string name="wallet_connect_network_not_found_format">%s network not found. Please, add it first and try again.</string>
<string name="wallet_currency_subtitle">%s network</string>
<string name="main_no_backup_warning_title">Your wallet has not been backed up</string>
<string name="main_no_backup_warning_subtitle">To protect your assets, we advise you to carry out this procedure</string>
<string name="wallet_hide_token" translatable="false">Remove token</string>
<string name="russian_bank_card_warning_title">Russian bank cards are not accepted at the moment</string>
<string name="russian_bank_card_warning_subtitle">Do you have a bank card of another country or a UnionPay card?</string>
<string name="common_yes">Yes</string>
<string name="common_no">No</string>
</resources>

View file

@ -43,4 +43,8 @@ data class CurrenciesResponse(val currencies: List<Currency>) {
val unit: String, // $, €, ₽
val type: String,
) : TangemTechResponse
}
}
data class GeoResponse(
val code: String
) : TangemTechResponse

View file

@ -27,4 +27,6 @@ interface TangemTechApi {
@GET("currencies")
suspend fun currencies(): CurrenciesResponse
@GET("geo")
suspend fun geo(): GeoResponse
}

View file

@ -47,6 +47,10 @@ class TangemTechService {
}
}
suspend fun userCountry(): Result<GeoResponse> = withContext(Dispatchers.IO) {
performRequest { api.geo() }
}
suspend fun currencies(): Result<CurrenciesResponse> = withContext(Dispatchers.IO) {
performRequest { api.currencies() }
}