Updated on 2026-08-14
This commit is contained in:
parent
9a8ff1830d
commit
a0798cfef2
252 changed files with 247 additions and 5857 deletions
|
|
@ -27,7 +27,6 @@ import com.tangem.operations.pins.SetUserCodeCommand
|
|||
import com.tangem.operations.usersetttings.SetUserCodeRecoveryAllowedTask
|
||||
import com.tangem.tap.common.analytics.events.Basic
|
||||
import com.tangem.tap.derivationsFinder
|
||||
import com.tangem.tap.domain.tasks.CreateWalletAndRescanTask
|
||||
import com.tangem.tap.domain.tasks.product.CreateProductWalletTask
|
||||
import com.tangem.tap.domain.tasks.product.CreateProductWalletTaskResponse
|
||||
import com.tangem.tap.domain.tasks.product.ResetToFactorySettingsTask
|
||||
|
|
@ -126,15 +125,6 @@ class TangemSdkManager(
|
|||
}
|
||||
}
|
||||
|
||||
suspend fun createWallet(cardId: String?): CompletionResult<CardDTO> {
|
||||
return runTaskAsyncReturnOnMain(
|
||||
CreateWalletAndRescanTask(),
|
||||
cardId,
|
||||
initialMessage = Message(resources.getString(R.string.initial_message_create_wallet_body)),
|
||||
)
|
||||
.map { CardDTO(it) }
|
||||
}
|
||||
|
||||
suspend fun derivePublicKeys(
|
||||
cardId: String?,
|
||||
derivations: Map<ByteArrayKey, List<DerivationPath>>,
|
||||
|
|
|
|||
|
|
@ -22,11 +22,7 @@ sealed class TapError(
|
|||
|
||||
object UnknownError : TapError(R.string.send_error_unknown)
|
||||
open class CustomError(val customMessage: String) : TapError(R.string.common_custom_string, listOf(customMessage))
|
||||
data class UnsupportedState(
|
||||
val stateError: String,
|
||||
) : TapError(R.string.common_custom_string, listOf("Unsupported state: $stateError"))
|
||||
|
||||
object UnknownBlockchain : TapError(R.string.wallet_error_unsupported_blockchain_subtitle)
|
||||
object NoInternetConnection : TapError(R.string.wallet_notification_no_internet)
|
||||
object AmountExceedsBalance : TapError(R.string.send_validation_amount_exceeds_balance)
|
||||
data class AmountLowerExistentialDeposit(
|
||||
|
|
@ -41,7 +37,6 @@ sealed class TapError(
|
|||
object DustChange : TapError(R.string.send_error_dust_change)
|
||||
|
||||
sealed class WalletManager {
|
||||
object CreationError : CustomError(customMessage = "Can't create wallet manager")
|
||||
class NoAccountError(amountToCreateAccount: String) : CustomError(amountToCreateAccount)
|
||||
class InternalError(message: String) : CustomError(message)
|
||||
object BlockchainIsUnreachableTryLater : TapError(R.string.wallet_balance_blockchain_unreachable_try_later)
|
||||
|
|
|
|||
|
|
@ -51,14 +51,12 @@ data class WarningMessage(
|
|||
}
|
||||
|
||||
enum class Location {
|
||||
@Json(name = "main")
|
||||
MainScreen,
|
||||
|
||||
@Json(name = "send")
|
||||
SendScreen,
|
||||
}
|
||||
|
||||
enum class Origin {
|
||||
Local, Remote
|
||||
Remote,
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,6 @@
|
|||
package com.tangem.tap.domain.configurable.warningMessage
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.utils.extensions.removeBy
|
||||
import com.tangem.wallet.R
|
||||
import java.util.concurrent.CopyOnWriteArrayList
|
||||
|
||||
/**
|
||||
|
|
@ -14,13 +12,6 @@ class WarningMessagesManager {
|
|||
|
||||
private val warningsList = CopyOnWriteArrayList<WarningMessage>()
|
||||
|
||||
fun addWarning(warning: WarningMessage) {
|
||||
if (findWarning(warning) == null) {
|
||||
warningsList.add(warning)
|
||||
sortByPriority()
|
||||
}
|
||||
}
|
||||
|
||||
fun getWarnings(location: WarningMessage.Location, blockchains: List<Blockchain>): List<WarningMessage> {
|
||||
return warningsList.filter { message ->
|
||||
val messageBlockchains = message.blockchainList
|
||||
|
|
@ -45,131 +36,7 @@ class WarningMessagesManager {
|
|||
}
|
||||
}
|
||||
|
||||
fun removeWarnings(origin: WarningMessage.Origin) {
|
||||
warningsList.removeBy { it.origin == origin }
|
||||
sortByPriority()
|
||||
}
|
||||
|
||||
fun removeWarnings(messageRes: Int) {
|
||||
warningsList.removeBy { it.messageResId == messageRes }
|
||||
}
|
||||
|
||||
fun containsWarning(warning: WarningMessage) = warning in warningsList
|
||||
|
||||
private fun sortByPriority() {
|
||||
warningsList.sortBy { it.priority.ordinal }
|
||||
}
|
||||
|
||||
private fun findWarning(warning: WarningMessage): WarningMessage? {
|
||||
return warningsList.firstOrNull { it == warning }
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val REMAINING_SIGNATURES_WARNING = 10
|
||||
|
||||
val devCardWarning = WarningMessage(
|
||||
title = "",
|
||||
message = "",
|
||||
type = WarningMessage.Type.Permanent,
|
||||
priority = WarningMessage.Priority.Critical,
|
||||
location = listOf(WarningMessage.Location.MainScreen),
|
||||
blockchains = null,
|
||||
titleResId = R.string.common_warning,
|
||||
// messageResId = R.string.alert_developer_card,
|
||||
origin = WarningMessage.Origin.Local,
|
||||
)
|
||||
|
||||
val alreadySignedHashesWarning = WarningMessage(
|
||||
title = "",
|
||||
message = "",
|
||||
type = WarningMessage.Type.Temporary,
|
||||
priority = WarningMessage.Priority.Info,
|
||||
location = listOf(WarningMessage.Location.MainScreen),
|
||||
blockchains = null,
|
||||
titleResId = R.string.common_warning,
|
||||
// messageResId = R.string.alert_card_signed_transactions,
|
||||
origin = WarningMessage.Origin.Local,
|
||||
)
|
||||
|
||||
val signedHashesMultiWalletWarning = WarningMessage(
|
||||
title = "",
|
||||
message = "",
|
||||
type = WarningMessage.Type.Temporary,
|
||||
priority = WarningMessage.Priority.Info,
|
||||
location = listOf(WarningMessage.Location.MainScreen),
|
||||
blockchains = null,
|
||||
// titleResId = R.string.warning_important_security_info,
|
||||
// messageResId = R.string.warning_signed_tx_previously,
|
||||
origin = WarningMessage.Origin.Local,
|
||||
buttonTextId = R.string.warning_button_learn_more,
|
||||
titleFormatArg = "\u26A0",
|
||||
)
|
||||
|
||||
val appRatingWarning = WarningMessage(
|
||||
title = "",
|
||||
message = "",
|
||||
type = WarningMessage.Type.AppRating,
|
||||
priority = WarningMessage.Priority.Info,
|
||||
location = listOf(WarningMessage.Location.MainScreen),
|
||||
blockchains = null,
|
||||
titleResId = R.string.warning_rate_app_title,
|
||||
messageResId = R.string.warning_rate_app_message,
|
||||
origin = WarningMessage.Origin.Local,
|
||||
)
|
||||
|
||||
val onlineVerificationFailed = WarningMessage(
|
||||
title = "",
|
||||
message = "",
|
||||
type = WarningMessage.Type.Permanent,
|
||||
priority = WarningMessage.Priority.Critical,
|
||||
location = listOf(WarningMessage.Location.MainScreen),
|
||||
blockchains = null,
|
||||
titleResId = R.string.warning_failed_to_verify_card_title,
|
||||
messageResId = R.string.warning_failed_to_verify_card_message,
|
||||
origin = WarningMessage.Origin.Local,
|
||||
)
|
||||
|
||||
val testCardWarning = WarningMessage(
|
||||
title = "",
|
||||
message = "",
|
||||
type = WarningMessage.Type.TestCard,
|
||||
priority = WarningMessage.Priority.Critical,
|
||||
location = listOf(WarningMessage.Location.MainScreen, WarningMessage.Location.SendScreen),
|
||||
blockchains = null,
|
||||
titleResId = R.string.common_warning,
|
||||
messageResId = R.string.warning_testnet_card_message,
|
||||
origin = WarningMessage.Origin.Local,
|
||||
)
|
||||
|
||||
val demoCardWarning = WarningMessage(
|
||||
title = "",
|
||||
message = "",
|
||||
type = WarningMessage.Type.Permanent,
|
||||
priority = WarningMessage.Priority.Critical,
|
||||
location = listOf(WarningMessage.Location.MainScreen),
|
||||
blockchains = null,
|
||||
titleResId = R.string.common_warning,
|
||||
// messageResId = R.string.alert_demo_message,
|
||||
origin = WarningMessage.Origin.Local,
|
||||
)
|
||||
|
||||
fun remainingSignaturesNotEnough(remainingSignatures: Int): WarningMessage {
|
||||
return WarningMessage(
|
||||
title = "",
|
||||
message = "",
|
||||
type = WarningMessage.Type.Permanent,
|
||||
priority = WarningMessage.Priority.Critical,
|
||||
location = listOf(WarningMessage.Location.MainScreen),
|
||||
blockchains = null,
|
||||
titleResId = R.string.common_warning,
|
||||
// messageResId = R.string.warning_low_signatures_format,
|
||||
origin = WarningMessage.Origin.Local,
|
||||
messageFormatArg = remainingSignatures.toString(),
|
||||
)
|
||||
}
|
||||
|
||||
// fun isAlreadySignedHashesWarning(warning: WarningMessage): Boolean {
|
||||
// return warning.messageResId == R.string.alert_card_signed_transactions
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
|
@ -9,17 +9,6 @@ import com.tangem.domain.userwallets.Artwork
|
|||
import com.tangem.operations.attestation.CardVerifyAndGetInfo
|
||||
import com.tangem.operations.attestation.OnlineCardVerifier
|
||||
|
||||
val CardDTO.remainingSignatures: Int?
|
||||
get() = this.wallets.firstOrNull()?.remainingSignatures
|
||||
|
||||
val CardDTO.isHdWalletAllowedByApp: Boolean
|
||||
get() = settings.isHDWalletAllowed
|
||||
|
||||
@Suppress("UnnecessaryParentheses")
|
||||
fun CardDTO.hasSignedHashes(): Boolean {
|
||||
return wallets.any { (it.totalSignedHashes ?: 0) > 0 }
|
||||
}
|
||||
|
||||
fun CardDTO.signedHashesCount(): Int {
|
||||
return wallets.sumOf { it.totalSignedHashes ?: 0 }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +0,0 @@
|
|||
package com.tangem.tap.domain.extensions
|
||||
|
||||
import com.tangem.blockchain.common.Token
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
|
||||
private val tokenCustomIconUrls = mutableMapOf<String, String>()
|
||||
|
||||
fun Token.getCustomIconUrl(): String? {
|
||||
return tokenCustomIconUrls[this.contractAddress]
|
||||
}
|
||||
|
||||
fun Token.setCustomIconUrl(url: String) {
|
||||
tokenCustomIconUrls[this.contractAddress] = url
|
||||
}
|
||||
64
app/src/main/java/com/tangem/tap/domain/model/Currency.kt
Normal file
64
app/src/main/java/com/tangem/tap/domain/model/Currency.kt
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
package com.tangem.tap.domain.model
|
||||
|
||||
import com.tangem.domain.common.BlockchainNetwork
|
||||
import com.tangem.domain.features.addCustomToken.CustomCurrency
|
||||
import com.tangem.tap.common.redux.global.CryptoCurrencyName
|
||||
import com.tangem.blockchain.common.Blockchain as SdkBlockchain
|
||||
import com.tangem.blockchain.common.Token as SdkToken
|
||||
|
||||
sealed interface Currency {
|
||||
val blockchain: SdkBlockchain
|
||||
val currencySymbol: CryptoCurrencyName
|
||||
val derivationPath: String?
|
||||
val decimals
|
||||
get() = when (this) {
|
||||
is Blockchain -> blockchain.decimals()
|
||||
is Token -> token.decimals
|
||||
}
|
||||
|
||||
data class Token(
|
||||
val token: SdkToken,
|
||||
override val blockchain: SdkBlockchain,
|
||||
override val derivationPath: String?,
|
||||
) : Currency {
|
||||
override val currencySymbol = token.symbol
|
||||
}
|
||||
|
||||
data class Blockchain(
|
||||
override val blockchain: SdkBlockchain,
|
||||
override val derivationPath: String?,
|
||||
) : Currency {
|
||||
override val currencySymbol: CryptoCurrencyName = blockchain.currency
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun fromBlockchainNetwork(blockchainNetwork: BlockchainNetwork, token: SdkToken? = null): Currency {
|
||||
return if (token != null) {
|
||||
Token(
|
||||
token = token,
|
||||
blockchain = blockchainNetwork.blockchain,
|
||||
derivationPath = blockchainNetwork.derivationPath,
|
||||
)
|
||||
} else {
|
||||
Blockchain(
|
||||
blockchain = blockchainNetwork.blockchain,
|
||||
derivationPath = blockchainNetwork.derivationPath,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun fromCustomCurrency(customCurrency: CustomCurrency): Currency {
|
||||
return when (customCurrency) {
|
||||
is CustomCurrency.CustomBlockchain -> Blockchain(
|
||||
blockchain = customCurrency.network,
|
||||
derivationPath = customCurrency.derivationPath?.rawPath,
|
||||
)
|
||||
is CustomCurrency.CustomToken -> Token(
|
||||
token = customCurrency.token,
|
||||
blockchain = customCurrency.network,
|
||||
derivationPath = customCurrency.derivationPath?.rawPath,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
package com.tangem.tap.domain.model
|
||||
|
||||
import com.tangem.blockchain.common.TransactionData
|
||||
import com.tangem.blockchain.common.TransactionStatus
|
||||
import com.tangem.blockchain.common.Wallet
|
||||
|
||||
data class PendingTransaction(
|
||||
val transactionData: TransactionData,
|
||||
val type: PendingTransactionType,
|
||||
) {
|
||||
val address: String? = when (type) {
|
||||
PendingTransactionType.Incoming -> nullIfUnknown(transactionData.sourceAddress)
|
||||
PendingTransactionType.Outgoing -> nullIfUnknown(transactionData.destinationAddress)
|
||||
PendingTransactionType.Unknown -> null
|
||||
}
|
||||
|
||||
val currency: String = transactionData.amount.currencySymbol
|
||||
|
||||
private fun nullIfUnknown(address: String): String? = if (address == "unknown") null else address
|
||||
}
|
||||
|
||||
enum class PendingTransactionType { Incoming, Outgoing, Unknown }
|
||||
|
||||
fun TransactionData.toPendingTransaction(walletAddress: String): PendingTransaction? {
|
||||
if (this.status == TransactionStatus.Confirmed) return null
|
||||
|
||||
val type: PendingTransactionType = when {
|
||||
this.sourceAddress == walletAddress -> PendingTransactionType.Outgoing
|
||||
this.destinationAddress == walletAddress -> PendingTransactionType.Incoming
|
||||
else -> PendingTransactionType.Unknown
|
||||
}
|
||||
return PendingTransaction(this, type)
|
||||
}
|
||||
|
||||
fun List<TransactionData>.toPendingTransactions(walletAddress: String): List<PendingTransaction> {
|
||||
return this.mapNotNull { it.toPendingTransaction(walletAddress) }
|
||||
}
|
||||
|
||||
fun Wallet.getPendingTransactions(type: PendingTransactionType? = null): List<PendingTransaction> {
|
||||
val txs = recentTransactions.toPendingTransactions(address)
|
||||
return when (type) {
|
||||
null -> txs
|
||||
else -> txs.filter { it.type == type }
|
||||
}
|
||||
}
|
||||
|
||||
fun Wallet.hasPendingTransactions(): Boolean {
|
||||
return getPendingTransactions().isNotEmpty()
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
package com.tangem.tap.domain.moduleMessage
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
* Base interface for conversion outputs from ModuleMessageConverter
|
||||
*/
|
||||
interface ConvertedMessage {
|
||||
val message: String
|
||||
}
|
||||
|
||||
/**
|
||||
* Dialog message used to construct a android.Dialog
|
||||
*/
|
||||
interface DialogMessage : ConvertedMessage {
|
||||
val title: String
|
||||
override val message: String
|
||||
val onPositive: String?
|
||||
val onNegative: String?
|
||||
val onNeutral: String?
|
||||
}
|
||||
|
||||
data class ConvertedStringMessage(
|
||||
override val message: String,
|
||||
) : ConvertedMessage
|
||||
|
||||
data class ConvertedDialogMessage(
|
||||
override val title: String,
|
||||
override val message: String,
|
||||
override val onPositive: String? = null,
|
||||
override val onNegative: String? = null,
|
||||
override val onNeutral: String? = null,
|
||||
) : DialogMessage
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
package com.tangem.tap.domain.moduleMessage
|
||||
|
||||
import android.content.Context
|
||||
import com.tangem.common.module.ModuleMessage
|
||||
import com.tangem.common.module.ModuleMessageConverter
|
||||
import com.tangem.domain.DomainModuleMessage
|
||||
import com.tangem.tap.domain.moduleMessage.domain.DomainMessageConverter
|
||||
|
||||
class ModuleMessageConverter(
|
||||
private val context: Context,
|
||||
) : ModuleMessageConverter<ModuleMessage, ConvertedMessage> {
|
||||
|
||||
override fun convert(message: ModuleMessage): ConvertedMessage {
|
||||
val convertedMessage = when (message) {
|
||||
is DomainModuleMessage -> DomainMessageConverter(context).convert(message)
|
||||
else -> null
|
||||
}
|
||||
return convertedMessage ?: convertUnknownMessage(message)
|
||||
}
|
||||
|
||||
private fun convertUnknownMessage(message: ModuleMessage): ConvertedMessage {
|
||||
return ConvertedStringMessage("Unknown message: ${message::class.java.simpleName}")
|
||||
}
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
package com.tangem.tap.domain.moduleMessage.domain
|
||||
|
||||
import android.content.Context
|
||||
import com.tangem.common.module.ModuleMessageConverter
|
||||
import com.tangem.domain.AddCustomTokenError
|
||||
import com.tangem.domain.DomainModuleError
|
||||
import com.tangem.domain.DomainModuleMessage
|
||||
import com.tangem.tap.domain.moduleMessage.ConvertedMessage
|
||||
import com.tangem.tap.domain.moduleMessage.domain.converter.AddCustomTokenErrorConverter
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class DomainMessageConverter(
|
||||
private val context: Context,
|
||||
) : ModuleMessageConverter<DomainModuleMessage, ConvertedMessage?> {
|
||||
|
||||
override fun convert(message: DomainModuleMessage): ConvertedMessage? {
|
||||
return when (message) {
|
||||
is DomainModuleError -> DomainErrorConverter(context).convert(message)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DomainErrorConverter(
|
||||
private val context: Context,
|
||||
) : ModuleMessageConverter<DomainModuleError, ConvertedMessage?> {
|
||||
|
||||
override fun convert(message: DomainModuleError): ConvertedMessage? = when (message) {
|
||||
is AddCustomTokenError -> AddCustomTokenErrorConverter(context).convert(message)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
package com.tangem.tap.domain.moduleMessage.domain.converter
|
||||
|
||||
import android.content.Context
|
||||
import com.tangem.common.module.ModuleMessageConverter
|
||||
import com.tangem.domain.AddCustomTokenError
|
||||
import com.tangem.domain.DomainModuleError
|
||||
import com.tangem.tap.domain.moduleMessage.ConvertedMessage
|
||||
import com.tangem.tap.domain.moduleMessage.ConvertedStringMessage
|
||||
import com.tangem.wallet.R
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class AddCustomTokenErrorConverter(
|
||||
private val context: Context,
|
||||
) : ModuleMessageConverter<DomainModuleError, ConvertedMessage?> {
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
override fun convert(message: DomainModuleError): ConvertedMessage? {
|
||||
val customTokenError = message as? AddCustomTokenError ?: throw UnsupportedOperationException()
|
||||
|
||||
val rawMessage = when (customTokenError) {
|
||||
AddCustomTokenError.Warning.PotentialScamToken -> R.string.custom_token_validation_error_not_found
|
||||
AddCustomTokenError.Warning.TokenAlreadyAdded -> R.string.custom_token_validation_error_already_added
|
||||
AddCustomTokenError.Warning.UnsupportedSolanaToken -> R.string.alert_manage_tokens_unsupported_message
|
||||
AddCustomTokenError.InvalidContractAddress -> R.string.custom_token_creation_error_invalid_contract_address
|
||||
AddCustomTokenError.NetworkIsNotSelected -> R.string.custom_token_creation_error_network_not_selected
|
||||
AddCustomTokenError.InvalidDerivationPath -> R.string.custom_token_creation_error_invalid_derivation_path
|
||||
AddCustomTokenError.InvalidDecimalsCount -> {
|
||||
context.getString(R.string.custom_token_creation_error_wrong_decimals, 30)
|
||||
}
|
||||
AddCustomTokenError.FieldIsEmpty -> R.string.custom_token_creation_error_required_field
|
||||
else -> null
|
||||
}
|
||||
|
||||
return when (rawMessage) {
|
||||
is Int -> ConvertedStringMessage(context.getString(rawMessage))
|
||||
is String -> ConvertedStringMessage(rawMessage)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
package com.tangem.tap.domain.statePrinter
|
||||
|
||||
import com.squareup.moshi.FromJson
|
||||
import com.squareup.moshi.ToJson
|
||||
import com.tangem.common.json.MoshiJsonConverter
|
||||
import com.tangem.domain.redux.state.StringStateConverter
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.features.onboarding.products.wallet.redux.BackupStep
|
||||
import com.tangem.tap.store
|
||||
import timber.log.Timber
|
||||
import java.math.BigInteger
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class OnboardingWalletStateConverter : StringStateConverter<AppState> {
|
||||
private val converter = MoshiJsonConverter(
|
||||
MoshiJsonConverter.getTangemSdkAdapters() + internalAdapters(),
|
||||
MoshiJsonConverter.getTangemSdkTypedAdapters(),
|
||||
)
|
||||
|
||||
private fun internalAdapters(): List<Any> {
|
||||
return listOf(
|
||||
BackupStepAdapter(),
|
||||
BigIntegerAdapter(),
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
override fun convert(stateHolder: AppState): String {
|
||||
val model = stateHolder.onboardingWalletState
|
||||
val json = converter.prettyPrint(model)
|
||||
|
||||
return json
|
||||
}
|
||||
}
|
||||
|
||||
fun printOnboardingWalletState() {
|
||||
val stringState = OnboardingWalletStateConverter().convert(store.state)
|
||||
Timber.d(stringState)
|
||||
}
|
||||
|
||||
class BackupStepAdapter {
|
||||
@ToJson
|
||||
fun toJson(src: BackupStep): String {
|
||||
return when (src) {
|
||||
BackupStep.AddBackupCards -> "AddBackupCards"
|
||||
BackupStep.EnterAccessCode -> "EnterAccessCode"
|
||||
BackupStep.Finished -> "Finished"
|
||||
BackupStep.InitBackup -> "InitBackup"
|
||||
BackupStep.ReenterAccessCode -> "ReenterAccessCode"
|
||||
BackupStep.ScanOriginCard -> "ScanOriginCard"
|
||||
BackupStep.SetAccessCode -> "SetAccessCode"
|
||||
is BackupStep.WriteBackupCard -> "WriteBackupCard[${src.cardNumber}]"
|
||||
BackupStep.WritePrimaryCard -> "WritePrimaryCard"
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
@FromJson
|
||||
fun fromJson(json: String): BackupStep {
|
||||
return when (json) {
|
||||
"AddBackupCards" -> BackupStep.AddBackupCards
|
||||
"EnterAccessCode" -> BackupStep.EnterAccessCode
|
||||
"Finished" -> BackupStep.Finished
|
||||
"InitBackup" -> BackupStep.InitBackup
|
||||
"ReenterAccessCode" -> BackupStep.ReenterAccessCode
|
||||
"ScanOriginCard" -> BackupStep.ScanOriginCard
|
||||
"SetAccessCode" -> BackupStep.SetAccessCode
|
||||
"WriteBackupCard[1]" -> BackupStep.WriteBackupCard(1)
|
||||
"WriteBackupCard[2]" -> BackupStep.WriteBackupCard(2)
|
||||
"WriteBackupCard[3]" -> BackupStep.WriteBackupCard(3)
|
||||
"WritePrimaryCard" -> BackupStep.WritePrimaryCard
|
||||
else -> throw UnsupportedOperationException()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class BigIntegerAdapter {
|
||||
@ToJson
|
||||
fun toJson(src: BigInteger): String {
|
||||
return src.toString()
|
||||
}
|
||||
|
||||
@FromJson
|
||||
fun fromJson(json: String): BigInteger {
|
||||
return BigInteger(json)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
package com.tangem.tap.domain.statePrinter
|
||||
|
||||
import com.tangem.common.extensions.toHexString
|
||||
import com.tangem.common.json.MoshiJsonConverter
|
||||
import com.tangem.domain.redux.state.StringStateConverter
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.store
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class ScanResponseConverter : StringStateConverter<AppState> {
|
||||
private val converter = MoshiJsonConverter.INSTANCE
|
||||
|
||||
override fun convert(stateHolder: AppState): String {
|
||||
val scanResponse = stateHolder.globalState.scanResponse ?: return "NULL"
|
||||
|
||||
val scanResponseMap = mutableMapOf<String, Any?>()
|
||||
val derivedKeysMap = mutableMapOf<String, Any?>()
|
||||
scanResponse.derivedKeys.forEach { (keyWalletPubKey, mapExPubKeys) ->
|
||||
val exPubKeysMap = mapExPubKeys.entries.map { (derivationPath, exPubKey) ->
|
||||
mapOf(
|
||||
"derivationPath" to derivationPath.rawPath,
|
||||
"extendedPublicKey" to mapOf(
|
||||
"publicKey" to exPubKey.publicKey.toHexString(),
|
||||
"chainCode" to exPubKey.chainCode.toHexString(),
|
||||
),
|
||||
)
|
||||
}
|
||||
derivedKeysMap[keyWalletPubKey.bytes.toHexString()] = exPubKeysMap
|
||||
}
|
||||
scanResponseMap["derivedKeys"] = derivedKeysMap
|
||||
|
||||
val json = converter.prettyPrint(scanResponseMap)
|
||||
|
||||
return json
|
||||
}
|
||||
}
|
||||
|
||||
fun printScanResponseState() {
|
||||
val stringState = ScanResponseConverter().convert(store.state)
|
||||
Timber.d(stringState)
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
package com.tangem.tap.domain.tasks
|
||||
|
||||
import com.tangem.blockchain.common.Wallet
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.common.core.CardSession
|
||||
import com.tangem.common.core.CardSessionRunnable
|
||||
import com.tangem.common.core.CompletionCallback
|
||||
import com.tangem.operations.CommandResponse
|
||||
import com.tangem.operations.sign.SignHashCommand
|
||||
|
||||
class TangemSignHashResponse(
|
||||
val signature: ByteArray,
|
||||
val totalSignedHashes: Int?,
|
||||
val remainingSignatures: Int?,
|
||||
) : CommandResponse
|
||||
|
||||
class SignHashTask(
|
||||
private val hash: ByteArray,
|
||||
private val publicKey: Wallet.PublicKey,
|
||||
) : CardSessionRunnable<TangemSignHashResponse> {
|
||||
override fun run(session: CardSession, callback: CompletionCallback<TangemSignHashResponse>) {
|
||||
SignHashCommand(hash, publicKey.seedKey, publicKey.derivationPath).run(session) { response ->
|
||||
|
||||
when (response) {
|
||||
is CompletionResult.Success -> {
|
||||
callback(
|
||||
CompletionResult.Success(
|
||||
TangemSignHashResponse(
|
||||
response.data.signature,
|
||||
response.data.totalSignedHashes,
|
||||
session.environment.card?.wallet(publicKey.seedKey)?.remainingSignatures,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
is CompletionResult.Failure ->
|
||||
callback(CompletionResult.Failure(response.error))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -309,7 +309,5 @@ private class CreateWalletTangemWallet(
|
|||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
val CURVES_FOR_WALLETS = listOf(EllipticCurve.Secp256k1, EllipticCurve.Ed25519)
|
||||
}
|
||||
private companion object
|
||||
}
|
||||
|
|
@ -13,9 +13,7 @@ internal data class UserWalletEncryptionKey(
|
|||
if (other !is UserWalletEncryptionKey) return false
|
||||
|
||||
if (walletId != other.walletId) return false
|
||||
if (!encryptionKey.contentEquals(other.encryptionKey)) return false
|
||||
|
||||
return true
|
||||
return encryptionKey.contentEquals(other.encryptionKey)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
|
|
|
|||
|
|
@ -1,9 +1 @@
|
|||
package com.tangem.tap.domain.userWalletList.utils
|
||||
|
||||
internal fun List<ByteArray>.containsBA(element: ByteArray?): Boolean {
|
||||
this.forEach {
|
||||
if (it.contentEquals(element)) return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
package com.tangem.tap.domain.userWalletList.utils
|
||||
|
|
@ -1,14 +1,9 @@
|
|||
package com.tangem.tap.domain.walletconnect
|
||||
|
||||
import com.github.salomonbrys.kotson.fromJson
|
||||
import com.github.salomonbrys.kotson.toMap
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonParser
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.trustwallet.walletconnect.JSONRPC_VERSION
|
||||
|
||||
object EthSignHelper {
|
||||
private val gson: Gson by lazy {
|
||||
|
|
@ -33,68 +28,4 @@ object EthSignHelper {
|
|||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class CustomJsonRpcRequest(
|
||||
val id: Long,
|
||||
val jsonrpc: String = JSONRPC_VERSION,
|
||||
val method: WCMethodExtended?,
|
||||
val params: JsonArray,
|
||||
) {
|
||||
|
||||
fun blockchainFromChainId(): Blockchain? {
|
||||
return try {
|
||||
val hex = params[0].asJsonObject.toMap()[CHAIN_ID_KEY]?.asString ?: ""
|
||||
Blockchain.fromChainId(Integer.decode(hex))
|
||||
} catch (exception: Exception) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val CHAIN_ID_KEY = "chainId"
|
||||
}
|
||||
}
|
||||
|
||||
enum class WCMethodExtended {
|
||||
@SerializedName("wc_sessionRequest")
|
||||
SESSION_REQUEST,
|
||||
|
||||
@SerializedName("wc_sessionUpdate")
|
||||
SESSION_UPDATE,
|
||||
|
||||
@SerializedName("eth_sign")
|
||||
ETH_SIGN,
|
||||
|
||||
@SerializedName("personal_sign")
|
||||
ETH_PERSONAL_SIGN,
|
||||
|
||||
@SerializedName("eth_signTypedData")
|
||||
ETH_SIGN_TYPE_DATA,
|
||||
|
||||
@SerializedName("eth_signTypedData_v4")
|
||||
ETH_SIGN_TYPE_DATA_V4,
|
||||
|
||||
@SerializedName("eth_signTransaction")
|
||||
ETH_SIGN_TRANSACTION,
|
||||
|
||||
@SerializedName("eth_sendTransaction")
|
||||
ETH_SEND_TRANSACTION,
|
||||
|
||||
@SerializedName("bnb_sign")
|
||||
BNB_SIGN,
|
||||
|
||||
@SerializedName("bnb_tx_confirmation")
|
||||
BNB_TRANSACTION_CONFIRM,
|
||||
|
||||
@SerializedName("get_accounts")
|
||||
GET_ACCOUNTS,
|
||||
|
||||
@SerializedName("trust_signTransaction")
|
||||
SIGN_TRANSACTION,
|
||||
|
||||
@SerializedName("wallet_switchEthereumChain")
|
||||
SWITCH_CHAIN,
|
||||
|
||||
;
|
||||
}
|
||||
|
|
@ -36,7 +36,7 @@ import okhttp3.OkHttpClient
|
|||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import timber.log.Timber
|
||||
import java.util.*
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.collections.set
|
||||
|
||||
|
|
@ -191,7 +191,7 @@ class WalletConnectManager {
|
|||
}
|
||||
}
|
||||
|
||||
fun removeSimilarSessions(activeData: WalletConnectActiveData) {
|
||||
private fun removeSimilarSessions(activeData: WalletConnectActiveData) {
|
||||
val sessionsToRemove = sessions.filter {
|
||||
it.value.wallet.walletPublicKey?.equals(activeData.wallet.walletPublicKey) == true &&
|
||||
it.value.peerMeta?.url == activeData.peerMeta?.url &&
|
||||
|
|
@ -206,7 +206,7 @@ class WalletConnectManager {
|
|||
activeData.client.rejectRequest(id)
|
||||
}
|
||||
|
||||
fun acceptRequest(topic: String, id: Long, data: String) {
|
||||
private fun acceptRequest(topic: String, id: Long, data: String) {
|
||||
val activeData = sessions[topic] ?: return
|
||||
activeData.client.approveRequest(id, data)
|
||||
}
|
||||
|
|
@ -368,7 +368,7 @@ class WalletConnectManager {
|
|||
}
|
||||
|
||||
@Suppress("LongMethod", "ComplexMethod")
|
||||
fun setListeners(client: WCClient) {
|
||||
private fun setListeners(client: WCClient) {
|
||||
client.onSessionRequest = { id: Long, peer: WCPeerMeta ->
|
||||
Timber.d("OnSessionRequest: $peer")
|
||||
val session = client.session
|
||||
|
|
|
|||
|
|
@ -25,11 +25,6 @@ class WalletConnectRepository(val context: Application) {
|
|||
saveSessions(sessions)
|
||||
}
|
||||
|
||||
fun removeSession(session: WalletConnectSession) {
|
||||
val sessions = loadSavedSessions().filterNot { it == session }
|
||||
saveSessions(sessions)
|
||||
}
|
||||
|
||||
fun removeSession(session: WCSession) {
|
||||
val sessions = loadSavedSessions().filterNot { it.session == session }
|
||||
saveSessions(sessions)
|
||||
|
|
|
|||
|
|
@ -31,14 +31,16 @@ import com.tangem.tap.domain.walletconnect2.domain.models.EthTransactionData
|
|||
import com.tangem.tap.domain.walletconnect2.domain.models.binance.WcBinanceTradeOrder
|
||||
import com.tangem.tap.domain.walletconnect2.domain.models.binance.WcBinanceTransferOrder
|
||||
import com.tangem.tap.features.demo.isDemoCard
|
||||
import com.tangem.tap.features.details.redux.walletconnect.*
|
||||
import com.tangem.tap.features.details.redux.walletconnect.BinanceMessageData
|
||||
import com.tangem.tap.features.details.redux.walletconnect.WcEthTransactionType
|
||||
import com.tangem.tap.features.details.redux.walletconnect.WcPersonalSignData
|
||||
import com.tangem.tap.features.details.redux.walletconnect.WcTransactionData
|
||||
import com.tangem.tap.features.details.ui.walletconnect.dialogs.PersonalSignDialogData
|
||||
import com.tangem.tap.features.details.ui.walletconnect.dialogs.TransactionRequestDialogData
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.tap.tangemSdkManager
|
||||
import com.tangem.tap.userWalletsListManager
|
||||
import com.trustwallet.walletconnect.models.ethereum.WCEthereumSignMessage.WCSignType.*
|
||||
import timber.log.Timber
|
||||
import java.math.BigDecimal
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
package com.tangem.tap.domain.walletconnect2.domain.models
|
||||
|
||||
data class ChainWithDerivation(
|
||||
val chain: String,
|
||||
val derivationPath: String?,
|
||||
)
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.tap.domain.walletconnect2.domain.models.binance
|
||||
|
||||
import com.squareup.moshi.*
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@JsonClass(generateAdapter = true)
|
||||
|
|
@ -21,12 +22,6 @@ class WcBinanceCancelOrder(
|
|||
msgs: List<Message>,
|
||||
) : WcBinanceOrder<WcBinanceCancelOrder.Message>(accountNumber, chainId, data, memo, sequence, source, msgs) {
|
||||
|
||||
enum class MessageKey(val key: String) {
|
||||
REFID("refid"),
|
||||
SENDER("sender"),
|
||||
SYMBOL("symbol"),
|
||||
}
|
||||
|
||||
data class Message(
|
||||
val refid: String,
|
||||
val sender: String,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package com.tangem.tap.domain.walletconnect2.domain.models.binance
|
||||
|
||||
import com.github.salomonbrys.kotson.*
|
||||
import com.github.salomonbrys.kotson.jsonSerializer
|
||||
import com.google.gson.JsonObject
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
|
@ -42,19 +42,6 @@ class WcBinanceTradeOrder(
|
|||
)
|
||||
}
|
||||
|
||||
val tradeOrderDeserializer = jsonDeserializer {
|
||||
WcBinanceTradeOrder.Message(
|
||||
id = it.json[WcBinanceTradeOrder.MessageKey.ID.key].string,
|
||||
orderType = it.json[WcBinanceTradeOrder.MessageKey.ORDER_TYPE.key].int,
|
||||
price = it.json[WcBinanceTradeOrder.MessageKey.PRICE.key].long,
|
||||
quantity = it.json[WcBinanceTradeOrder.MessageKey.QUANTITY.key].long,
|
||||
sender = it.json[WcBinanceTradeOrder.MessageKey.SENDER.key].string,
|
||||
side = it.json[WcBinanceTradeOrder.MessageKey.SIDE.key].int,
|
||||
symbol = it.json[WcBinanceTradeOrder.MessageKey.SYMBOL.key].string,
|
||||
timeInforce = it.json[WcBinanceTradeOrder.MessageKey.TIME_INFORCE.key].int,
|
||||
)
|
||||
}
|
||||
|
||||
val tradeOrderSerializer = jsonSerializer<WcBinanceTradeOrder.Message> {
|
||||
val jsonObject = JsonObject()
|
||||
jsonObject.addProperty(WcBinanceTradeOrder.MessageKey.ID.key, it.src.id)
|
||||
|
|
|
|||
|
|
@ -1,17 +0,0 @@
|
|||
package com.tangem.tap.domain.walletconnect2.domain.models.binance
|
||||
|
||||
data class WcBinanceTradePair(val from: String, val to: String) {
|
||||
companion object {
|
||||
fun from(symbol: String): WcBinanceTradePair? {
|
||||
val pair = symbol.split("_")
|
||||
|
||||
return if (pair.size > 1) {
|
||||
val firstParts = pair[0].split("-")
|
||||
val secondParts = pair[1].split("-")
|
||||
WcBinanceTradePair(firstParts[0], secondParts[0])
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -17,11 +17,6 @@ class WcBinanceTransferOrder(
|
|||
msgs: List<Message>,
|
||||
) : WcBinanceOrder<WcBinanceTransferOrder.Message>(accountNumber, chainId, data, memo, sequence, source, msgs) {
|
||||
|
||||
enum class MessageKey(val key: String) {
|
||||
INPUTS("inputs"),
|
||||
OUTPUTS("outputs"),
|
||||
}
|
||||
|
||||
data class Message(
|
||||
val inputs: List<Item>,
|
||||
val outputs: List<Item>,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue