Updated on 2026-08-14
This commit is contained in:
commit
996eee33e3
23 changed files with 219 additions and 129 deletions
|
|
@ -77,9 +77,9 @@ dependencies {
|
|||
implementation 'com.google.android.play:core-ktx:1.8.1'
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
|
||||
|
||||
implementation 'com.tangem:blockchain:develop-17'
|
||||
implementation 'com.tangem:core:develop-36'
|
||||
implementation 'com.tangem:sdk:develop-36'
|
||||
implementation 'com.tangem:blockchain:develop-26'
|
||||
implementation 'com.tangem:core:fixes_for_app_release-44'
|
||||
implementation 'com.tangem:sdk:fixes_for_app_release-44'
|
||||
|
||||
// WebView
|
||||
implementation "androidx.browser:browser:1.3.0"
|
||||
|
|
@ -117,10 +117,6 @@ dependencies {
|
|||
implementation 'com.squareup.moshi:moshi:1.9.2'
|
||||
implementation "com.squareup.moshi:moshi-kotlin:1.9.2"
|
||||
implementation 'com.squareup.okhttp3:logging-interceptor:4.2.2'
|
||||
//
|
||||
// //Crypto
|
||||
implementation "com.madgag.spongycastle:core:1.58.0.0"
|
||||
|
||||
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
testImplementation "com.google.truth:truth:1.0.1"
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ 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.blockchain.network.BlockchainSdkRetrofitBuilder
|
||||
import com.tangem.tap.common.images.PicassoHelper
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.common.redux.appReducer
|
||||
|
|
@ -58,6 +59,8 @@ class TapApplication : Application() {
|
|||
|
||||
initFeedbackManager()
|
||||
loadConfigs()
|
||||
|
||||
BlockchainSdkRetrofitBuilder.enableNetworkLogging = BuildConfig.DEBUG
|
||||
}
|
||||
|
||||
private fun loadConfigs() {
|
||||
|
|
|
|||
|
|
@ -4,11 +4,9 @@ import android.app.Dialog
|
|||
import android.content.Context
|
||||
import com.tangem.tap.common.redux.global.GlobalState
|
||||
import com.tangem.tap.features.details.redux.walletconnect.WalletConnectDialog
|
||||
import com.tangem.tap.features.details.ui.walletconnect.dialogs.ApproveWcSessionDialog
|
||||
import com.tangem.tap.features.details.ui.walletconnect.dialogs.ClipboardOrScanQrDialog
|
||||
import com.tangem.tap.features.details.ui.walletconnect.dialogs.PersonalSignDialog
|
||||
import com.tangem.tap.features.details.ui.walletconnect.dialogs.TransactionDialog
|
||||
import com.tangem.tap.features.details.ui.walletconnect.dialogs.*
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.wallet.R
|
||||
import org.rekotlin.StoreSubscriber
|
||||
|
||||
class DialogManager : StoreSubscriber<GlobalState> {
|
||||
|
|
@ -40,9 +38,21 @@ class DialogManager : StoreSubscriber<GlobalState> {
|
|||
if (dialog != null) return
|
||||
|
||||
when (state.dialog) {
|
||||
is WalletConnectDialog.UnsupportedCard ->
|
||||
dialog = SimpleAlertDialog.create(
|
||||
titleRes = R.string.wallet_connect,
|
||||
messageRes = R.string.wallet_connect_scanner_error_no_ethereum_wallet,
|
||||
context = context
|
||||
)
|
||||
is WalletConnectDialog.OpeningSessionRejected -> {
|
||||
dialog = SimpleAlertDialog.create(
|
||||
titleRes = R.string.wallet_connect,
|
||||
messageRes = R.string.wallet_connect_same_wcuri,
|
||||
context = context
|
||||
)
|
||||
}
|
||||
is WalletConnectDialog.ApproveWcSession ->
|
||||
dialog = ApproveWcSessionDialog.create(state.dialog.session, context)
|
||||
|
||||
is WalletConnectDialog.ClipboardOrScanQr ->
|
||||
dialog = ClipboardOrScanQrDialog.create(state.dialog.clipboardUri, context)
|
||||
is WalletConnectDialog.RequestTransaction ->
|
||||
|
|
|
|||
|
|
@ -19,5 +19,6 @@ fun Blockchain.getIconRes(): Int {
|
|||
Blockchain.Tezos -> R.drawable.ic_tezos
|
||||
Blockchain.XRP -> R.drawable.ic_xrp
|
||||
Blockchain.Stellar -> R.drawable.ic_stellar
|
||||
else -> R.drawable.shape_circle
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ import com.tangem.tap.common.analytics.FirebaseAnalyticsHandler
|
|||
import com.tangem.tap.common.redux.global.FiatCurrencyName
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.currenciesRepository
|
||||
import com.tangem.tap.domain.TapWorkarounds.isStart2Coin
|
||||
import com.tangem.tap.domain.configurable.config.ConfigManager
|
||||
import com.tangem.tap.domain.extensions.*
|
||||
import com.tangem.tap.domain.tasks.ScanNoteResponse
|
||||
|
|
@ -89,7 +90,6 @@ class TapWalletManager {
|
|||
if (addAnalyticsEvent) {
|
||||
FirebaseAnalyticsHandler.triggerEvent(AnalyticsEvent.CARD_IS_SCANNED, data.card)
|
||||
}
|
||||
TapWorkarounds.updateCard(data.card)
|
||||
store.state.globalState.feedbackManager?.infoHolder?.setCardInfo(data.card)
|
||||
updateConfigManager(data)
|
||||
|
||||
|
|
@ -119,7 +119,7 @@ class TapWalletManager {
|
|||
private fun updateConfigManager(data: ScanNoteResponse) {
|
||||
val configManager = store.state.globalState.configManager
|
||||
val blockchain = data.card.getBlockchain()
|
||||
if (TapWorkarounds.isStart2Coin) {
|
||||
if (data.card.isStart2Coin) {
|
||||
configManager?.turnOff(ConfigManager.isSendingToPayIdEnabled)
|
||||
configManager?.turnOff(ConfigManager.isTopUpEnabled)
|
||||
} else if (blockchain == Blockchain.Bitcoin
|
||||
|
|
|
|||
|
|
@ -3,18 +3,19 @@ package com.tangem.tap.domain
|
|||
import com.tangem.commands.common.card.Card
|
||||
import com.tangem.commands.common.card.EllipticCurve
|
||||
import com.tangem.commands.common.card.masks.Product
|
||||
import com.tangem.tap.domain.TapWorkarounds.isStart2Coin
|
||||
import com.tangem.tap.domain.extensions.getSingleWallet
|
||||
import java.util.*
|
||||
|
||||
object TapWorkarounds {
|
||||
|
||||
var isStart2Coin: Boolean = false
|
||||
private set
|
||||
|
||||
fun updateCard(card: Card) {
|
||||
isStart2Coin = card.cardData?.issuerName?.toLowerCase(Locale.US) == START_2_COIN_ISSUER
|
||||
fun isStart2CoinIssuer(cardIssuer: String?): Boolean {
|
||||
return cardIssuer?.toLowerCase(Locale.US) == START_2_COIN_ISSUER
|
||||
}
|
||||
|
||||
val Card.isStart2Coin: Boolean
|
||||
get() = isStart2CoinIssuer(cardData?.issuerName)
|
||||
|
||||
fun Card.isExcluded(): Boolean {
|
||||
val cardData = this.cardData ?: return false
|
||||
val productMask = cardData.productMask
|
||||
|
|
@ -43,7 +44,7 @@ object TapWorkarounds {
|
|||
val Card.isMultiwalletAllowed: Boolean
|
||||
get() {
|
||||
return cardData?.productMask?.contains(Product.TwinCard) != true
|
||||
&& !TapWorkarounds.isStart2Coin
|
||||
&& !isStart2Coin
|
||||
&& (firmwareVersion.major >= 4 ||
|
||||
getSingleWallet()?.curve == EllipticCurve.Secp256k1)
|
||||
}
|
||||
|
|
@ -31,10 +31,11 @@ fun Blockchain.getSupportedCurves(): List<EllipticCurve>? {
|
|||
Blockchain.Unknown -> null
|
||||
Blockchain.Bitcoin, Blockchain.BitcoinTestnet, Blockchain.BitcoinCash, Blockchain.Litecoin,
|
||||
Blockchain.Ducatus, Blockchain.Ethereum, Blockchain.EthereumTestnet, Blockchain.RSK,
|
||||
Blockchain.XRP, Blockchain.Binance, Blockchain.BinanceTestnet -> listOf(EllipticCurve.Secp256k1)
|
||||
Blockchain.Tezos -> listOf(EllipticCurve.Secp256k1, EllipticCurve.Ed25519)
|
||||
Blockchain.Binance, Blockchain.BinanceTestnet -> listOf(EllipticCurve.Secp256k1)
|
||||
Blockchain.Tezos, Blockchain.XRP -> listOf(EllipticCurve.Secp256k1, EllipticCurve.Ed25519)
|
||||
Blockchain.Cardano, Blockchain.CardanoShelley, Blockchain.Stellar ->
|
||||
listOf(EllipticCurve.Ed25519)
|
||||
else -> listOf(EllipticCurve.Secp256k1)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,10 @@ class CurrenciesRepository(val context: Application) {
|
|||
saveTokens(cardId, tokens)
|
||||
}
|
||||
|
||||
fun saveAddedTokens(cardId: String, tokens: Collection<Token>) {
|
||||
saveTokens(cardId, loadSavedTokens(cardId) + tokens)
|
||||
}
|
||||
|
||||
fun saveAddedBlockchain(cardId: String, blockchain: Blockchain) {
|
||||
val blockchains = loadSavedBlockchains(cardId) + blockchain
|
||||
saveBlockchains(cardId, blockchains)
|
||||
|
|
@ -96,9 +100,9 @@ class CurrenciesRepository(val context: Application) {
|
|||
|
||||
fun getBlockchains(cardFirmware: FirmwareVersion?): List<Blockchain> {
|
||||
return if (cardFirmware == null || cardFirmware.major < 4) {
|
||||
secp256k1Blochcains
|
||||
secp256k1Blockchains
|
||||
} else {
|
||||
secp256k1Blochcains + ed25519Blockchains
|
||||
secp256k1Blockchains + ed25519Blockchains
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -111,10 +115,19 @@ class CurrenciesRepository(val context: Application) {
|
|||
fun getFileNameForBlockchains(cardId: String): String =
|
||||
"${FILE_NAME_PREFIX_BLOCKCHAINS}_$cardId"
|
||||
|
||||
private val secp256k1Blochcains = listOf(
|
||||
Blockchain.Bitcoin, Blockchain.BitcoinCash, Blockchain.Binance, Blockchain.Litecoin,
|
||||
Blockchain.XRP, Blockchain.Tezos,
|
||||
Blockchain.Ethereum, Blockchain.RSK)
|
||||
private val secp256k1Blockchains = listOf(
|
||||
Blockchain.Bitcoin,
|
||||
Blockchain.BitcoinCash,
|
||||
Blockchain.Binance,
|
||||
Blockchain.BSC,
|
||||
Blockchain.Litecoin,
|
||||
Blockchain.XRP,
|
||||
Blockchain.Tezos,
|
||||
Blockchain.Ethereum,
|
||||
Blockchain.RSK,
|
||||
Blockchain.Polygon,
|
||||
Blockchain.Dogecoin,
|
||||
)
|
||||
private val ed25519Blockchains = listOf(Blockchain.CardanoShelley, Blockchain.Stellar)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,10 @@ class WalletConnectManager {
|
|||
|
||||
fun connect(wcUri: String, wallet: WalletForSession) {
|
||||
val session = WCSession.from(wcUri) ?: return
|
||||
if (sessions[session] != null) {
|
||||
store.dispatchOnMain(WalletConnectAction.RefuseOpeningSession)
|
||||
return
|
||||
}
|
||||
val client = WCClient(httpClient = okHttpClient)
|
||||
setListeners(client)
|
||||
val peerId = UUID.randomUUID().toString()
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ package com.tangem.tap.features.details.redux
|
|||
import com.tangem.commands.common.card.Card
|
||||
import com.tangem.commands.common.card.masks.Settings
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.domain.TapWorkarounds
|
||||
import com.tangem.tap.domain.TapWorkarounds.isStart2Coin
|
||||
import com.tangem.tap.domain.extensions.isWalletDataSupported
|
||||
import com.tangem.tap.domain.extensions.signedHashesCount
|
||||
import com.tangem.tap.domain.extensions.toSendableAmounts
|
||||
|
|
@ -143,7 +143,7 @@ private fun handleSecurityAction(
|
|||
): DetailsState {
|
||||
return when (action) {
|
||||
is DetailsAction.ManageSecurity.OpenSecurity -> {
|
||||
if (TapWorkarounds.isStart2Coin) {
|
||||
if (state.card?.isStart2Coin == true) {
|
||||
return state.copy(securityScreenState = state.securityScreenState?.copy(
|
||||
allowedOptions = EnumSet.of(SecurityOption.LongTap),
|
||||
selectedOption = state.securityScreenState.currentOption
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ sealed class WalletConnectAction : Action {
|
|||
val wallet: WalletForSession,
|
||||
) : WalletConnectAction()
|
||||
|
||||
object RefuseOpeningSession : WalletConnectAction()
|
||||
|
||||
data class AcceptOpeningSession(val session: WalletConnectSession) : WalletConnectAction()
|
||||
|
||||
data class ApproveSession(
|
||||
|
|
@ -37,7 +39,7 @@ sealed class WalletConnectAction : Action {
|
|||
data class Success(val session: WalletConnectSession) : WalletConnectAction()
|
||||
}
|
||||
|
||||
object FailureEstablishingSession : WalletConnectAction()
|
||||
data class FailureEstablishingSession(val session: WCSession?) : WalletConnectAction()
|
||||
|
||||
|
||||
data class SetSessionsRestored(val sessions: List<WalletConnectSession>) :
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.tap.features.details.redux.walletconnect
|
||||
|
||||
import com.tangem.blockchain.common.*
|
||||
import com.tangem.commands.common.card.Card
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.common.extensions.toHexString
|
||||
import com.tangem.tap.*
|
||||
|
|
@ -14,6 +15,7 @@ import com.tangem.tap.common.redux.navigation.NavigationAction
|
|||
import com.tangem.tap.domain.extensions.makeWalletManagerForApp
|
||||
import com.tangem.tap.domain.isMultiwalletAllowed
|
||||
import com.tangem.tap.domain.walletconnect.WalletConnectManager
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.wallet.R
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
|
@ -55,55 +57,19 @@ class WalletConnectMiddleware {
|
|||
}
|
||||
|
||||
is WalletConnectAction.ScanCard -> {
|
||||
scope.launch {
|
||||
val result = tangemSdkManager.scanNote(
|
||||
FirebaseAnalyticsHandler,
|
||||
R.string.wallet_connect_scan_card_message
|
||||
)
|
||||
withContext(Dispatchers.Main) {
|
||||
when (result) {
|
||||
is CompletionResult.Success -> {
|
||||
val card = result.data.card
|
||||
val factory =
|
||||
store.state.globalState.tapWalletManager.walletManagerFactory
|
||||
handleScanCard(action.wcUri)
|
||||
}
|
||||
|
||||
val walletManager = if (card.isMultiwalletAllowed) {
|
||||
if (currenciesRepository.loadCardCurrencies(card.cardId)?.blockchains?.contains(
|
||||
Blockchain.Ethereum) == true
|
||||
) {
|
||||
factory.makeWalletManagerForApp(result.data.card,
|
||||
Blockchain.Ethereum)
|
||||
} else {
|
||||
factory.makeWalletManagerForApp(result.data.card,
|
||||
Blockchain.Ethereum)?.also {
|
||||
currenciesRepository.saveAddedBlockchain(card.cardId,
|
||||
Blockchain.Ethereum)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
if (walletManager == null) {
|
||||
store.dispatchOnMain(WalletConnectAction.UnsupportedCard)
|
||||
return@withContext
|
||||
};
|
||||
|
||||
val key = walletManager.wallet.publicKey
|
||||
store.dispatchOnMain(WalletConnectAction.OpenSession(
|
||||
wcUri = action.wcUri,
|
||||
wallet = WalletForSession(
|
||||
card.cardId, key.toHexString(),
|
||||
isTestNet = false
|
||||
),
|
||||
))
|
||||
}
|
||||
is CompletionResult.Failure ->
|
||||
store.dispatchOnMain(WalletConnectAction.FailureEstablishingSession)
|
||||
}
|
||||
}
|
||||
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,
|
||||
|
|
@ -111,6 +77,12 @@ class WalletConnectMiddleware {
|
|||
)
|
||||
}
|
||||
|
||||
is WalletConnectAction.RefuseOpeningSession -> {
|
||||
store.dispatch(GlobalAction.ShowDialog(
|
||||
WalletConnectDialog.OpeningSessionRejected
|
||||
))
|
||||
}
|
||||
|
||||
is WalletConnectAction.AcceptOpeningSession -> {
|
||||
store.dispatchOnMain(GlobalAction.ShowDialog(WalletConnectDialog.ApproveWcSession(
|
||||
action.session)))
|
||||
|
|
@ -153,4 +125,69 @@ class WalletConnectMiddleware {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleScanCard(wcUri: String) {
|
||||
scope.launch {
|
||||
val result = tangemSdkManager.scanNote(
|
||||
FirebaseAnalyticsHandler,
|
||||
R.string.wallet_connect_scan_card_message
|
||||
)
|
||||
withContext(Dispatchers.Main) {
|
||||
when (result) {
|
||||
is CompletionResult.Success -> {
|
||||
val card = result.data.card
|
||||
|
||||
if (!card.isMultiwalletAllowed) {
|
||||
store.dispatchOnMain(WalletConnectAction.UnsupportedCard)
|
||||
return@withContext
|
||||
}
|
||||
|
||||
val walletManager = getWalletManager(card)
|
||||
if (walletManager == null) {
|
||||
store.dispatchOnMain(WalletConnectAction.UnsupportedCard)
|
||||
return@withContext
|
||||
}
|
||||
|
||||
val key = walletManager.wallet.publicKey
|
||||
store.dispatchOnMain(WalletConnectAction.OpenSession(
|
||||
wcUri = wcUri,
|
||||
wallet = WalletForSession(
|
||||
card.cardId, key.toHexString(),
|
||||
isTestNet = false
|
||||
),
|
||||
))
|
||||
}
|
||||
is CompletionResult.Failure ->
|
||||
store.dispatchOnMain(WalletConnectAction.FailureEstablishingSession(
|
||||
null
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getWalletManager(card: Card): WalletManager? {
|
||||
val factory = store.state.globalState.tapWalletManager.walletManagerFactory
|
||||
|
||||
return if (store.state.globalState.scanNoteResponse?.card?.cardId == card.cardId) {
|
||||
store.state.walletState.getWalletManager(Blockchain.Ethereum)
|
||||
?: factory.makeWalletManagerForApp(card, Blockchain.Ethereum)
|
||||
?.also { walletManager ->
|
||||
store.dispatch(WalletAction.MultiWallet.AddWalletManagers(walletManager))
|
||||
store.dispatch(WalletAction.MultiWallet.AddBlockchain(walletManager.wallet.blockchain))
|
||||
}
|
||||
} else {
|
||||
if (currenciesRepository.loadCardCurrencies(card.cardId)?.blockchains?.contains(
|
||||
Blockchain.Ethereum) == true
|
||||
) {
|
||||
factory.makeWalletManagerForApp(card, Blockchain.Ethereum)
|
||||
} else {
|
||||
factory.makeWalletManagerForApp(card,
|
||||
Blockchain.Ethereum)
|
||||
?.also {
|
||||
currenciesRepository.saveAddedBlockchain(card.cardId, Blockchain.Ethereum)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -26,6 +26,8 @@ class WalletConnectReducer {
|
|||
}
|
||||
is WalletConnectAction.ScanCard -> state.copy(loading = true)
|
||||
|
||||
is WalletConnectAction.UnsupportedCard -> state.copy(loading = false)
|
||||
is WalletConnectAction.RefuseOpeningSession -> state.copy(loading = false)
|
||||
is WalletConnectAction.FailureEstablishingSession -> state.copy(loading = false)
|
||||
|
||||
else -> state
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@ data class WalletForSession(
|
|||
|
||||
sealed class WalletConnectDialog : StateDialog {
|
||||
data class ClipboardOrScanQr(val clipboardUri: String) : WalletConnectDialog()
|
||||
object UnsupportedCard : WalletConnectDialog()
|
||||
object OpeningSessionRejected : WalletConnectDialog()
|
||||
data class ApproveWcSession(val session: WalletConnectSession) : WalletConnectDialog()
|
||||
data class RequestTransaction(val dialogData: TransactionRequestDialogData) :
|
||||
WalletConnectDialog()
|
||||
|
|
|
|||
|
|
@ -25,7 +25,9 @@ class ApproveWcSessionDialog {
|
|||
session.session
|
||||
))
|
||||
}
|
||||
setNegativeButton(context.getText(R.string.common_reject)) { _, _ -> }
|
||||
setNegativeButton(context.getText(R.string.common_reject)) { _, _ ->
|
||||
store.dispatch(WalletConnectAction.FailureEstablishingSession(session.session))
|
||||
}
|
||||
setOnDismissListener {
|
||||
store.dispatch(GlobalAction.HideDialog)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
package com.tangem.tap.features.details.ui.walletconnect.dialogs
|
||||
|
||||
import android.content.Context
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.wallet.R
|
||||
|
||||
class SimpleAlertDialog {
|
||||
companion object {
|
||||
fun create(
|
||||
titleRes: Int,
|
||||
messageRes: Int,
|
||||
buttonRes: Int = R.string.common_ok,
|
||||
context: Context,
|
||||
): AlertDialog {
|
||||
|
||||
return AlertDialog.Builder(context).apply {
|
||||
setTitle(context.getString(titleRes))
|
||||
setMessage(context.getText(messageRes))
|
||||
setPositiveButton(context.getText(buttonRes)) { _, _ -> }
|
||||
setOnDismissListener {
|
||||
store.dispatch(GlobalAction.HideDialog)
|
||||
}
|
||||
}.create()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14,10 +14,9 @@ import com.tangem.Log
|
|||
import com.tangem.TangemSdkLogger
|
||||
import com.tangem.blockchain.common.*
|
||||
import com.tangem.commands.common.card.Card
|
||||
import com.tangem.commands.wallet.WalletStatus
|
||||
import com.tangem.tap.common.extensions.stripZeroPlainString
|
||||
import com.tangem.tap.domain.TapWorkarounds
|
||||
import com.tangem.tap.domain.extensions.signedHashesCount
|
||||
import com.tangem.tap.store
|
||||
import timber.log.Timber
|
||||
import java.io.File
|
||||
import java.io.FileWriter
|
||||
|
|
@ -50,7 +49,11 @@ class FeedbackManager(
|
|||
}
|
||||
|
||||
private fun getSupportEmail(): String {
|
||||
return if (TapWorkarounds.isStart2Coin) S2C_SUPPORT_EMAIL else DEFAULT_SUPPORT_EMAIL
|
||||
return if (TapWorkarounds.isStart2CoinIssuer(infoHolder.cardIssuer)) {
|
||||
S2C_SUPPORT_EMAIL
|
||||
} else {
|
||||
DEFAULT_SUPPORT_EMAIL
|
||||
}
|
||||
}
|
||||
|
||||
private fun sendTo(email: String, subject: String, message: String, fileLog: File? = null) {
|
||||
|
|
@ -145,6 +148,7 @@ class AdditionalEmailInfo {
|
|||
// card
|
||||
var cardId: String = ""
|
||||
var cardFirmwareVersion: String = ""
|
||||
var cardIssuer: String = ""
|
||||
|
||||
// wallets
|
||||
internal val walletsInfo = mutableListOf<EmailWalletInfo>()
|
||||
|
|
@ -173,7 +177,10 @@ class AdditionalEmailInfo {
|
|||
fun setCardInfo(card: Card) {
|
||||
cardId = card.cardId
|
||||
cardFirmwareVersion = card.firmwareVersion.version
|
||||
signedHashesCount = card.signedHashesCount().toString()
|
||||
cardIssuer = card.cardData?.issuerName ?: ""
|
||||
signedHashesCount = card.wallets
|
||||
.filter { it.status == WalletStatus.Loaded }
|
||||
.joinToString(";") { "${it.curve?.curve} - ${it.signedHashes}" }
|
||||
}
|
||||
|
||||
fun setWalletsInfo(walletManagers: List<WalletManager>) {
|
||||
|
|
@ -191,7 +198,6 @@ class AdditionalEmailInfo {
|
|||
}
|
||||
|
||||
fun updateOnSendError(wallet: Wallet, host: String, amountToSend: Amount, feeAmount: Amount, destinationAddress: String) {
|
||||
val amountState = store.state.sendState.amountState
|
||||
onSendErrorWalletInfo = EmailWalletInfo(
|
||||
blockchain = wallet.blockchain,
|
||||
address = getAddress(wallet),
|
||||
|
|
@ -202,9 +208,7 @@ class AdditionalEmailInfo {
|
|||
this.destinationAddress = destinationAddress
|
||||
amount = amountToSend.value?.stripZeroPlainString() ?: "0"
|
||||
fee = feeAmount.value?.stripZeroPlainString() ?: "0"
|
||||
if (amountState.typeOfAmount is AmountType.Token) {
|
||||
token = amountState.amountToExtract?.currencySymbol ?: ""
|
||||
}
|
||||
token = if (amountToSend.type is AmountType.Token) amountToSend.currencySymbol else ""
|
||||
}
|
||||
|
||||
private fun getAddress(wallet: Wallet): String {
|
||||
|
|
@ -289,6 +293,7 @@ class SendTransactionFailedEmail(private val error: String) : EmailData {
|
|||
appendKeyValue("OS version", infoHolder.osVersion)
|
||||
appendKeyValue("App version", infoHolder.appVersion)
|
||||
appendKeyValue("Firmware version", infoHolder.cardFirmwareVersion)
|
||||
appendKeyValue("Signed hashes", infoHolder.signedHashesCount)
|
||||
// appendKeyValue("Transaction HEX", infoHolder.transactionHex)
|
||||
}.toString()
|
||||
}
|
||||
|
|
@ -301,6 +306,7 @@ class FeedbackEmail : EmailData {
|
|||
val builder = StringBuilder()
|
||||
builder.appendKeyValue("Card ID", infoHolder.cardId)
|
||||
builder.appendKeyValue("Firmware version", infoHolder.cardFirmwareVersion)
|
||||
builder.appendKeyValue("Signed hashes", infoHolder.signedHashesCount)
|
||||
|
||||
infoHolder.walletsInfo.forEach {
|
||||
builder.appendKeyValue("Blockchain", it.blockchain.fullName)
|
||||
|
|
@ -316,6 +322,6 @@ class FeedbackEmail : EmailData {
|
|||
}
|
||||
}
|
||||
|
||||
fun StringBuilder.appendKeyValue(key: String, value: String): StringBuilder {
|
||||
return this.append("$key: $value\n")
|
||||
private fun StringBuilder.appendKeyValue(key: String, value: String): StringBuilder {
|
||||
return if (value.isNotBlank()) this.append("$key: $value\n") else this
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@ import com.tangem.tap.common.redux.global.GlobalAction
|
|||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.domain.TangemSigner
|
||||
import com.tangem.tap.domain.TapError
|
||||
import com.tangem.tap.domain.TapWorkarounds
|
||||
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.send.redux.*
|
||||
|
|
@ -108,7 +108,7 @@ private fun sendTransaction(
|
|||
scope.launch {
|
||||
walletManager.update()
|
||||
val isLinkedTerminal = tangemSdk.config.linkedTerminal
|
||||
if (TapWorkarounds.isStart2Coin) {
|
||||
if (card.isStart2Coin) {
|
||||
tangemSdk.config.linkedTerminal = false
|
||||
}
|
||||
val signer = TangemSigner(
|
||||
|
|
|
|||
|
|
@ -44,14 +44,14 @@ class MultiWalletMiddleware {
|
|||
addTokens(action.tokens, walletState, globalState)
|
||||
}
|
||||
is WalletAction.MultiWallet.AddBlockchain -> {
|
||||
if (walletState?.blockchains?.contains(action.blockchain) == true) return
|
||||
|
||||
globalState?.scanNoteResponse?.card?.let { card ->
|
||||
currenciesRepository.saveAddedBlockchain(card.cardId, action.blockchain)
|
||||
globalState.tapWalletManager.walletManagerFactory
|
||||
if (walletState?.blockchains?.contains(action.blockchain) != true) {
|
||||
globalState.tapWalletManager.walletManagerFactory
|
||||
.makeWalletManagerForApp(card, action.blockchain)?.let {
|
||||
store.dispatch(WalletAction.MultiWallet.AddWalletManagers(it))
|
||||
}
|
||||
}
|
||||
}
|
||||
store.dispatch(WalletAction.LoadFiatRate(currency = Currency.Blockchain(action.blockchain)))
|
||||
store.dispatch(WalletAction.LoadWallet(blockchain = action.blockchain))
|
||||
|
|
@ -87,12 +87,12 @@ class MultiWalletMiddleware {
|
|||
val wallet = walletManager.wallet
|
||||
val coinAmount = wallet.amounts[AmountType.Coin]?.value
|
||||
if (coinAmount != null && !coinAmount.isZero()) {
|
||||
if (walletState?.getWalletData(wallet.blockchain) == null) {
|
||||
scope.launch(Dispatchers.Main) {
|
||||
scope.launch(Dispatchers.Main) {
|
||||
if (walletState?.getWalletData(wallet.blockchain) == null) {
|
||||
store.dispatch(WalletAction.MultiWallet.AddWalletManagers(
|
||||
listOfNotNull(walletManager)))
|
||||
listOfNotNull(walletManager)))
|
||||
store.dispatch(WalletAction.MultiWallet.AddBlockchain(
|
||||
wallet.blockchain
|
||||
wallet.blockchain
|
||||
))
|
||||
store.dispatch(WalletAction.LoadWallet.Success(wallet))
|
||||
}
|
||||
|
|
@ -118,6 +118,7 @@ class MultiWalletMiddleware {
|
|||
when (result) {
|
||||
is Result.Success -> {
|
||||
if (result.data.isNotEmpty()) {
|
||||
currenciesRepository.saveAddedTokens(card.cardId, result.data)
|
||||
store.dispatch(
|
||||
WalletAction.MultiWallet.AddWalletManagers(
|
||||
walletManager
|
||||
|
|
|
|||
|
|
@ -18,9 +18,6 @@ import com.tangem.tap.features.wallet.ui.BalanceStatus
|
|||
import com.tangem.tap.store
|
||||
import com.tangem.wallet.R
|
||||
import kotlinx.android.synthetic.main.item_currency_wallet.view.*
|
||||
import kotlinx.android.synthetic.main.item_currency_wallet.view.iv_currency
|
||||
import kotlinx.android.synthetic.main.item_currency_wallet.view.tv_currency_symbol
|
||||
import kotlinx.android.synthetic.main.item_currency_wallet.view.tv_token_letter
|
||||
import java.math.BigDecimal
|
||||
|
||||
class WalletAdapter
|
||||
|
|
@ -57,7 +54,7 @@ class WalletAdapter
|
|||
|
||||
val sorted = listModified.sortedWith(
|
||||
compareByDescending<WalletData> { it.currencyData.fiatAmount ?: BigDecimal.ZERO }
|
||||
.thenBy { it.currencyData.currencySymbol }
|
||||
.thenBy { it.currencyData.currency }
|
||||
)
|
||||
val sortedList = listOfNotNull(primaryBlockchainWallet, primaryTokenWallet) + sorted
|
||||
super.submitList(sortedList)
|
||||
|
|
|
|||
|
|
@ -31,14 +31,6 @@
|
|||
android:layout_marginTop="16dp"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
|
||||
<com.google.android.material.progressindicator.LinearProgressIndicator
|
||||
android:id="@+id/pb_wallet_connect"
|
||||
android:indeterminate="true"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_no_sessions_title"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
@ -71,6 +63,13 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
<com.google.android.material.progressindicator.LinearProgressIndicator
|
||||
android:id="@+id/pb_wallet_connect"
|
||||
android:indeterminate="true"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fab_open_session"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
|||
|
|
@ -153,4 +153,7 @@ this wallet.
|
|||
<string name="wallet_connect_clipboard_alert" translatable="false">Clipboard contain WalletConnect code. Use copied value or scan QR-code</string>
|
||||
<string name="wallet_connect_paste_from_clipboard" translatable="false">Paste from clipboard</string>
|
||||
<string name="wallet_connect_scan_new_code" translatable="false">Scan new code</string>
|
||||
<string name="wallet_connect_scanner_error_no_ethereum_wallet" translatable="false">This card can’t be used to establish WalletConnect session</string>
|
||||
<string name="wallet_connect_could_not_complete" translatable="false">The operation couldn\'t be completed</string>
|
||||
<string name="wallet_connect_same_wcuri" translatable="false">The operation couldn\'t be completed. \n\nYou have already established a WalletConnect session with this parameters.</string>
|
||||
</resources>
|
||||
|
|
|
|||
24
build.gradle
24
build.gradle
|
|
@ -19,28 +19,10 @@ buildscript {
|
|||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
mavenLocal()
|
||||
maven { url "https://nexus.tangem-tech.com/repository/maven-releases/" }
|
||||
maven { url 'https://jitpack.io' }
|
||||
def nexusUser = "viewer"
|
||||
def nexusPass = "smartcash124"
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
maven {
|
||||
credentials {
|
||||
username = nexusUser
|
||||
password = nexusPass
|
||||
}
|
||||
url "https://nexus.tangem-tech.com/repository/maven-releases/"
|
||||
}
|
||||
maven {
|
||||
credentials {
|
||||
username = nexusUser
|
||||
password = nexusPass
|
||||
}
|
||||
url "https://nexus.tangem-tech.com/repository/maven-snapshots/"
|
||||
}
|
||||
maven { url 'https://jitpack.io' }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue