Updated on 2026-08-14
This commit is contained in:
commit
27f43629fa
29 changed files with 187 additions and 271 deletions
|
|
@ -1,18 +1,18 @@
|
|||
package com.tangem.tap
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import coil.ImageLoader
|
||||
import coil.ImageLoaderFactory
|
||||
import com.appsflyer.AppsFlyerLib
|
||||
import com.google.firebase.ktx.Firebase
|
||||
import com.google.firebase.remoteconfig.ktx.remoteConfig
|
||||
import com.google.firebase.remoteconfig.ktx.remoteConfigSettings
|
||||
import com.tangem.Log
|
||||
import com.tangem.LogFormat
|
||||
import com.tangem.blockchain.network.BlockchainSdkRetrofitBuilder
|
||||
import com.tangem.domain.DomainLayer
|
||||
import com.tangem.domain.common.LogConfig
|
||||
import com.tangem.network.common.MoshiConverter
|
||||
import com.tangem.tap.common.AndroidAssetReader
|
||||
import com.tangem.tap.common.analytics.GlobalAnalyticsHandler
|
||||
import com.tangem.tap.common.feedback.AdditionalFeedbackInfo
|
||||
import com.tangem.tap.common.feedback.FeedbackManager
|
||||
|
|
@ -22,10 +22,9 @@ import com.tangem.tap.common.redux.AppState
|
|||
import com.tangem.tap.common.redux.appReducer
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.common.shop.TangemShopService
|
||||
import com.tangem.tap.domain.configurable.config.Config
|
||||
import com.tangem.tap.domain.configurable.config.ConfigManager
|
||||
import com.tangem.tap.domain.configurable.config.FeaturesLocalLoader
|
||||
import com.tangem.tap.domain.configurable.config.FeaturesRemoteLoader
|
||||
import com.tangem.tap.domain.configurable.warningMessage.RemoteWarningLoader
|
||||
import com.tangem.tap.domain.configurable.warningMessage.WarningMessagesManager
|
||||
import com.tangem.tap.domain.tokens.CurrenciesRepository
|
||||
import com.tangem.tap.domain.walletconnect.WalletConnectRepository
|
||||
|
|
@ -38,7 +37,7 @@ import timber.log.Timber
|
|||
val store = Store(
|
||||
reducer = ::appReducer,
|
||||
middleware = AppState.getMiddleware(),
|
||||
state = AppState()
|
||||
state = AppState(),
|
||||
)
|
||||
|
||||
lateinit var foregroundActivityObserver: ForegroundActivityObserver
|
||||
|
|
@ -49,36 +48,28 @@ lateinit var walletConnectRepository: WalletConnectRepository
|
|||
lateinit var shopService: TangemShopService
|
||||
|
||||
class TapApplication : Application(), ImageLoaderFactory {
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
||||
DomainLayer.init()
|
||||
if (BuildConfig.DEBUG) {
|
||||
Timber.plant(Timber.DebugTree())
|
||||
Firebase.remoteConfig.setConfigSettingsAsync(remoteConfigSettings {
|
||||
this.minimumFetchIntervalInSeconds = 60
|
||||
})
|
||||
} else {
|
||||
Firebase.remoteConfig.setConfigSettingsAsync(remoteConfigSettings {
|
||||
this.minimumFetchIntervalInSeconds = 3600
|
||||
})
|
||||
}
|
||||
|
||||
NetworkConnectivity.createInstance(store, this)
|
||||
preferencesStorage = PreferencesStorage(this)
|
||||
currenciesRepository = CurrenciesRepository(
|
||||
this, store.state.domainNetworks.tangemTechService
|
||||
)
|
||||
walletConnectRepository = WalletConnectRepository(this)
|
||||
|
||||
foregroundActivityObserver = ForegroundActivityObserver()
|
||||
registerActivityLifecycleCallbacks(foregroundActivityObserver.callbacks)
|
||||
initFeedbackManager()
|
||||
loadConfigs()
|
||||
|
||||
DomainLayer.init()
|
||||
NetworkConnectivity.createInstance(store, this)
|
||||
preferencesStorage = PreferencesStorage(this)
|
||||
currenciesRepository = CurrenciesRepository(this, store.state.domainNetworks.tangemTechService)
|
||||
walletConnectRepository = WalletConnectRepository(this)
|
||||
|
||||
val configLoader = FeaturesLocalLoader(AndroidAssetReader(this), MoshiConverter.defaultMoshi())
|
||||
initConfigManager(configLoader, ::initWithConfigDependency)
|
||||
initWarningMessagesManager()
|
||||
|
||||
BlockchainSdkRetrofitBuilder.enableNetworkLogging = LogConfig.network.blockchainSdkNetwork
|
||||
|
||||
initAppsFlyer()
|
||||
}
|
||||
|
||||
override fun newImageLoader(): ImageLoader {
|
||||
|
|
@ -88,64 +79,71 @@ class TapApplication : Application(), ImageLoaderFactory {
|
|||
)
|
||||
}
|
||||
|
||||
private fun loadConfigs() {
|
||||
val moshi = MoshiConverter.defaultMoshi()
|
||||
val localLoader = FeaturesLocalLoader(this, moshi)
|
||||
val remoteLoader = FeaturesRemoteLoader(moshi)
|
||||
val configManager = ConfigManager(localLoader, remoteLoader)
|
||||
configManager.load { config ->
|
||||
private fun initConfigManager(loader: FeaturesLocalLoader, onComplete: (Config) -> Unit) {
|
||||
val configManager = ConfigManager()
|
||||
configManager.load(loader) { config ->
|
||||
store.dispatch(GlobalAction.SetConfigManager(configManager))
|
||||
shopService = TangemShopService(
|
||||
application = this,
|
||||
shopifyShop = config.shopify!!
|
||||
)
|
||||
store.state.globalState.feedbackManager?.initChat(
|
||||
context = this,
|
||||
zendeskConfig = config.zendesk!!
|
||||
)
|
||||
onComplete(config)
|
||||
}
|
||||
val warningsManager = WarningMessagesManager(RemoteWarningLoader(moshi))
|
||||
warningsManager.load { store.dispatch(GlobalAction.SetWarningManager(warningsManager)) }
|
||||
}
|
||||
|
||||
private fun initFeedbackManager() {
|
||||
val infoHolder = AdditionalFeedbackInfo()
|
||||
infoHolder.setAppVersion(this)
|
||||
|
||||
val logLevels = listOf(
|
||||
Log.Level.ApduCommand,
|
||||
Log.Level.Apdu,
|
||||
Log.Level.Tlv,
|
||||
Log.Level.Nfc,
|
||||
Log.Level.Command,
|
||||
Log.Level.Session,
|
||||
Log.Level.View,
|
||||
Log.Level.Network,
|
||||
Log.Level.Error,
|
||||
)
|
||||
val logWriter = TangemLogCollector(
|
||||
levels = logLevels,
|
||||
messageFormatter = LogFormat.StairsFormatter(),
|
||||
)
|
||||
Log.addLogger(logWriter)
|
||||
|
||||
store.dispatch(
|
||||
GlobalAction.SetFeedbackManager(
|
||||
FeedbackManager(
|
||||
infoHolder = infoHolder,
|
||||
logCollector = logWriter,
|
||||
preferencesStorage = preferencesStorage,
|
||||
logEnabled = LogConfig.zendesk,
|
||||
),
|
||||
),
|
||||
)
|
||||
private fun initWithConfigDependency(config: Config) {
|
||||
shopService = TangemShopService(this, config.shopify!!)
|
||||
initAppsFlyer(this, config)
|
||||
initFeedbackManager(this, preferencesStorage, config)
|
||||
}
|
||||
|
||||
private fun initAppsFlyer() {
|
||||
val devKey = store.state.globalState.configManager?.config?.appsFlyerDevKey ?: return
|
||||
AppsFlyerLib.getInstance().init(devKey, null, this)
|
||||
AppsFlyerLib.getInstance().start(this)
|
||||
val analyticsHandler = GlobalAnalyticsHandler.createDefaultAnalyticHandlers(this)
|
||||
private fun initAppsFlyer(context: Context, config: Config) {
|
||||
AppsFlyerLib.getInstance().init(config.appsFlyerDevKey, null, context)
|
||||
AppsFlyerLib.getInstance().start(context)
|
||||
val analyticsHandler = GlobalAnalyticsHandler.createDefaultAnalyticHandlers(context)
|
||||
store.dispatch(GlobalAction.SetAnanlyticHandlers(analyticsHandler))
|
||||
}
|
||||
|
||||
private fun initFeedbackManager(context: Context, preferencesStorage: PreferencesStorage, config: Config) {
|
||||
fun initAdditionalFeedbackInfo(context: Context): AdditionalFeedbackInfo = AdditionalFeedbackInfo().apply {
|
||||
appVersion = try {
|
||||
val pInfo = context.packageManager.getPackageInfo(context.packageName, 0)
|
||||
pInfo.versionName
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
e.printStackTrace()
|
||||
"x.y.z"
|
||||
}
|
||||
}
|
||||
|
||||
fun initTangemLogCollector(): TangemLogCollector {
|
||||
val logLevels = listOf(
|
||||
Log.Level.ApduCommand,
|
||||
Log.Level.Apdu,
|
||||
Log.Level.Tlv,
|
||||
Log.Level.Nfc,
|
||||
Log.Level.Command,
|
||||
Log.Level.Session,
|
||||
Log.Level.View,
|
||||
Log.Level.Network,
|
||||
Log.Level.Error,
|
||||
)
|
||||
return TangemLogCollector(logLevels, LogFormat.StairsFormatter())
|
||||
}
|
||||
|
||||
val additionalFeedbackInfo = initAdditionalFeedbackInfo(context)
|
||||
val tangemLogCollector = initTangemLogCollector()
|
||||
Log.addLogger(tangemLogCollector)
|
||||
|
||||
val feedbackManager = FeedbackManager(
|
||||
infoHolder = additionalFeedbackInfo,
|
||||
logCollector = tangemLogCollector,
|
||||
preferencesStorage = preferencesStorage,
|
||||
logEnabled = LogConfig.zendesk,
|
||||
)
|
||||
feedbackManager.initChat(
|
||||
context = context,
|
||||
zendeskConfig = config.zendesk!!,
|
||||
)
|
||||
store.dispatch(GlobalAction.SetFeedbackManager(feedbackManager))
|
||||
}
|
||||
|
||||
private fun initWarningMessagesManager() {
|
||||
store.dispatch(GlobalAction.SetWarningManager(WarningMessagesManager()))
|
||||
}
|
||||
}
|
||||
20
app/src/main/java/com/tangem/tap/common/AssetReader.kt
Normal file
20
app/src/main/java/com/tangem/tap/common/AssetReader.kt
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
package com.tangem.tap.common
|
||||
|
||||
import android.content.Context
|
||||
import com.tangem.tap.common.extensions.readAssetAsString
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface AssetReader {
|
||||
fun readAssetAsString(name: String): String
|
||||
}
|
||||
|
||||
class AndroidAssetReader(
|
||||
private val context: Context,
|
||||
) : AssetReader {
|
||||
|
||||
override fun readAssetAsString(name: String): String {
|
||||
return context.readAssetAsString(name)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
package com.tangem.tap.common.analytics
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import com.appsflyer.AFInAppEventParameterName
|
||||
import com.appsflyer.AFInAppEventType
|
||||
import com.appsflyer.AppsFlyerLib
|
||||
|
|
@ -8,7 +8,7 @@ import com.shopify.buy3.Storefront
|
|||
import com.tangem.common.card.Card
|
||||
import com.tangem.common.core.TangemSdkError
|
||||
|
||||
class AppsFlyerAnalyticsHandler(val context: Application): AnalyticsHandler() {
|
||||
class AppsFlyerAnalyticsHandler(val context: Context): AnalyticsHandler() {
|
||||
|
||||
override fun triggerEvent(
|
||||
event: AnalyticsEvent,
|
||||
|
|
@ -16,8 +16,7 @@ class AppsFlyerAnalyticsHandler(val context: Application): AnalyticsHandler() {
|
|||
blockchain: String?,
|
||||
params: Map<String, String>
|
||||
) {
|
||||
AppsFlyerLib.getInstance().logEvent(context,
|
||||
event.event, prepareParams(card, blockchain))
|
||||
AppsFlyerLib.getInstance().logEvent(context, event.event, prepareParams(card, blockchain))
|
||||
}
|
||||
|
||||
override fun logCardSdkError(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package com.tangem.tap.common.analytics
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import com.shopify.buy3.Storefront
|
||||
import com.tangem.common.card.Card
|
||||
import com.tangem.common.core.TangemSdkError
|
||||
|
|
@ -42,7 +42,7 @@ class GlobalAnalyticsHandler(val analyticsHandlers: List<AnalyticsHandler>) :
|
|||
}
|
||||
|
||||
companion object {
|
||||
fun createDefaultAnalyticHandlers(context: Application): GlobalAnalyticsHandler {
|
||||
fun createDefaultAnalyticHandlers(context: Context): GlobalAnalyticsHandler {
|
||||
return GlobalAnalyticsHandler(
|
||||
listOf(
|
||||
FirebaseAnalyticsHandler,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
package com.tangem.tap.common.feedback
|
||||
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.AmountType
|
||||
|
|
@ -45,15 +43,6 @@ class AdditionalFeedbackInfo {
|
|||
var fee: String = ""
|
||||
var token: String = ""
|
||||
|
||||
fun setAppVersion(context: Context) {
|
||||
try {
|
||||
val pInfo = context.packageManager.getPackageInfo(context.packageName, 0)
|
||||
appVersion = pInfo.versionName
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
fun setCardInfo(data: ScanResponse) {
|
||||
cardId = data.card.cardId
|
||||
cardBlockchain = data.walletData?.blockchain ?: ""
|
||||
|
|
|
|||
|
|
@ -31,13 +31,13 @@ sealed class TapError(
|
|||
object InsufficientBalance : TapError(R.string.send_error_insufficient_balance)
|
||||
object BlockchainInternalError : TapError(R.string.send_error_blockchain_internal)
|
||||
object AmountExceedsBalance : TapError(R.string.send_validation_amount_exceeds_balance)
|
||||
data class AmountLowerExistentialDeposit(override val args: List<Any>) : TapError(R.string.send_error_minimum_balance_format)
|
||||
object FeeExceedsBalance : TapError(R.string.send_validation_invalid_fee)
|
||||
object TotalExceedsBalance : TapError(R.string.send_validation_invalid_total)
|
||||
object InvalidAmountValue : TapError(R.string.send_validation_invalid_amount)
|
||||
object InvalidFeeValue : TapError(R.string.send_error_invalid_fee_value)
|
||||
data class DustAmount(override val args: List<Any>) : TapError(R.string.send_error_dust_amount_format)
|
||||
object DustChange : TapError(R.string.send_error_dust_change)
|
||||
data class CreateAccountUnderfunded(override val args: List<Any>) : TapError(R.string.send_error_no_target_account)
|
||||
|
||||
data class UnsupportedState(
|
||||
val stateError: String,
|
||||
|
|
|
|||
|
|
@ -1,12 +1,8 @@
|
|||
package com.tangem.tap.domain.configurable.config
|
||||
|
||||
import android.content.Context
|
||||
import com.google.firebase.ktx.Firebase
|
||||
import com.google.firebase.remoteconfig.ktx.remoteConfig
|
||||
import com.squareup.moshi.JsonAdapter
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.tangem.tap.common.analytics.FirebaseAnalyticsHandler
|
||||
import com.tangem.tap.common.extensions.readAssetAsString
|
||||
import com.tangem.tap.common.AssetReader
|
||||
import com.tangem.tap.domain.configurable.Loader
|
||||
import timber.log.Timber
|
||||
|
||||
|
|
@ -14,8 +10,8 @@ import timber.log.Timber
|
|||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class FeaturesLocalLoader(
|
||||
private val context: Context,
|
||||
private val moshi: Moshi,
|
||||
private val assetReader: AssetReader,
|
||||
private val moshi: Moshi,
|
||||
) : Loader<ConfigModel> {
|
||||
|
||||
override fun load(onComplete: (ConfigModel) -> Unit) {
|
||||
|
|
@ -23,8 +19,8 @@ class FeaturesLocalLoader(
|
|||
val featureAdapter: JsonAdapter<FeatureModel> = moshi.adapter(FeatureModel::class.java)
|
||||
val valuesAdapter: JsonAdapter<ConfigValueModel> = moshi.adapter(ConfigValueModel::class.java)
|
||||
|
||||
val jsonFeatures = context.readAssetAsString(Loader.featuresName)
|
||||
val jsonConfigValues = context.readAssetAsString(Loader.configValuesName)
|
||||
val jsonFeatures = assetReader.readAssetAsString(Loader.featuresName)
|
||||
val jsonConfigValues = assetReader.readAssetAsString(Loader.configValuesName)
|
||||
|
||||
ConfigModel(featureAdapter.fromJson(jsonFeatures), valuesAdapter.fromJson(jsonConfigValues))
|
||||
} catch (ex: Exception) {
|
||||
|
|
@ -33,31 +29,4 @@ class FeaturesLocalLoader(
|
|||
}
|
||||
onComplete(config)
|
||||
}
|
||||
}
|
||||
|
||||
class FeaturesRemoteLoader(
|
||||
private val moshi: Moshi,
|
||||
) : Loader<ConfigModel> {
|
||||
|
||||
override fun load(onComplete: (ConfigModel) -> Unit) {
|
||||
val emptyConfig = ConfigModel.empty()
|
||||
val remoteConfig = Firebase.remoteConfig
|
||||
remoteConfig.fetchAndActivate().addOnCompleteListener {
|
||||
if (it.isSuccessful) {
|
||||
val config = remoteConfig.getValue(Loader.featuresName)
|
||||
val jsonConfig = config.asString()
|
||||
if (jsonConfig.isEmpty()) {
|
||||
onComplete(emptyConfig)
|
||||
return@addOnCompleteListener
|
||||
}
|
||||
val featureAdapter: JsonAdapter<FeatureModel> = moshi.adapter(FeatureModel::class.java)
|
||||
onComplete(ConfigModel(featureAdapter.fromJson(jsonConfig), null))
|
||||
} else {
|
||||
onComplete(emptyConfig)
|
||||
}
|
||||
}.addOnFailureListener {
|
||||
FirebaseAnalyticsHandler.logException("remote_config_error.features", it)
|
||||
onComplete(emptyConfig)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -24,26 +24,19 @@ data class Config(
|
|||
val zendesk: ZendeskConfig? = null,
|
||||
)
|
||||
|
||||
class ConfigManager(
|
||||
private val localLoader: Loader<ConfigModel>,
|
||||
private val remoteLoader: Loader<ConfigModel>
|
||||
) {
|
||||
class ConfigManager {
|
||||
|
||||
var config: Config = Config()
|
||||
private set
|
||||
|
||||
private var defaultConfig = Config()
|
||||
|
||||
fun load(onComplete: ((config: Config) -> Unit)? = null) {
|
||||
localLoader.load { configModel ->
|
||||
fun load(configLoader: Loader<ConfigModel>, onComplete: ((config: Config) -> Unit)? = null) {
|
||||
configLoader.load { configModel ->
|
||||
setupFeature(configModel.features)
|
||||
setupKey(configModel.configValues)
|
||||
onComplete?.invoke(config)
|
||||
}
|
||||
// Uncomment to enable remote config
|
||||
// remoteLoader.load { config ->
|
||||
// setupFeature(config.features)
|
||||
// }
|
||||
}
|
||||
|
||||
fun turnOff(name: String) {
|
||||
|
|
|
|||
|
|
@ -1,52 +0,0 @@
|
|||
package com.tangem.tap.domain.configurable.warningMessage
|
||||
|
||||
import com.google.firebase.ktx.Firebase
|
||||
import com.google.firebase.remoteconfig.ktx.remoteConfig
|
||||
import com.squareup.moshi.JsonAdapter
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.squareup.moshi.Types
|
||||
import com.tangem.tap.common.analytics.FirebaseAnalyticsHandler
|
||||
import com.tangem.tap.domain.configurable.Loader
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class RemoteWarningLoader(
|
||||
private val moshi: Moshi,
|
||||
) : Loader<List<WarningMessage>> {
|
||||
|
||||
override fun load(onComplete: (List<WarningMessage>) -> Unit) {
|
||||
val emptyConfig = listOf<WarningMessage>()
|
||||
val remoteConfig = Firebase.remoteConfig
|
||||
remoteConfig.fetchAndActivate().addOnCompleteListener {
|
||||
if (!it.isSuccessful) {
|
||||
onComplete(emptyConfig)
|
||||
return@addOnCompleteListener
|
||||
}
|
||||
|
||||
val config = remoteConfig.getValue(Loader.warnings)
|
||||
val jsonConfig = config.asString()
|
||||
if (jsonConfig.isEmpty()) {
|
||||
onComplete(emptyConfig)
|
||||
return@addOnCompleteListener
|
||||
}
|
||||
|
||||
val adapterType = Types.newParameterizedType(List::class.java, WarningMessage::class.java)
|
||||
val warningsAdapter: JsonAdapter<List<WarningMessage>> = moshi.adapter(adapterType)
|
||||
try {
|
||||
val warnings = warningsAdapter.fromJson(jsonConfig) ?: listOf()
|
||||
onComplete(warnings)
|
||||
} catch (ex: Exception) {
|
||||
handleError(ex)
|
||||
onComplete(emptyConfig)
|
||||
}
|
||||
}.addOnFailureListener {
|
||||
handleError(it)
|
||||
onComplete(emptyConfig)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleError(ex: Exception) {
|
||||
FirebaseAnalyticsHandler.logException("remote_config_error.warnings", ex)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,35 +1,17 @@
|
|||
package com.tangem.tap.domain.configurable.warningMessage
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.common.extensions.VoidCallback
|
||||
import com.tangem.tap.common.extensions.containsAny
|
||||
import com.tangem.tap.common.extensions.removeBy
|
||||
import com.tangem.wallet.BuildConfig
|
||||
import com.tangem.wallet.R
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class WarningMessagesManager(
|
||||
private val warningLoader: RemoteWarningLoader,
|
||||
) {
|
||||
class WarningMessagesManager {
|
||||
|
||||
private val warningsList: MutableList<WarningMessage> = mutableListOf()
|
||||
|
||||
fun load(onComplete: VoidCallback? = null) {
|
||||
// exclude annoying remote debug warnings
|
||||
if (BuildConfig.DEBUG) {
|
||||
onComplete?.invoke()
|
||||
return
|
||||
}
|
||||
warningLoader.load { remoteList ->
|
||||
warningsList.clear()
|
||||
warningsList.addAll(remoteList)
|
||||
sortByPriority()
|
||||
onComplete?.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
fun addWarning(warning: WarningMessage) {
|
||||
if (findWarning(warning) == null) {
|
||||
warningsList.add(warning)
|
||||
|
|
@ -37,7 +19,10 @@ class WarningMessagesManager(
|
|||
}
|
||||
}
|
||||
|
||||
fun getWarnings(location: WarningMessage.Location, forBlockchains: List<Blockchain> = emptyList()): List<WarningMessage> {
|
||||
fun getWarnings(
|
||||
location: WarningMessage.Location,
|
||||
forBlockchains: List<Blockchain> = emptyList(),
|
||||
): List<WarningMessage> {
|
||||
return warningsList
|
||||
.filter { !it.isHidden && it.location.contains(location) }
|
||||
.filter {
|
||||
|
|
@ -94,7 +79,7 @@ class WarningMessagesManager(
|
|||
null,
|
||||
R.string.alert_title,
|
||||
R.string.alert_developer_card,
|
||||
WarningMessage.Origin.Local
|
||||
WarningMessage.Origin.Local,
|
||||
)
|
||||
|
||||
fun alreadySignedHashesWarning(): WarningMessage = WarningMessage(
|
||||
|
|
@ -106,7 +91,7 @@ class WarningMessagesManager(
|
|||
null,
|
||||
R.string.alert_title,
|
||||
R.string.alert_card_signed_transactions,
|
||||
WarningMessage.Origin.Local
|
||||
WarningMessage.Origin.Local,
|
||||
)
|
||||
|
||||
fun signedHashesMultiWalletWarning(): WarningMessage = WarningMessage(
|
||||
|
|
@ -131,7 +116,7 @@ class WarningMessagesManager(
|
|||
null,
|
||||
R.string.warning_rate_app_title,
|
||||
R.string.warning_rate_app_message,
|
||||
WarningMessage.Origin.Local
|
||||
WarningMessage.Origin.Local,
|
||||
)
|
||||
|
||||
fun isAlreadySignedHashesWarning(warning: WarningMessage): Boolean {
|
||||
|
|
@ -147,7 +132,7 @@ class WarningMessagesManager(
|
|||
null,
|
||||
R.string.warning_failed_to_verify_card_title,
|
||||
R.string.warning_failed_to_verify_card_message,
|
||||
WarningMessage.Origin.Local
|
||||
WarningMessage.Origin.Local,
|
||||
)
|
||||
|
||||
fun remainingSignaturesNotEnough(remainingSignatures: Int): WarningMessage = WarningMessage(
|
||||
|
|
@ -160,7 +145,7 @@ class WarningMessagesManager(
|
|||
titleResId = R.string.alert_title,
|
||||
messageResId = R.string.warning_low_signatures_format,
|
||||
origin = WarningMessage.Origin.Local,
|
||||
messageFormatArg = remainingSignatures.toString()
|
||||
messageFormatArg = remainingSignatures.toString(),
|
||||
)
|
||||
|
||||
fun testCardWarning(): WarningMessage = WarningMessage(
|
||||
|
|
@ -172,7 +157,7 @@ class WarningMessagesManager(
|
|||
null,
|
||||
R.string.alert_title,
|
||||
R.string.warning_testnet_card_message,
|
||||
WarningMessage.Origin.Local
|
||||
WarningMessage.Origin.Local,
|
||||
)
|
||||
|
||||
fun demoCardWarning(): WarningMessage = WarningMessage(
|
||||
|
|
@ -184,7 +169,7 @@ class WarningMessagesManager(
|
|||
null,
|
||||
R.string.alert_title,
|
||||
R.string.alert_demo_message,
|
||||
WarningMessage.Origin.Local
|
||||
WarningMessage.Origin.Local,
|
||||
)
|
||||
|
||||
const val REMAINING_SIGNATURES_WARNING = 10
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import com.tangem.common.extensions.toHexString
|
|||
import com.tangem.domain.common.ScanResponse
|
||||
import com.tangem.network.common.MoshiConverter
|
||||
import com.tangem.operations.wallet.CreateWalletResponse
|
||||
import com.tangem.tap.common.AssetReader
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.AnalyticsHandler
|
||||
import com.tangem.tap.tangemSdkManager
|
||||
|
|
@ -119,10 +120,6 @@ class TwinCardsManager(
|
|||
}
|
||||
}
|
||||
|
||||
interface AssetReader {
|
||||
fun readAssetAsString(name: String): String
|
||||
}
|
||||
|
||||
private class Issuer(
|
||||
val id: String,
|
||||
val privateKey: String,
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ import com.tangem.Message
|
|||
import com.tangem.blockchain.common.WalletManager
|
||||
import com.tangem.common.extensions.VoidCallback
|
||||
import com.tangem.domain.common.ScanResponse
|
||||
import com.tangem.tap.common.AssetReader
|
||||
import com.tangem.tap.common.redux.StateDialog
|
||||
import com.tangem.tap.domain.TapError
|
||||
import com.tangem.tap.domain.twins.AssetReader
|
||||
import com.tangem.tap.domain.twins.TwinCardsManager
|
||||
import com.tangem.tap.features.onboarding.OnboardingWalletBalance
|
||||
import org.rekotlin.Action
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@ import com.tangem.blockchain.common.Blockchain
|
|||
import com.tangem.common.extensions.VoidCallback
|
||||
import com.tangem.domain.common.TwinCardNumber
|
||||
import com.tangem.tangem_sdk_new.ui.widget.leapfrogWidget.LeapfrogWidget
|
||||
import com.tangem.tap.common.AndroidAssetReader
|
||||
import com.tangem.tap.common.extensions.beginDelayedTransition
|
||||
import com.tangem.tap.common.extensions.getDrawableCompat
|
||||
import com.tangem.tap.common.extensions.hide
|
||||
import com.tangem.tap.common.extensions.readAssetAsString
|
||||
import com.tangem.tap.common.extensions.show
|
||||
import com.tangem.tap.common.extensions.stripZeroPlainString
|
||||
import com.tangem.tap.common.redux.navigation.AppScreen
|
||||
|
|
@ -26,7 +26,6 @@ import com.tangem.tap.common.redux.navigation.NavigationAction
|
|||
import com.tangem.tap.common.redux.navigation.ShareElement
|
||||
import com.tangem.tap.common.toggleWidget.RefreshBalanceWidget
|
||||
import com.tangem.tap.common.transitions.InternalNoteLayoutTransition
|
||||
import com.tangem.tap.domain.twins.AssetReader
|
||||
import com.tangem.tap.domain.twins.TwinsCardWidget
|
||||
import com.tangem.tap.features.addBackPressHandler
|
||||
import com.tangem.tap.features.onboarding.products.BaseOnboardingFragment
|
||||
|
|
@ -46,13 +45,6 @@ class TwinsCardsFragment : BaseOnboardingFragment<TwinCardsState>() {
|
|||
private lateinit var twinsWidget: TwinsCardWidget
|
||||
private lateinit var btnRefreshBalanceWidget: RefreshBalanceWidget
|
||||
|
||||
private val assetReader: AssetReader by lazy {
|
||||
object : AssetReader {
|
||||
override fun readAssetAsString(name: String): String =
|
||||
requireContext().readAssetAsString(name)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
postponeEnterTransition()
|
||||
|
|
@ -250,7 +242,7 @@ class TwinsCardsFragment : BaseOnboardingFragment<TwinCardsState>() {
|
|||
store.dispatch(
|
||||
TwinCardsAction.Wallet.LaunchFirstStep(
|
||||
Message(getString(R.string.twins_recreate_title_format, twinIndexNumber)),
|
||||
assetReader
|
||||
AndroidAssetReader(requireContext()),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@ private fun filterErrorsForAmountField(errors: EnumSet<TransactionError>): EnumS
|
|||
TransactionError.TotalExceedsBalance -> {
|
||||
val notAcceptable = listOf(TransactionError.AmountExceedsBalance, TransactionError.FeeExceedsBalance)
|
||||
if (!showIntoAmountField.containsAll(notAcceptable)) showIntoAmountField.add(it)
|
||||
showIntoAmountField.remove(TransactionError.AmountLowerExistentialDeposit)
|
||||
}
|
||||
else -> showIntoAmountField.add(it)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.tap.features.send.redux.middlewares
|
|||
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import com.tangem.blockchain.blockchains.binance.BinanceTransactionExtras
|
||||
import com.tangem.blockchain.blockchains.polkadot.ExistentialDepositProvider
|
||||
import com.tangem.blockchain.blockchains.stellar.StellarTransactionExtras
|
||||
import com.tangem.blockchain.blockchains.xrp.XrpTransactionBuilder
|
||||
import com.tangem.blockchain.common.Amount
|
||||
|
|
@ -301,12 +302,21 @@ fun createValidateTransactionError(
|
|||
val tapErrors = errorList.map {
|
||||
when (it) {
|
||||
TransactionError.AmountExceedsBalance -> TapError.AmountExceedsBalance
|
||||
TransactionError.AmountLowerExistentialDeposit -> {
|
||||
if (walletManager is ExistentialDepositProvider) {
|
||||
val args = listOf(walletManager.getExistentialDeposit().stripZeroPlainString())
|
||||
TapError.AmountLowerExistentialDeposit(args)
|
||||
} else {
|
||||
TapError.UnknownError
|
||||
}
|
||||
}
|
||||
TransactionError.FeeExceedsBalance -> TapError.FeeExceedsBalance
|
||||
TransactionError.TotalExceedsBalance -> TapError.TotalExceedsBalance
|
||||
TransactionError.InvalidAmountValue -> TapError.InvalidAmountValue
|
||||
TransactionError.InvalidFeeValue -> TapError.InvalidFeeValue
|
||||
TransactionError.DustAmount -> {
|
||||
TapError.DustAmount(listOf(walletManager.dustValue?.stripZeroPlainString() ?: "0"))
|
||||
val args = listOf(walletManager.dustValue?.stripZeroPlainString() ?: "0")
|
||||
TapError.DustAmount(args)
|
||||
}
|
||||
TransactionError.DustChange -> TapError.DustChange
|
||||
else -> TapError.UnknownError
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ class ReceiptReducer : SendInternalReducer {
|
|||
}
|
||||
|
||||
private fun String.addPrecisionSign(): String {
|
||||
val result = if (feeState.feeIsApproximate) "$CAN_BE_LOWER_SIGN $this" else ""
|
||||
val result = if (feeState.feeIsApproximate) "$CAN_BE_LOWER_SIGN $this" else this
|
||||
return result.trim()
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package com.tangem.tap.features.send.ui.dialogs
|
|||
|
||||
import android.content.Context
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.BlockchainSdkError
|
||||
import com.tangem.common.module.ModuleMessageConverter
|
||||
import com.tangem.tangem_sdk_new.extensions.localizedDescription
|
||||
|
|
@ -47,9 +48,13 @@ private class BlockchainSdkErrorConverter(
|
|||
override fun convert(message: BlockchainSdkError): String {
|
||||
return when (message) {
|
||||
is BlockchainSdkError.CreateAccountUnderfunded -> {
|
||||
val reserve = message.minReserve.value?.stripZeroPlainString() ?: "0"
|
||||
val symbol = message.minReserve.currencySymbol
|
||||
context.getString(R.string.send_error_no_target_account, reserve, symbol)
|
||||
val resStringId = when (message.blockchain) {
|
||||
Blockchain.Polkadot, Blockchain.PolkadotTestnet -> R.string.no_account_polkadot
|
||||
else -> R.string.send_error_no_target_account
|
||||
}
|
||||
val reserveValueString = message.minReserve.value?.stripZeroPlainString() ?: "0"
|
||||
val argument = "$reserveValueString ${message.minReserve.currencySymbol}"
|
||||
context.getString(resStringId, argument)
|
||||
}
|
||||
else -> message.customMessage
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ class SendStateSubscriber(fragment: BaseStoreFragment) :
|
|||
if (!it.viewFieldValue.isFromUserInput) etXlmMemo.setText(it.viewFieldValue.value)
|
||||
if (it.error != null) {
|
||||
if (it.error == TransactionExtraError.INVALID_XLM_MEMO) {
|
||||
tilXlmMemo.error = fg.getText(R.string.send_error_invalid_memo)
|
||||
tilXlmMemo.error = fg.getText(R.string.send_extras_error_invalid_memo)
|
||||
}
|
||||
} else {
|
||||
tilXlmMemo.error = null
|
||||
|
|
@ -91,7 +91,7 @@ class SendStateSubscriber(fragment: BaseStoreFragment) :
|
|||
if (infoState.xrpDestinationTag.error != null) {
|
||||
if (infoState.xrpDestinationTag.error == TransactionExtraError.INVALID_DESTINATION_TAG) {
|
||||
tilDestinationTag.error =
|
||||
fg.getText(R.string.send_error_invalid_destination_tag)
|
||||
fg.getText(R.string.send_extras_error_invalid_destination_tag)
|
||||
}
|
||||
} else {
|
||||
tilDestinationTag.error = null
|
||||
|
|
@ -103,7 +103,7 @@ class SendStateSubscriber(fragment: BaseStoreFragment) :
|
|||
infoState.binanceMemo?.let {
|
||||
if (infoState.binanceMemo.error != null) {
|
||||
if (infoState.binanceMemo.error == TransactionExtraError.INVALID_BINANCE_MEMO) {
|
||||
tilBinanceMemo.error = fg.getText(R.string.send_error_invalid_memo)
|
||||
tilBinanceMemo.error = fg.getText(R.string.send_extras_error_invalid_memo)
|
||||
}
|
||||
} else {
|
||||
tilBinanceMemo.error = null
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<string name="send_error_invalid_fee_value">Falsche Gebühr</string>
|
||||
<string name="send_error_dust_amount_format">Minimaler Betrag ist %s</string>
|
||||
<string name="send_error_dust_change">Restbestand zu klein</string>
|
||||
<string name="send_error_no_target_account">Das Zielkonto ist nicht erstellt. Der abzusendende Betrag soll %s %s + Gebühr oder mehr sein</string>
|
||||
<string name="send_error_no_target_account">Das Zielkonto ist nicht erstellt. Der abzusendende Betrag soll %s + Gebühr oder mehr sein</string>
|
||||
<string name="send_error_no_account_xlm">Um ein Konto zu erstellen, senden Sie 1+ XLM an diese Adresse</string>
|
||||
<string name="send_error_fee_request_failed">Erhalt der Gebühr fehlgeschlagen</string>
|
||||
<string name="send_error_unknown">Unbekannter Fehler</string>
|
||||
|
|
@ -17,4 +17,11 @@
|
|||
<string name="send_validation_amount_exceeds_balance">Der Betrag geht über die Bilanz hinaus</string>
|
||||
<string name="send_validation_invalid_total">Der Gesamtbetrag geht über die Bilanz hinaus</string>
|
||||
<string name="send_validation_invalid_fee">Die Gebühr geht über die Bilanz hinaus</string>
|
||||
<string name="send_error_minimum_balance_format">Minimum balance is %s</string>
|
||||
<string name="send_extras_hint_memo">Memo</string>
|
||||
<string name="send_extras_hint_destination_tag">Tag</string>
|
||||
<string name="send_extras_error_invalid_memo">Invalid Memo. It won\'t be added to the transaction</string>
|
||||
<string name="send_extras_error_invalid_destination_tag">Invalid Tag. It won\'t be added to the transaction</string>
|
||||
<string name="warning_existential_deposit_message">%s network has a concept of Existential Deposit. If your account drops below %s %s it will be deactivated and any remaining funds will be destroyed.</string>
|
||||
<string name="no_account_polkadot">Destination account is not active. Send %s or more to activate the account.</string>
|
||||
</resources>
|
||||
|
|
@ -86,9 +86,4 @@
|
|||
<string name="card_settings_reset_card_to_factory">Reset to Factory Settings</string>
|
||||
<string name="card_settings_reset_card_to_factory_footer">Factory Reset will completely delete the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code.</string>
|
||||
<string name="wallet_connect_select_network">Select network</string>
|
||||
<string name="send_extras_hint_memo">Memo</string>
|
||||
<string name="send_extras_hint_destination_tag">Tag</string>
|
||||
<string name="send_error_invalid_memo">Invalid Memo. It won\'t be added to the transaction</string>
|
||||
<string name="send_error_invalid_destination_tag">Invalid Tag. It won\'t be added to the transaction</string>
|
||||
<string name="warning_existential_deposit_message">%s network has a concept of Existential Deposit. If your account drops below %s %s it will be deactivated and any remaining funds will be destroyed.</string>
|
||||
</resources>
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
<string name="send_error_invalid_fee_value">Commission non valide</string>
|
||||
<string name="send_error_dust_amount_format">Le montant minimal est de %s</string>
|
||||
<string name="send_error_dust_change">Le reste est trop petit</string>
|
||||
<string name="send_error_no_target_account">Le compte cible n\'a pas été créé. Le montant à envoyer doit être de %s %s + commissions ou plus</string>
|
||||
<string name="send_error_no_target_account">Le compte cible n\'a pas été créé. Le montant à envoyer doit être de %s + commissions ou plus</string>
|
||||
<string name="send_error_no_account_xlm">Pour créer un compte, envoyez 1+ XLM à cette adresse</string>
|
||||
<string name="send_error_fee_request_failed">Échec de réception des commissions</string>
|
||||
<string name="send_error_unknown">Erreur inconnue</string>
|
||||
|
|
@ -17,4 +17,11 @@
|
|||
<string name="xtz_withdrawal_message_warning">Pour ne pas payer une commission élevée la prochaine fois que vous rechargez votre portefeuille, veuillez réduire le montant de %s XTZ</string>
|
||||
<string name="xtz_withdrawal_message_reduce">Réduire de %s XTZ</string>
|
||||
<string name="xtz_withdrawal_message_ignore">Non, envoyer toute la somme</string>
|
||||
<string name="send_error_minimum_balance_format">Minimum balance is %s</string>
|
||||
<string name="send_extras_hint_memo">Memo</string>
|
||||
<string name="send_extras_hint_destination_tag">Tag</string>
|
||||
<string name="send_extras_error_invalid_memo">Invalid Memo. It won\'t be added to the transaction</string>
|
||||
<string name="send_extras_error_invalid_destination_tag">Invalid Tag. It won\'t be added to the transaction</string>
|
||||
<string name="warning_existential_deposit_message">%s network has a concept of Existential Deposit. If your account drops below %s %s it will be deactivated and any remaining funds will be destroyed.</string>
|
||||
<string name="no_account_polkadot">Destination account is not active. Send %s or more to activate the account.</string>
|
||||
</resources>
|
||||
|
|
@ -86,9 +86,4 @@
|
|||
<string name="card_settings_reset_card_to_factory">Reset to Factory Settings</string>
|
||||
<string name="card_settings_reset_card_to_factory_footer">Factory Reset will completely delete the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code.</string>
|
||||
<string name="wallet_connect_select_network">Select network</string>
|
||||
<string name="send_extras_hint_memo">Memo</string>
|
||||
<string name="send_extras_hint_destination_tag">Tag</string>
|
||||
<string name="send_error_invalid_memo">Invalid Memo. It won\'t be added to the transaction</string>
|
||||
<string name="send_error_invalid_destination_tag">Invalid Tag. It won\'t be added to the transaction</string>
|
||||
<string name="warning_existential_deposit_message">%s network has a concept of Existential Deposit. If your account drops below %s %s it will be deactivated and any remaining funds will be destroyed.</string>
|
||||
</resources>
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
<string name="send_error_dust_change">L\'importo residuo è molto basso</string>
|
||||
<string name="send_error_unknown">Errore sconosciuto</string>
|
||||
<string name="send_validation_amount_exceeds_balance">L\'importo supera il saldo</string>
|
||||
<string name="send_error_no_target_account">Per creare un account, invia %s %s a questo indirizzo</string>
|
||||
<string name="send_error_no_target_account">Per creare un account, invia %s a questo indirizzo</string>
|
||||
<string name="send_error_fee_request_failed">Impossibile ottenere la commissione</string>
|
||||
<string name="send_error_no_account_xlm">Per creare un account, invia 1+ XLM a questo indirizzo</string>
|
||||
<string name="send_validation_invalid_address">Indirizzo non valido</string>
|
||||
|
|
@ -17,4 +17,11 @@
|
|||
<string name="xtz_withdrawal_message_warning">Per evitare di pagare una commissione maggiore la prossima volta che ricarichi il tuo portafoglio, riduci l\'importo di %s XTZ</string>
|
||||
<string name="xtz_withdrawal_message_reduce">Riduci di %s XTZ</string>
|
||||
<string name="xtz_withdrawal_message_ignore">No, invia l\'intero importo</string>
|
||||
<string name="send_error_minimum_balance_format">Minimum balance is %s</string>
|
||||
<string name="send_extras_hint_memo">Memo</string>
|
||||
<string name="send_extras_hint_destination_tag">Tag</string>
|
||||
<string name="send_extras_error_invalid_memo">Invalid Memo. It won\'t be added to the transaction</string>
|
||||
<string name="send_extras_error_invalid_destination_tag">Invalid Tag. It won\'t be added to the transaction</string>
|
||||
<string name="warning_existential_deposit_message">%s network has a concept of Existential Deposit. If your account drops below %s %s it will be deactivated and any remaining funds will be destroyed.</string>
|
||||
<string name="no_account_polkadot">Destination account is not active. Send %s or more to activate the account.</string>
|
||||
</resources>
|
||||
|
|
@ -86,9 +86,4 @@
|
|||
<string name="card_settings_reset_card_to_factory">Reset to Factory Settings</string>
|
||||
<string name="card_settings_reset_card_to_factory_footer">Factory Reset will completely delete the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code.</string>
|
||||
<string name="wallet_connect_select_network">Select network</string>
|
||||
<string name="send_extras_hint_memo">Memo</string>
|
||||
<string name="send_extras_hint_destination_tag">Tag</string>
|
||||
<string name="send_error_invalid_memo">Invalid Memo. It won\'t be added to the transaction</string>
|
||||
<string name="send_error_invalid_destination_tag">Invalid Tag. It won\'t be added to the transaction</string>
|
||||
<string name="warning_existential_deposit_message">%s network has a concept of Existential Deposit. If your account drops below %s %s it will be deactivated and any remaining funds will be destroyed.</string>
|
||||
</resources>
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
<string name="send_error_dust_change">Сдача слишком мала</string>
|
||||
<string name="send_error_no_account_xlm">Для создания учетной записи отправьте 1+ XLM на этот адрес</string>
|
||||
<string name="send_error_fee_request_failed">Не удалось получить комиссию</string>
|
||||
<string name="send_error_no_target_account">Целевая учетная запись не создана. Сумма для отправки должна быть %1$s %2$s + плата за создание или больше</string>
|
||||
<string name="send_error_no_target_account">Целевая учетная запись не создана. Сумма для отправки должна быть %s + плата за создание или больше</string>
|
||||
<string name="send_error_unknown">Неизвестная ошибка</string>
|
||||
<string name="send_validation_invalid_address">Неверный адрес</string>
|
||||
<string name="send_validation_invalid_amount">Недопустимая сумма</string>
|
||||
|
|
@ -17,4 +17,6 @@
|
|||
<string name="xtz_withdrawal_message_warning">Чтобы не платить повышенную комиссию при следующем пополнении кошелька, уменьшите сумму на %s XTZ</string>
|
||||
<string name="xtz_withdrawal_message_reduce">Уменьшить на %s XTZ</string>
|
||||
<string name="xtz_withdrawal_message_ignore">Нет, отправить все</string>
|
||||
<string name="send_error_minimum_balance_format">Минимальный баланс: %s</string>
|
||||
<string name="no_account_polkadot">Аккаунт получателя не активирован. Отправьте %s или более для активации аккаунта.</string>
|
||||
</resources>
|
||||
|
|
@ -99,7 +99,7 @@
|
|||
<string name="wallet_connect_select_network">Выберите сеть</string>
|
||||
<string name="send_extras_hint_memo">Memo</string>
|
||||
<string name="send_extras_hint_destination_tag">Tag</string>
|
||||
<string name="send_error_invalid_memo">Недопустимый Memo. Он не будет добавлен в транзакцию.</string>
|
||||
<string name="send_error_invalid_destination_tag">Недопустимый Tag. Он не будет добавлен в транзакцию.</string>
|
||||
<string name="send_extras_error_invalid_memo">Недопустимый Memo. Он не будет добавлен в транзакцию.</string>
|
||||
<string name="send_extras_error_invalid_destination_tag">Недопустимый Tag. Он не будет добавлен в транзакцию.</string>
|
||||
<string name="warning_existential_deposit_message">Сеть %s использует концепцию экзистенциального депозита. Если баланс вашего счета опустится ниже %s %s, он будет деактивирован, а все оставшиеся средства будут уничтожены.</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<string name="send_error_dust_change">Change is too small</string>
|
||||
<string name="send_error_no_account_xlm">To create account send 1+ XLM to this address</string>
|
||||
<string name="send_error_fee_request_failed">Failed to get fee</string>
|
||||
<string name="send_error_no_target_account">Target account is not created. Amount to send should be %s %s + fee or more to create</string>
|
||||
<string name="send_error_no_target_account">Target account is not created. Amount to send should be %s + fee or more to create</string>
|
||||
<string name="send_error_unknown">Unknown error</string>
|
||||
<string name="send_validation_invalid_address">Invalid address</string>
|
||||
<string name="send_validation_invalid_amount">Invalid amount</string>
|
||||
|
|
@ -17,4 +17,11 @@
|
|||
<string name="xtz_withdrawal_message_warning">To avoid paying an increased commission the next time you top up your wallet, reduce the amount by %s XTZ</string>
|
||||
<string name="xtz_withdrawal_message_reduce">Reduce by %s XTZ</string>
|
||||
<string name="xtz_withdrawal_message_ignore">No, send all</string>
|
||||
<string name="send_error_minimum_balance_format">Minimum balance is %s</string>
|
||||
<string name="send_extras_hint_memo">Memo</string>
|
||||
<string name="send_extras_hint_destination_tag">Tag</string>
|
||||
<string name="send_extras_error_invalid_memo">Invalid Memo. It won\'t be added to the transaction</string>
|
||||
<string name="send_extras_error_invalid_destination_tag">Invalid Tag. It won\'t be added to the transaction</string>
|
||||
<string name="warning_existential_deposit_message">%s network has a concept of Existential Deposit. If your account drops below %s %s it will be deactivated and any remaining funds will be destroyed.</string>
|
||||
<string name="no_account_polkadot">Destination account is not active. Send %s or more to activate the account.</string>
|
||||
</resources>
|
||||
|
|
@ -99,9 +99,4 @@
|
|||
<string name="card_settings_reset_card_to_factory">Reset to Factory Settings</string>
|
||||
<string name="card_settings_reset_card_to_factory_footer">Factory Reset will completely delete the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code.</string>
|
||||
<string name="wallet_connect_select_network">Select network</string>
|
||||
<string name="send_extras_hint_memo">Memo</string>
|
||||
<string name="send_extras_hint_destination_tag">Tag</string>
|
||||
<string name="send_error_invalid_memo">Invalid Memo. It won\'t be added to the transaction</string>
|
||||
<string name="send_error_invalid_destination_tag">Invalid Tag. It won\'t be added to the transaction</string>
|
||||
<string name="warning_existential_deposit_message">%s network has a concept of Existential Deposit. If your account drops below %s %s it will be deactivated and any remaining funds will be destroyed.</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ ext.versions = [
|
|||
kotlin : '1.6.10',
|
||||
build_gradle : '7.1.3',
|
||||
tangem_card_sdk : 'develop-159',
|
||||
tangem_blockchain_sdk: 'develop-111',
|
||||
tangem_blockchain_sdk: 'develop-113',
|
||||
// tangem_blockchain_sdk: '0.0.1',
|
||||
]
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue