Updated on 2026-08-14
This commit is contained in:
commit
3752563b2f
26 changed files with 449 additions and 420 deletions
|
|
@ -79,7 +79,8 @@ 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-65'
|
||||
implementation 'com.tangem:blockchain:develop-66'
|
||||
// implementation 'com.tangem:blockchain:0.0.1'
|
||||
implementation 'com.tangem.tangem-sdk-kotlin:core:develop-139'
|
||||
implementation 'com.tangem.tangem-sdk-kotlin:android:develop-139'
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
package com.tangem.tap.common.extensions.compose
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.core.graphics.alpha
|
||||
import androidx.core.graphics.blue
|
||||
import androidx.core.graphics.green
|
||||
import androidx.core.graphics.red
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
fun Color.argb(): Int {
|
||||
val argb = this.toArgb()
|
||||
return android.graphics.Color.argb(argb.alpha, argb.red, argb.green, argb.blue)
|
||||
}
|
||||
|
|
@ -3,7 +3,6 @@ package com.tangem.tap.domain
|
|||
import com.tangem.blockchain.blockchains.solana.RentProvider
|
||||
import com.tangem.blockchain.common.*
|
||||
import com.tangem.common.services.Result
|
||||
import com.tangem.tap.common.extensions.dispatchDebugErrorNotification
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.safeUpdate
|
||||
import com.tangem.tap.common.extensions.stripZeroPlainString
|
||||
|
|
@ -42,20 +41,31 @@ class TapWalletManager {
|
|||
by lazy { WalletManagerFactory(blockchainSdkConfig) }
|
||||
|
||||
suspend fun loadWalletData(walletManager: WalletManager) {
|
||||
handleUpdateWalletResult(walletManager.safeUpdate(), walletManager)
|
||||
}
|
||||
|
||||
suspend fun updateWallet(walletManager: WalletManager) {
|
||||
val result = walletManager.safeUpdate()
|
||||
withContext(Dispatchers.Main) {
|
||||
when (result) {
|
||||
is Result.Success ->
|
||||
store.dispatch(WalletAction.UpdateWallet.Success(result.data))
|
||||
is Result.Failure ->
|
||||
store.dispatch(WalletAction.UpdateWallet.Failure(result.error.localizedMessage))
|
||||
is Result.Success -> {
|
||||
checkForRentWarning(walletManager)
|
||||
store.dispatch(WalletAction.LoadWallet.Success(result.data))
|
||||
}
|
||||
is Result.Failure -> {
|
||||
when (result.error) {
|
||||
is TapError.WalletManagerUpdate.NoAccountError -> {
|
||||
store.dispatch(WalletAction.LoadWallet.NoAccount(
|
||||
walletManager.wallet,
|
||||
(result.error as TapError.WalletManagerUpdate.NoAccountError).customMessage
|
||||
))
|
||||
}
|
||||
else -> {
|
||||
store.dispatch(WalletAction.LoadWallet.Failure(
|
||||
walletManager.wallet,
|
||||
result.error.localizedMessage
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
suspend fun loadFiatRate(fiatCurrency: FiatCurrencyName, wallet: Wallet) {
|
||||
|
|
@ -65,11 +75,6 @@ class TapWalletManager {
|
|||
loadFiatRate(fiatCurrency, currencies)
|
||||
}
|
||||
|
||||
suspend fun loadFiatRate(fiatCurrency: FiatCurrencyName, currency: Currency) {
|
||||
val currencies = listOf(currency)
|
||||
loadFiatRate(fiatCurrency, currencies)
|
||||
}
|
||||
|
||||
suspend fun loadFiatRate(fiatCurrency: FiatCurrencyName, currencies: List<Currency>) {
|
||||
val results = mutableListOf<Pair<Currency, Result<BigDecimal>?>>()
|
||||
currencies.forEach {
|
||||
|
|
@ -79,7 +84,7 @@ class TapWalletManager {
|
|||
}
|
||||
|
||||
suspend fun onCardScanned(data: ScanResponse) {
|
||||
store.state.globalState.feedbackManager?.infoHolder?.setCardInfo(data.card)
|
||||
store.state.globalState.feedbackManager?.infoHolder?.setCardInfo(data)
|
||||
updateConfigManager(data)
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
|
|
@ -224,36 +229,6 @@ class TapWalletManager {
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun handleUpdateWalletResult(result: Result<Wallet>, walletManager: WalletManager) {
|
||||
withContext(Dispatchers.Main) {
|
||||
when (result) {
|
||||
is Result.Success -> {
|
||||
checkForRentWarning(walletManager)
|
||||
store.dispatch(WalletAction.LoadWallet.Success(result.data))
|
||||
}
|
||||
is Result.Failure -> {
|
||||
val error = (result.error as? TapError) ?: TapError.UnknownError
|
||||
when (error) {
|
||||
TapError.NoInternetConnection -> {
|
||||
store.dispatch(WalletAction.LoadData.Failure(error))
|
||||
}
|
||||
is TapError.WalletManagerUpdate.NoAccountError -> {
|
||||
store.dispatch(WalletAction.LoadWallet
|
||||
.NoAccount(walletManager.wallet, error.customMessage))
|
||||
}
|
||||
is TapError.WalletManagerUpdate.InternalError -> {
|
||||
store.dispatch(WalletAction.LoadWallet
|
||||
.Failure(walletManager.wallet, error.customMessage))
|
||||
}
|
||||
else -> {
|
||||
store.dispatchDebugErrorNotification(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkForRentWarning(walletManager: WalletManager) {
|
||||
val rentProvider = walletManager as? RentProvider ?: return
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.tangem.common.CompletionResult
|
|||
import com.tangem.common.card.EllipticCurve
|
||||
import com.tangem.common.core.CardSession
|
||||
import com.tangem.common.core.CardSessionRunnable
|
||||
import com.tangem.common.core.TangemSdkError
|
||||
import com.tangem.operations.CommandResponse
|
||||
import com.tangem.operations.wallet.CreateWalletResponse
|
||||
import com.tangem.operations.wallet.CreateWalletTask
|
||||
|
|
@ -22,6 +23,11 @@ class CreateWalletsTask(
|
|||
private val createdWalletsResponses = mutableListOf<CreateWalletResponse>()
|
||||
|
||||
override fun run(session: CardSession, callback: (result: CompletionResult<CreateWalletsResponse>) -> Unit) {
|
||||
if (curves.isEmpty()){
|
||||
callback(CompletionResult.Failure(TangemSdkError.WalletIsNotCreated()))
|
||||
return
|
||||
}
|
||||
|
||||
val curve = curves[createdWalletsResponses.size]
|
||||
createWallet(curve, session, callback)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,12 +7,10 @@ import android.os.Build
|
|||
import com.tangem.Log
|
||||
import com.tangem.TangemSdkLogger
|
||||
import com.tangem.blockchain.common.*
|
||||
import com.tangem.common.card.Card
|
||||
import com.tangem.tap.common.extensions.sendEmail
|
||||
import com.tangem.tap.common.extensions.stripZeroPlainString
|
||||
import com.tangem.tap.domain.TapWorkarounds
|
||||
import com.tangem.tap.features.feedback.EmailData.Companion.appendBlankLine
|
||||
import com.tangem.tap.features.feedback.EmailData.Companion.appendDelimiter
|
||||
import com.tangem.tap.domain.tasks.product.ScanResponse
|
||||
import com.tangem.wallet.R
|
||||
import timber.log.Timber
|
||||
import java.io.File
|
||||
|
|
@ -86,16 +84,19 @@ class FeedbackManager(
|
|||
class TangemLogCollector : TangemSdkLogger {
|
||||
private val dateFormatter = SimpleDateFormat("HH:mm:ss.SSS")
|
||||
private val logs = mutableListOf<String>()
|
||||
private val mutex = Object()
|
||||
|
||||
override fun log(message: () -> String, level: Log.Level) {
|
||||
val time = dateFormatter.format(Date())
|
||||
logs.add("$time: ${message()}\n")
|
||||
synchronized(mutex) {
|
||||
logs.add("$time: ${message()}\n")
|
||||
}
|
||||
}
|
||||
|
||||
fun getLogs(): List<String> = logs.toList()
|
||||
fun getLogs(): List<String> = synchronized(mutex) { logs.toList() }
|
||||
|
||||
fun clearLogs() {
|
||||
logs.clear()
|
||||
synchronized(mutex) { logs.clear() }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -105,8 +106,6 @@ class AdditionalEmailInfo {
|
|||
var address: String = "",
|
||||
var explorerLink: String = "",
|
||||
var host: String = "",
|
||||
// var outputsCount: String = ""
|
||||
// var transactionHex: String = ""
|
||||
)
|
||||
|
||||
var appVersion: String = ""
|
||||
|
|
@ -115,6 +114,7 @@ class AdditionalEmailInfo {
|
|||
var cardId: String = ""
|
||||
var cardFirmwareVersion: String = ""
|
||||
var cardIssuer: String = ""
|
||||
var cardBlockchain: String = ""
|
||||
|
||||
// wallets
|
||||
internal val walletsInfo = mutableListOf<EmailWalletInfo>()
|
||||
|
|
@ -141,12 +141,13 @@ class AdditionalEmailInfo {
|
|||
}
|
||||
}
|
||||
|
||||
fun setCardInfo(card: Card) {
|
||||
cardId = card.cardId
|
||||
cardFirmwareVersion = card.firmwareVersion.stringValue
|
||||
cardIssuer = card.issuer.name
|
||||
signedHashesCount = card.wallets
|
||||
.joinToString(";") { "${it.curve?.curve} - ${it.totalSignedHashes}" }
|
||||
fun setCardInfo(data: ScanResponse) {
|
||||
cardId = data.card.cardId
|
||||
cardBlockchain = data.walletData?.blockchain ?: ""
|
||||
cardFirmwareVersion = data.card.firmwareVersion.stringValue
|
||||
cardIssuer = data.card.issuer.name
|
||||
signedHashesCount = data.card.wallets
|
||||
.joinToString("; ") { "${it.curve.curve} - ${it.totalSignedHashes}" }
|
||||
}
|
||||
|
||||
fun setWalletsInfo(walletManagers: List<WalletManager>) {
|
||||
|
|
@ -217,33 +218,23 @@ interface EmailData {
|
|||
fun joinTogether(context: Context, infoHolder: AdditionalEmailInfo): String {
|
||||
return StringBuilder().apply {
|
||||
append(context.getString(mainMessageResId))
|
||||
append("\n\n\n\n")
|
||||
appendLine(3)
|
||||
append(context.getString(getDataCollectionMessageResId()))
|
||||
appendLine()
|
||||
append(createOptionalMessage(infoHolder))
|
||||
}.toString()
|
||||
}
|
||||
|
||||
companion object {
|
||||
internal fun StringBuilder.appendDelimiter() = append("----------\n")
|
||||
internal fun StringBuilder.appendBlankLine() = append("\n")
|
||||
}
|
||||
}
|
||||
|
||||
class RateCanBeBetterEmail : EmailData {
|
||||
override val subjectResId: Int = R.string.feedback_subject_rate_negative
|
||||
override val mainMessageResId: Int = R.string.feedback_preface_rate_negative
|
||||
|
||||
override fun createOptionalMessage(infoHolder: AdditionalEmailInfo): String {
|
||||
val walletInfo = infoHolder.walletsInfo[0]
|
||||
return StringBuilder().apply {
|
||||
appendKeyValue("Card ID", infoHolder.cardId)
|
||||
appendKeyValue("Blockchain", walletInfo.blockchain.fullName)
|
||||
appendBlankLine()
|
||||
appendKeyValue("Phone model", infoHolder.phoneModel)
|
||||
appendKeyValue("OS version", infoHolder.osVersion)
|
||||
appendKeyValue("App version", infoHolder.appVersion)
|
||||
}.toString()
|
||||
}
|
||||
override fun createOptionalMessage(infoHolder: AdditionalEmailInfo): String = EmailDataBuilder(infoHolder)
|
||||
.appendCardInfo()
|
||||
.appendLine()
|
||||
.appendPhoneInfo()
|
||||
.build()
|
||||
}
|
||||
|
||||
class ScanFailsEmail : EmailData {
|
||||
|
|
@ -251,51 +242,31 @@ class ScanFailsEmail : EmailData {
|
|||
override val subjectResId: Int = R.string.feedback_subject_scan_failed
|
||||
override val mainMessageResId: Int = R.string.feedback_preface_scan_failed
|
||||
|
||||
override fun joinTogether(context: Context, infoHolder: AdditionalEmailInfo): String {
|
||||
return StringBuilder().apply {
|
||||
append(context.getString(mainMessageResId))
|
||||
append("\n\n\n\n")
|
||||
append(createOptionalMessage(infoHolder))
|
||||
}.toString()
|
||||
}
|
||||
override fun joinTogether(context: Context, infoHolder: AdditionalEmailInfo): String = StringBuilder().apply {
|
||||
append(context.getString(mainMessageResId))
|
||||
appendLine(4)
|
||||
append(createOptionalMessage(infoHolder))
|
||||
}.toString()
|
||||
|
||||
override fun createOptionalMessage(infoHolder: AdditionalEmailInfo): String {
|
||||
return StringBuilder().apply {
|
||||
appendBlankLine()
|
||||
appendKeyValue("Phone model", infoHolder.phoneModel)
|
||||
appendKeyValue("OS version", infoHolder.osVersion)
|
||||
appendKeyValue("App version", infoHolder.appVersion)
|
||||
}.toString()
|
||||
}
|
||||
override fun createOptionalMessage(infoHolder: AdditionalEmailInfo): String = EmailDataBuilder(infoHolder)
|
||||
.appendPhoneInfo()
|
||||
.build()
|
||||
}
|
||||
|
||||
class SendTransactionFailedEmail(private val error: String) : EmailData {
|
||||
class SendTransactionFailedEmail(
|
||||
val error: String
|
||||
) : EmailData {
|
||||
|
||||
override val subjectResId: Int = R.string.feedback_subject_tx_failed
|
||||
override val mainMessageResId: Int = R.string.feedback_preface_tx_failed
|
||||
|
||||
override fun createOptionalMessage(infoHolder: AdditionalEmailInfo): String {
|
||||
val walletInfo = infoHolder.onSendErrorWalletInfo ?: AdditionalEmailInfo.EmailWalletInfo()
|
||||
return StringBuilder().apply {
|
||||
appendKeyValue("Card ID", infoHolder.cardId)
|
||||
appendKeyValue("Firmware version", infoHolder.cardFirmwareVersion)
|
||||
appendKeyValue("Signed hashes", infoHolder.signedHashesCount)
|
||||
appendDelimiter()
|
||||
appendKeyValue("Blockchain", walletInfo.blockchain.fullName)
|
||||
appendKeyValue("Host", walletInfo.host)
|
||||
appendKeyValue("Token", infoHolder.token)
|
||||
appendKeyValue("Error", error)
|
||||
appendDelimiter()
|
||||
appendKeyValue("Source address", walletInfo.address)
|
||||
appendKeyValue("Destination address", infoHolder.destinationAddress)
|
||||
appendKeyValue("Amount", infoHolder.amount)
|
||||
appendKeyValue("Fee", infoHolder.fee)
|
||||
appendBlankLine()
|
||||
appendKeyValue("Phone model", infoHolder.phoneModel)
|
||||
appendKeyValue("OS version", infoHolder.osVersion)
|
||||
appendKeyValue("App version", infoHolder.appVersion)
|
||||
// appendKeyValue("Transaction HEX", infoHolder.transactionHex)
|
||||
}.toString()
|
||||
}
|
||||
override fun createOptionalMessage(infoHolder: AdditionalEmailInfo): String = EmailDataBuilder(infoHolder)
|
||||
.appendCardInfo()
|
||||
.appendDelimiter()
|
||||
.appendTxFailedBlockchainInfo(error)
|
||||
.appendLine()
|
||||
.appendPhoneInfo()
|
||||
.build()
|
||||
}
|
||||
|
||||
class FeedbackEmail : EmailData {
|
||||
|
|
@ -316,37 +287,88 @@ class FeedbackEmail : EmailData {
|
|||
isS2CCard = TapWorkarounds.isStart2CoinIssuer(infoHolder.cardIssuer)
|
||||
}
|
||||
|
||||
override fun createOptionalMessage(infoHolder: AdditionalEmailInfo): String {
|
||||
val builder = StringBuilder()
|
||||
override fun createOptionalMessage(infoHolder: AdditionalEmailInfo): String = EmailDataBuilder(infoHolder)
|
||||
.appendCardInfo()
|
||||
.appendWalletsInfo()
|
||||
.appendLine()
|
||||
.appendPhoneInfo()
|
||||
.build()
|
||||
}
|
||||
|
||||
|
||||
class EmailDataBuilder(
|
||||
private val infoHolder: AdditionalEmailInfo
|
||||
) {
|
||||
val builder = StringBuilder()
|
||||
|
||||
fun appendDelimiter(): EmailDataBuilder {
|
||||
builder.appendDelimiter()
|
||||
return this
|
||||
}
|
||||
|
||||
fun appendLine(count: Int = 1): EmailDataBuilder {
|
||||
builder.appendLine(count)
|
||||
return this
|
||||
}
|
||||
|
||||
fun appendCardInfo(): EmailDataBuilder {
|
||||
builder.appendKeyValue("Card ID", infoHolder.cardId)
|
||||
builder.appendKeyValue("Firmware version", infoHolder.cardFirmwareVersion)
|
||||
builder.appendKeyValue("Card Blockchain", infoHolder.cardBlockchain)
|
||||
builder.appendKeyValue("Signed hashes", infoHolder.signedHashesCount)
|
||||
return this
|
||||
}
|
||||
|
||||
fun appendWalletsInfo(): EmailDataBuilder {
|
||||
infoHolder.walletsInfo.forEach {
|
||||
builder.appendDelimiter()
|
||||
builder.appendKeyValue("Blockchain", it.blockchain.fullName)
|
||||
builder.appendKeyValue("Host", it.host)
|
||||
builder.appendKeyValue("Wallet address", it.address)
|
||||
builder.appendKeyValue("Explorer link", it.explorerLink)
|
||||
}
|
||||
builder.appendBlankLine()
|
||||
|
||||
infoHolder.tokens.forEach { tokens ->
|
||||
builder.appendDelimiter()
|
||||
builder.appendKeyValue("Blockchain", tokens.key.fullName)
|
||||
builder.appendKeyValue("Tokens", tokens.value.map { "${it.name} - ${it.symbol}" }.toString())
|
||||
infoHolder.tokens[it.blockchain]?.let { tokens ->
|
||||
builder.append("Tokens:")
|
||||
appendLine()
|
||||
tokens.forEach { token ->
|
||||
builder.appendKeyValue("Name", token.name)
|
||||
builder.appendKeyValue("Contract address", token.contractAddress)
|
||||
}
|
||||
}
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
fun appendTxFailedBlockchainInfo(error: String): EmailDataBuilder {
|
||||
val walletInfo = infoHolder.onSendErrorWalletInfo ?: AdditionalEmailInfo.EmailWalletInfo()
|
||||
builder.appendKeyValue("Blockchain", walletInfo.blockchain.fullName)
|
||||
builder.appendKeyValue("Host", walletInfo.host)
|
||||
builder.appendKeyValue("Token", infoHolder.token)
|
||||
builder.appendKeyValue("Error", error)
|
||||
builder.appendDelimiter()
|
||||
builder.appendBlankLine()
|
||||
// appendKeyValue("Outputs count", infoHolder.outputsCount)
|
||||
builder.appendKeyValue("Source address", walletInfo.address)
|
||||
builder.appendKeyValue("Destination address", infoHolder.destinationAddress)
|
||||
builder.appendKeyValue("Amount", infoHolder.amount)
|
||||
builder.appendKeyValue("Fee", infoHolder.fee)
|
||||
return this
|
||||
}
|
||||
|
||||
fun appendPhoneInfo(): EmailDataBuilder {
|
||||
builder.appendKeyValue("Phone model", infoHolder.phoneModel)
|
||||
builder.appendKeyValue("OS version", infoHolder.osVersion)
|
||||
builder.appendKeyValue("App version", infoHolder.appVersion)
|
||||
|
||||
return builder.toString()
|
||||
return this
|
||||
}
|
||||
|
||||
fun build(): String = builder.toString()
|
||||
}
|
||||
|
||||
private fun StringBuilder.appendKeyValue(key: String, value: String): StringBuilder {
|
||||
return if (value.isNotBlank()) this.append("$key: $value\n") else this
|
||||
}
|
||||
|
||||
private fun StringBuilder.appendDelimiter(): StringBuilder = append("----------\n")
|
||||
|
||||
private fun StringBuilder.appendLine(count: Int = 1): StringBuilder {
|
||||
return append(List(count) { "\n" }.joinToString(separator = ""))
|
||||
}
|
||||
|
|
@ -1,5 +1,11 @@
|
|||
package com.tangem.tap.features.home.compose
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Typeface
|
||||
import android.util.TypedValue
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.Text
|
||||
|
|
@ -14,6 +20,9 @@ import androidx.compose.ui.text.font.FontWeight
|
|||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import com.tangem.tangem_sdk_new.extensions.dpToPx
|
||||
import com.tangem.tap.common.extensions.compose.argb
|
||||
import com.tangem.wallet.R
|
||||
|
||||
@Composable
|
||||
|
|
@ -22,8 +31,9 @@ fun StoriesGeneralContent(
|
|||
subtitleText: String,
|
||||
imageSource: Int?,
|
||||
isDarkBackground: Boolean,
|
||||
subtitleTextId: Int? = null,
|
||||
imageComposable: (() -> Unit)? = null,
|
||||
) {
|
||||
) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center,
|
||||
|
|
@ -45,15 +55,7 @@ fun StoriesGeneralContent(
|
|||
|
||||
Spacer(modifier = Modifier.size(16.dp))
|
||||
|
||||
Text(
|
||||
text = subtitleText,
|
||||
fontSize = 20.sp,
|
||||
fontWeight = FontWeight.Normal,
|
||||
modifier = Modifier
|
||||
.padding(start = 40.dp, end = 40.dp),
|
||||
color = Color(0xFFA6AAAD),
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
SubtitleText(subtitleText, subtitleTextId)
|
||||
|
||||
Spacer(modifier = Modifier.size(25.dp))
|
||||
|
||||
|
|
@ -61,7 +63,7 @@ fun StoriesGeneralContent(
|
|||
Image(
|
||||
painter = painterResource(id = imageSource),
|
||||
contentDescription = null,
|
||||
contentScale = if(isDarkBackground) ContentScale.Inside else ContentScale.FillWidth,
|
||||
contentScale = if (isDarkBackground) ContentScale.Inside else ContentScale.FillWidth,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
}
|
||||
|
|
@ -69,6 +71,34 @@ fun StoriesGeneralContent(
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SubtitleText(subtitleText: String, subtitleTextId: Int?) {
|
||||
val color = Color(0xFFA6AAAD)
|
||||
|
||||
if (subtitleTextId == null) {
|
||||
Text(
|
||||
text = subtitleText,
|
||||
fontSize = 20.sp,
|
||||
fontWeight = FontWeight.Normal,
|
||||
modifier = Modifier.padding(start = 40.dp, end = 40.dp),
|
||||
color = color,
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
} else {
|
||||
HtmlText(subtitleTextId) { context ->
|
||||
val padding = context.dpToPx(40f).toInt()
|
||||
TextView(context).apply {
|
||||
layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
setPadding(padding, 0, padding, 0)
|
||||
textAlignment = View.TEXT_ALIGNMENT_CENTER
|
||||
typeface = Typeface.DEFAULT
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_SP, 20f)
|
||||
setTextColor(color.argb())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun StoriesRevolutionaryWallet() {
|
||||
StoriesGeneralContent(
|
||||
|
|
@ -85,6 +115,7 @@ fun StoriesUltraSecureBackup() {
|
|||
titleText = stringResource(id = R.string.story_backup_title),
|
||||
subtitleText = stringResource(id = R.string.story_backup_description),
|
||||
imageSource = R.drawable.floating_cards,
|
||||
subtitleTextId = R.string.story_backup_description,
|
||||
isDarkBackground = false
|
||||
)
|
||||
}
|
||||
|
|
@ -117,4 +148,13 @@ fun StoriesWalletForEveryone() {
|
|||
imageSource = R.drawable.wallet_for_everyone,
|
||||
isDarkBackground = true
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun HtmlText(
|
||||
stringResId: Int,
|
||||
modifier: Modifier = Modifier,
|
||||
factory: (Context) -> TextView
|
||||
) {
|
||||
AndroidView(factory, modifier) { it.text = it.context.getText(stringResId) }
|
||||
}
|
||||
|
|
@ -202,11 +202,11 @@ private fun sendTransaction(
|
|||
}
|
||||
scope.launch(Dispatchers.IO) {
|
||||
withContext(Dispatchers.Main) {
|
||||
dispatch(WalletAction.UpdateWallet(walletManager.wallet.blockchain))
|
||||
dispatch(WalletAction.LoadWallet(walletManager.wallet.blockchain))
|
||||
}
|
||||
delay(10000)
|
||||
withContext(Dispatchers.Main) {
|
||||
dispatch(WalletAction.UpdateWallet(walletManager.wallet.blockchain))
|
||||
dispatch(WalletAction.LoadWallet(walletManager.wallet.blockchain))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,14 +74,8 @@ sealed class WalletAction : Action {
|
|||
class CheckRemainingSignatures(val remainingSignatures: Int?) : Warnings()
|
||||
}
|
||||
|
||||
data class UpdateWallet(val blockchain: Blockchain? = null) : WalletAction() {
|
||||
object ScheduleUpdatingWallet : WalletAction()
|
||||
data class Success(val wallet: Wallet) : WalletAction()
|
||||
data class Failure(val errorMessage: String? = null) : WalletAction()
|
||||
}
|
||||
|
||||
data class LoadFiatRate(
|
||||
val wallet: Wallet? = null, val currency: Currency? = null,
|
||||
val wallet: Wallet? = null, val currencyList: List<Currency>? = null,
|
||||
) : WalletAction() {
|
||||
data class Success(val fiatRate: Pair<Currency, BigDecimal?>) : WalletAction()
|
||||
object Failure : WalletAction()
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import android.graphics.Bitmap
|
|||
import com.tangem.blockchain.common.*
|
||||
import com.tangem.blockchain.common.address.AddressType
|
||||
import com.tangem.blockchain.extensions.isAboveZero
|
||||
import com.tangem.common.extensions.isZero
|
||||
import com.tangem.tap.common.entities.Button
|
||||
import com.tangem.tap.common.extensions.toQrCode
|
||||
import com.tangem.tap.common.redux.StateDialog
|
||||
|
|
@ -32,11 +33,11 @@ data class WalletState(
|
|||
val hashesCountVerified: Boolean? = null,
|
||||
val walletDialog: StateDialog? = null,
|
||||
val mainWarningsList: List<WarningMessage> = mutableListOf(),
|
||||
val wallets: List<WalletData> = emptyList(),
|
||||
val walletsData: List<WalletData> = emptyList(),
|
||||
val walletManagers: List<WalletManager> = emptyList(),
|
||||
val isMultiwalletAllowed: Boolean = false,
|
||||
val cardCurrency: CryptoCurrencyName? = null,
|
||||
val selectedWallet: Currency? = null,
|
||||
val selectedCurrency: Currency? = null,
|
||||
val primaryBlockchain: Blockchain? = null,
|
||||
val primaryToken: Token? = null,
|
||||
val isTestnet: Boolean = false,
|
||||
|
|
@ -51,7 +52,7 @@ data class WalletState(
|
|||
val isTangemTwins: Boolean
|
||||
get() = store.state.globalState.scanResponse?.isTangemTwins() == true
|
||||
|
||||
val primaryWallet = if (wallets.isNotEmpty()) wallets[0] else null
|
||||
val primaryWallet = if (walletsData.isNotEmpty()) walletsData[0] else null
|
||||
|
||||
val shouldShowDetails: Boolean =
|
||||
primaryWallet?.currencyData?.status != BalanceStatus.EmptyCard &&
|
||||
|
|
@ -61,7 +62,7 @@ data class WalletState(
|
|||
get() = walletManagers.map { it.wallet.blockchain }
|
||||
|
||||
val currencies: List<Currency>
|
||||
get() = wallets.mapNotNull { it.currency }
|
||||
get() = walletsData.mapNotNull { it.currency }
|
||||
|
||||
fun getWalletManager(token: Token?): WalletManager? {
|
||||
if (token == null) return null
|
||||
|
|
@ -79,21 +80,21 @@ data class WalletState(
|
|||
|
||||
fun getWalletData(currency: Currency?): WalletData? {
|
||||
if (currency == null) return null
|
||||
return wallets.find { it.currency == currency }
|
||||
return walletsData.find { it.currency == currency }
|
||||
}
|
||||
|
||||
fun getWalletData(blockchain: Blockchain?): WalletData? {
|
||||
if (blockchain == null) return null
|
||||
return wallets.find { (it.currency as? Currency.Blockchain)?.blockchain == blockchain }
|
||||
return walletsData.find { (it.currency as? Currency.Blockchain)?.blockchain == blockchain }
|
||||
}
|
||||
|
||||
fun getWalletData(token: Token?): WalletData? {
|
||||
if (token == null) return null
|
||||
return wallets.find { (it.currency as? Currency.Token)?.token == token }
|
||||
return walletsData.find { (it.currency as? Currency.Token)?.token == token }
|
||||
}
|
||||
|
||||
fun getSelectedWalletData(): WalletData? {
|
||||
return wallets.find { it.currency == selectedWallet }
|
||||
return walletsData.find { it.currency == selectedCurrency }
|
||||
}
|
||||
|
||||
fun canBeRemoved(walletData: WalletData?): Boolean {
|
||||
|
|
@ -132,9 +133,9 @@ data class WalletState(
|
|||
}
|
||||
|
||||
fun replaceWalletInWallets(walletData: WalletData?): List<WalletData> {
|
||||
if (walletData == null) return wallets
|
||||
if (walletData == null) return walletsData
|
||||
var changed = false
|
||||
val updatedWallets = wallets.map {
|
||||
val updatedWallets = walletsData.map {
|
||||
if (it.currency == walletData.currency) {
|
||||
changed = true
|
||||
walletData
|
||||
|
|
@ -142,12 +143,12 @@ data class WalletState(
|
|||
it
|
||||
}
|
||||
}
|
||||
return if (changed) updatedWallets else wallets + walletData
|
||||
return if (changed) updatedWallets else walletsData + walletData
|
||||
}
|
||||
|
||||
fun replaceSomeWallets(newWallets: List<WalletData>): List<WalletData> {
|
||||
val remainingWallets: MutableList<WalletData> = newWallets.toMutableList()
|
||||
val updatedWallets = wallets.map { wallet ->
|
||||
val updatedWallets = walletsData.map { wallet ->
|
||||
val newWallet = newWallets
|
||||
.firstOrNull { wallet.currency == it.currency }
|
||||
if (newWallet == null) {
|
||||
|
|
@ -248,17 +249,26 @@ data class WalletData(
|
|||
val currencyData: BalanceWidgetData = BalanceWidgetData(),
|
||||
val updatingWallet: Boolean = false,
|
||||
val tradeCryptoState: TradeCryptoState = TradeCryptoState(),
|
||||
val allowToSend: Boolean = true,
|
||||
val fiatRateString: String? = null,
|
||||
val fiatRate: BigDecimal? = null,
|
||||
val mainButton: WalletMainButton = WalletMainButton.SendButton(false),
|
||||
val currency: Currency,
|
||||
val walletRent: WalletRent? = null,
|
||||
val warningRent: WalletRent? = null,
|
||||
) {
|
||||
fun shouldShowMultipleAddress(): Boolean {
|
||||
val listOfAddresses = walletAddresses?.list ?: return false
|
||||
return listOfAddresses.size > 1
|
||||
}
|
||||
|
||||
fun shouldShowCoinAmountWarning(): Boolean = when (currency) {
|
||||
is Currency.Blockchain -> false
|
||||
is Currency.Token -> blockchainAmountIsEmpty() && !tokenAmountIsEmpty()
|
||||
}
|
||||
|
||||
fun shouldEnableTokenSendButton(): Boolean = !blockchainAmountIsEmpty() || !tokenAmountIsEmpty()
|
||||
|
||||
private fun blockchainAmountIsEmpty(): Boolean = currencyData.blockchainAmount?.isZero() ?: false
|
||||
private fun tokenAmountIsEmpty(): Boolean = currencyData.amount?.isZero() == true
|
||||
}
|
||||
|
||||
data class WalletRent(
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package com.tangem.tap.features.wallet.redux.middlewares
|
|||
import com.tangem.blockchain.common.*
|
||||
import com.tangem.blockchain.extensions.Result
|
||||
import com.tangem.common.extensions.isZero
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.safeUpdate
|
||||
import com.tangem.tap.common.redux.global.GlobalState
|
||||
import com.tangem.tap.common.redux.navigation.AppScreen
|
||||
|
|
@ -47,7 +46,7 @@ class MultiWalletMiddleware {
|
|||
globalState.scanResponse?.card?.cardId?.let {
|
||||
currenciesRepository.saveAddedToken(it, action.token)
|
||||
}
|
||||
addToken(action.token, walletState, globalState)
|
||||
addTokens(listOf(action.token), walletState, globalState)
|
||||
}
|
||||
is WalletAction.MultiWallet.AddTokens -> {
|
||||
addTokens(action.tokens, walletState, globalState)
|
||||
|
|
@ -62,7 +61,9 @@ class MultiWalletMiddleware {
|
|||
}
|
||||
}
|
||||
}
|
||||
store.dispatch(WalletAction.LoadFiatRate(currency = Currency.Blockchain(action.blockchain)))
|
||||
store.dispatch(WalletAction.LoadFiatRate(
|
||||
currencyList = listOf(Currency.Blockchain(action.blockchain)))
|
||||
)
|
||||
store.dispatch(WalletAction.LoadWallet(action.blockchain)
|
||||
)
|
||||
}
|
||||
|
|
@ -172,80 +173,39 @@ class MultiWalletMiddleware {
|
|||
}
|
||||
}
|
||||
|
||||
private fun addToken(token: Token, walletState: WalletState?, globalState: GlobalState?) {
|
||||
private fun addTokens(tokens: List<Token>, walletState: WalletState?, globalState: GlobalState?) {
|
||||
val scanResponse = globalState?.scanResponse ?: return
|
||||
val wmFactory = globalState.tapWalletManager.walletManagerFactory
|
||||
|
||||
val walletManager = walletState?.getWalletManager(token)
|
||||
?: globalState.tapWalletManager.walletManagerFactory.makeWalletManagerForApp(
|
||||
scanResponse,
|
||||
token.blockchain
|
||||
)?.also { walletManager ->
|
||||
store.dispatch(WalletAction.MultiWallet.AddWalletManagers(walletManager))
|
||||
store.dispatch(WalletAction.MultiWallet.AddBlockchain(walletManager.wallet.blockchain))
|
||||
}
|
||||
|
||||
store.dispatch(WalletAction.LoadFiatRate(currency = Currency.Token(token)))
|
||||
|
||||
scope.launch {
|
||||
when (val result = walletManager?.addToken(token)) {
|
||||
is Result.Success -> {
|
||||
store.dispatchOnMain(WalletAction.MultiWallet.TokenLoaded(result.data, token))
|
||||
val groupedTokens = tokens.groupBy { it.blockchain }
|
||||
val walletManagers = groupedTokens.mapNotNull { entry ->
|
||||
val blockchain = entry.key
|
||||
val tokensList = entry.value
|
||||
val walletManager = walletState?.getWalletManager(blockchain)
|
||||
?: wmFactory.makeWalletManagerForApp(scanResponse, blockchain)?.also {
|
||||
store.dispatch(WalletAction.MultiWallet.AddWalletManagers(it))
|
||||
store.dispatch(WalletAction.MultiWallet.AddBlockchain(blockchain))
|
||||
}
|
||||
is Result.Failure -> {
|
||||
when (val result = walletManager.safeUpdate()) {
|
||||
is com.tangem.common.services.Result.Success -> {
|
||||
val tokenAmount = result.data.getTokenAmount(token) ?: return@launch
|
||||
store.dispatchOnMain(WalletAction.MultiWallet.TokenLoaded(tokenAmount, token))
|
||||
}
|
||||
is com.tangem.common.services.Result.Failure -> {
|
||||
}
|
||||
store.dispatch(WalletAction.LoadFiatRate(currencyList = tokensList.map { Currency.Token(it) }))
|
||||
walletManager?.apply { addTokens(tokensList) }
|
||||
}
|
||||
scope.launch {
|
||||
walletManagers.forEach { walletManager ->
|
||||
when (val result = walletManager.safeUpdate()) {
|
||||
is com.tangem.common.services.Result.Success -> {
|
||||
val wallet = result.data
|
||||
wallet.getTokens()
|
||||
.filter { tokens.contains(it) }
|
||||
.mapNotNull { token -> wallet.getTokenAmount(token)?.let { Pair(token, it) } }
|
||||
.forEach {
|
||||
withContext(Dispatchers.Main) {
|
||||
store.dispatch(WalletAction.MultiWallet.TokenLoaded(it.second, it.first))
|
||||
}
|
||||
}
|
||||
}
|
||||
is com.tangem.common.services.Result.Failure -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun addTokens(
|
||||
tokens: List<Token>,
|
||||
walletState: WalletState?,
|
||||
globalState: GlobalState?,
|
||||
) {
|
||||
val scanResponse = globalState?.scanResponse ?: return
|
||||
|
||||
val tokensWithManagers = tokens.map { token ->
|
||||
val walletManager = walletState?.getWalletManager(token)
|
||||
?: globalState.tapWalletManager.walletManagerFactory.makeWalletManagerForApp(
|
||||
scanResponse,
|
||||
token.blockchain
|
||||
)?.also { walletManager ->
|
||||
store.dispatch(WalletAction.MultiWallet.AddWalletManagers(walletManager))
|
||||
store.dispatch(WalletAction.MultiWallet.AddBlockchain(walletManager.wallet.blockchain))
|
||||
}
|
||||
store.dispatch(
|
||||
WalletAction.LoadFiatRate(currency = Currency.Token(token))
|
||||
)
|
||||
TokenWithManager(token, walletManager)
|
||||
}
|
||||
scope.launch {
|
||||
tokensWithManagers.forEach {
|
||||
when (val result = it.walletManager?.addToken(it.token)) {
|
||||
is Result.Success -> {
|
||||
store.dispatchOnMain(WalletAction.MultiWallet.TokenLoaded(result.data, it.token))
|
||||
}
|
||||
is Result.Failure -> {
|
||||
when (val result = it.walletManager.safeUpdate()) {
|
||||
is com.tangem.common.services.Result.Success -> {
|
||||
val tokenAmount = result.data.getTokenAmount(it.token) ?: return@launch
|
||||
store.dispatchOnMain(WalletAction.MultiWallet.TokenLoaded(tokenAmount, it.token))
|
||||
}
|
||||
is com.tangem.common.services.Result.Failure -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private data class TokenWithManager(val token: Token, val walletManager: WalletManager?)
|
||||
}
|
||||
|
|
@ -24,7 +24,10 @@ import com.tangem.tap.domain.extensions.toSendableAmounts
|
|||
import com.tangem.tap.features.demo.DemoHelper
|
||||
import com.tangem.tap.features.home.redux.HomeAction
|
||||
import com.tangem.tap.features.send.redux.PrepareSendScreen
|
||||
import com.tangem.tap.features.wallet.redux.*
|
||||
import com.tangem.tap.features.wallet.redux.Currency
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.features.wallet.redux.WalletData
|
||||
import com.tangem.tap.features.wallet.redux.WalletState
|
||||
import com.tangem.tap.network.NetworkStateChanged
|
||||
import com.tangem.tap.scope
|
||||
import com.tangem.tap.store
|
||||
|
|
@ -63,9 +66,9 @@ class WalletMiddleware {
|
|||
is WalletAction.LoadWallet -> {
|
||||
scope.launch {
|
||||
if (action.blockchain == null) {
|
||||
walletState.walletManagers.map { walletManager ->
|
||||
async { globalState.tapWalletManager.loadWalletData(walletManager) }
|
||||
}.awaitAll()
|
||||
walletState.walletManagers.map { walletManager ->
|
||||
async { globalState.tapWalletManager.loadWalletData(walletManager) }
|
||||
}.awaitAll()
|
||||
} else {
|
||||
val walletManager = walletState.getWalletManager(action.blockchain)
|
||||
walletManager?.let { globalState.tapWalletManager.loadWalletData(it) }
|
||||
|
|
@ -84,23 +87,19 @@ class WalletMiddleware {
|
|||
warningsMiddleware.tryToShowAppRatingWarning(action.wallet)
|
||||
}
|
||||
is WalletAction.LoadFiatRate -> {
|
||||
val tapWalletManager = globalState.tapWalletManager
|
||||
val fiatAppCurrency = globalState.appCurrency
|
||||
scope.launch {
|
||||
when {
|
||||
action.wallet != null -> {
|
||||
globalState.tapWalletManager.loadFiatRate(
|
||||
globalState.appCurrency, action.wallet
|
||||
)
|
||||
tapWalletManager.loadFiatRate(fiatAppCurrency, action.wallet)
|
||||
}
|
||||
action.currency != null -> {
|
||||
globalState.tapWalletManager.loadFiatRate(
|
||||
globalState.appCurrency, action.currency
|
||||
)
|
||||
action.currencyList != null -> {
|
||||
tapWalletManager.loadFiatRate(fiatAppCurrency, action.currencyList)
|
||||
}
|
||||
else -> {
|
||||
globalState.tapWalletManager.loadFiatRate(
|
||||
fiatCurrency = globalState.appCurrency,
|
||||
currencies = walletState.wallets.mapNotNull { it.currency }
|
||||
)
|
||||
val currencyList = walletState.walletsData.map { it.currency }
|
||||
tapWalletManager.loadFiatRate(fiatAppCurrency, currencyList)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -127,22 +126,6 @@ class WalletMiddleware {
|
|||
}
|
||||
}
|
||||
}
|
||||
is WalletAction.UpdateWallet -> {
|
||||
if (action.blockchain != null) {
|
||||
scope.launch {
|
||||
val walletManager = walletState.getWalletManager(action.blockchain)
|
||||
walletManager?.let { globalState.tapWalletManager.updateWallet(it) }
|
||||
}
|
||||
} else {
|
||||
scope.launch {
|
||||
if (walletState.state == ProgressState.Done) {
|
||||
walletState.walletManagers.map { walletManager ->
|
||||
globalState.tapWalletManager.updateWallet(walletManager)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
is WalletAction.Scan -> {
|
||||
store.dispatch(HomeAction.ShouldScanCardOnResume(true))
|
||||
store.dispatch(NavigationAction.PopBackTo(AppScreen.Home))
|
||||
|
|
@ -170,7 +153,7 @@ class WalletMiddleware {
|
|||
is WalletAction.LoadData -> {
|
||||
scope.launch {
|
||||
val scanNoteResponse = globalState.scanResponse ?: return@launch
|
||||
if (!walletState.wallets.isEmpty()) {
|
||||
if (walletState.walletsData.isNotEmpty()) {
|
||||
globalState.tapWalletManager.reloadData(scanNoteResponse)
|
||||
} else {
|
||||
globalState.tapWalletManager.loadData(scanNoteResponse)
|
||||
|
|
@ -203,7 +186,7 @@ class WalletMiddleware {
|
|||
}
|
||||
}
|
||||
is WalletAction.ShowDialog.QrCode -> {
|
||||
val selectedWalletData = walletState.getWalletData(walletState.selectedWallet) ?: return
|
||||
val selectedWalletData = walletState.getWalletData(walletState.selectedCurrency) ?: return
|
||||
val selectedAddressData = selectedWalletData.walletAddresses?.selectedAddress ?: return
|
||||
|
||||
val currency = selectedWalletData.currency
|
||||
|
|
@ -230,12 +213,12 @@ class WalletMiddleware {
|
|||
when (currency) {
|
||||
is Currency.Blockchain -> {
|
||||
val amountToSend = amounts?.find { it.currencySymbol == currency.blockchain.currency }
|
||||
?: return WalletAction.Send.ChooseCurrency(amounts)
|
||||
?: return WalletAction.Send.ChooseCurrency(amounts)
|
||||
PrepareSendScreen(amountToSend, selectedWalletData.fiatRate, walletManager)
|
||||
}
|
||||
is Currency.Token -> {
|
||||
val amountToSend = amounts?.find { it.currencySymbol == currency.token.symbol }
|
||||
?: return WalletAction.Send.ChooseCurrency(amounts)
|
||||
?: return WalletAction.Send.ChooseCurrency(amounts)
|
||||
prepareSendActionForToken(amountToSend, state, selectedWalletData, wallet, walletManager)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ class MultiWalletReducer {
|
|||
state.addWalletManagers(action.walletManagers)
|
||||
}
|
||||
is WalletAction.MultiWallet.AddBlockchains -> {
|
||||
val wallets = action.blockchains.map { blockchain ->
|
||||
val walletsData = action.blockchains.map { blockchain ->
|
||||
val wallet = state.getWalletManager(blockchain)?.wallet
|
||||
val cardToken = if (!state.isMultiwalletAllowed) {
|
||||
wallet?.getFirstToken()?.symbol?.let { TokenData("", tokenSymbol = it) }
|
||||
|
|
@ -29,41 +29,41 @@ class MultiWalletReducer {
|
|||
null
|
||||
}
|
||||
WalletData(
|
||||
currencyData = BalanceWidgetData(
|
||||
BalanceStatus.Loading,
|
||||
blockchain.fullName,
|
||||
currencySymbol = blockchain.currency,
|
||||
token = cardToken
|
||||
),
|
||||
walletAddresses = createAddressList(wallet),
|
||||
mainButton = WalletMainButton.SendButton(false),
|
||||
currency = Currency.Blockchain(blockchain),
|
||||
currencyData = BalanceWidgetData(
|
||||
BalanceStatus.Loading,
|
||||
blockchain.fullName,
|
||||
currencySymbol = blockchain.currency,
|
||||
token = cardToken
|
||||
),
|
||||
walletAddresses = createAddressList(wallet),
|
||||
mainButton = WalletMainButton.SendButton(false),
|
||||
currency = Currency.Blockchain(blockchain),
|
||||
)
|
||||
}
|
||||
|
||||
val selectedWallet = if (!state.isMultiwalletAllowed) {
|
||||
wallets[0].currency
|
||||
val selectedCurrency = if (!state.isMultiwalletAllowed) {
|
||||
walletsData[0].currency
|
||||
} else {
|
||||
state.selectedWallet
|
||||
state.selectedCurrency
|
||||
}
|
||||
state.copy(
|
||||
wallets = wallets,
|
||||
selectedWallet = selectedWallet
|
||||
walletsData = walletsData,
|
||||
selectedCurrency = selectedCurrency
|
||||
)
|
||||
}
|
||||
is WalletAction.MultiWallet.AddBlockchain -> {
|
||||
val wallet = state.getWalletManager(action.blockchain)?.wallet
|
||||
val walletData = WalletData(
|
||||
currencyData = BalanceWidgetData(
|
||||
BalanceStatus.Loading,
|
||||
action.blockchain.fullName,
|
||||
currencySymbol = action.blockchain.currency,
|
||||
),
|
||||
walletAddresses = createAddressList(wallet),
|
||||
mainButton = WalletMainButton.SendButton(false),
|
||||
currency = Currency.Blockchain(action.blockchain),
|
||||
currencyData = BalanceWidgetData(
|
||||
BalanceStatus.Loading,
|
||||
action.blockchain.fullName,
|
||||
currencySymbol = action.blockchain.currency,
|
||||
),
|
||||
walletAddresses = createAddressList(wallet),
|
||||
mainButton = WalletMainButton.SendButton(false),
|
||||
currency = Currency.Blockchain(action.blockchain),
|
||||
)
|
||||
val newState = state.copy(wallets = state.replaceWalletInWallets(walletData))
|
||||
val newState = state.copy(walletsData = state.replaceWalletInWallets(walletData))
|
||||
if (wallet != null && wallet.amounts[AmountType.Coin]?.value != null) {
|
||||
OnWalletLoadedReducer().reduce(wallet, newState)
|
||||
} else {
|
||||
|
|
@ -72,21 +72,21 @@ class MultiWalletReducer {
|
|||
}
|
||||
is WalletAction.MultiWallet.AddTokens -> {
|
||||
val wallets = action.tokens.mapNotNull { token -> token.toWallet(state) }
|
||||
state.copy(wallets = state.replaceSomeWallets(wallets))
|
||||
state.copy(walletsData = state.replaceSomeWallets(wallets))
|
||||
}
|
||||
is WalletAction.MultiWallet.AddToken -> {
|
||||
val walletData = action.token.toWallet(state) ?: return state
|
||||
state.copy(wallets = state.replaceWalletInWallets(walletData))
|
||||
state.copy(walletsData = state.replaceWalletInWallets(walletData))
|
||||
}
|
||||
is WalletAction.MultiWallet.TokenLoaded -> {
|
||||
val pendingTransactions = state.getWalletManager(action.token)
|
||||
?.wallet?.let { wallet ->
|
||||
wallet.recentTransactions.toPendingTransactions(wallet.address)
|
||||
} ?: emptyList()
|
||||
?.wallet?.let { wallet ->
|
||||
wallet.recentTransactions.toPendingTransactions(wallet.address)
|
||||
} ?: emptyList()
|
||||
|
||||
val sendButtonEnabled = action.amount.value?.isZero() == false && pendingTransactions.isEmpty()
|
||||
val tokenPendingTransactions = pendingTransactions
|
||||
.filter { it.currency == action.amount.currencySymbol }
|
||||
.filter { it.currency == action.amount.currencySymbol }
|
||||
val tokenBalanceStatus = when {
|
||||
tokenPendingTransactions.isNotEmpty() -> BalanceStatus.TransactionInProgress
|
||||
pendingTransactions.isNotEmpty() -> BalanceStatus.SameCurrencyTransactionInProgress
|
||||
|
|
@ -94,42 +94,43 @@ class MultiWalletReducer {
|
|||
}
|
||||
val tokenWalletData = state.getWalletData(action.token)
|
||||
val newTokenWalletData = tokenWalletData?.copy(
|
||||
currencyData = tokenWalletData.currencyData.copy(
|
||||
status = tokenBalanceStatus,
|
||||
amount = action.amount.value?.toFormattedCurrencyString(
|
||||
action.amount.decimals, action.amount.currencySymbol
|
||||
),
|
||||
fiatAmountFormatted = tokenWalletData.fiatRate?.let {
|
||||
action.amount.value
|
||||
?.toFiatString(it, store.state.globalState.appCurrency)
|
||||
}
|
||||
currencyData = tokenWalletData.currencyData.copy(
|
||||
status = tokenBalanceStatus,
|
||||
amount = action.amount.value,
|
||||
amountFormatted = action.amount.value?.toFormattedCurrencyString(
|
||||
action.amount.decimals, action.amount.currencySymbol
|
||||
),
|
||||
pendingTransactions = pendingTransactions.removeUnknownTransactions(),
|
||||
mainButton = WalletMainButton.SendButton(sendButtonEnabled),
|
||||
currency = Currency.Token(action.token)
|
||||
fiatAmountFormatted = tokenWalletData.fiatRate?.let {
|
||||
action.amount.value
|
||||
?.toFiatString(it, store.state.globalState.appCurrency)
|
||||
}
|
||||
),
|
||||
pendingTransactions = pendingTransactions.removeUnknownTransactions(),
|
||||
mainButton = WalletMainButton.SendButton(sendButtonEnabled),
|
||||
currency = Currency.Token(action.token)
|
||||
)
|
||||
val wallets = state.replaceWalletInWallets(newTokenWalletData)
|
||||
state.copy(wallets = wallets)
|
||||
state.copy(walletsData = wallets)
|
||||
}
|
||||
is WalletAction.MultiWallet.SetIsMultiwalletAllowed ->
|
||||
state.copy(isMultiwalletAllowed = action.isMultiwalletAllowed)
|
||||
|
||||
is WalletAction.MultiWallet.SelectWallet ->
|
||||
state.copy(selectedWallet = action.walletData?.currency)
|
||||
state.copy(selectedCurrency = action.walletData?.currency)
|
||||
|
||||
is WalletAction.MultiWallet.RemoveWallet -> {
|
||||
val wallets = state.wallets.filterNot {
|
||||
val wallets = state.walletsData.filterNot {
|
||||
it.currency == action.walletData.currency
|
||||
}
|
||||
if (action.walletData.currency is Currency.Blockchain) {
|
||||
state.copy(
|
||||
wallets = wallets,
|
||||
walletsData = wallets,
|
||||
walletManagers = state.walletManagers.filterNot {
|
||||
it.wallet.blockchain == action.walletData.currency.blockchain
|
||||
}
|
||||
)
|
||||
} else {
|
||||
state.copy(wallets = wallets)
|
||||
state.copy(walletsData = wallets)
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -36,11 +36,11 @@ class OnWalletLoadedReducer {
|
|||
return walletState
|
||||
}
|
||||
val formattedAmount = coinAmountValue?.toFormattedCurrencyString(
|
||||
wallet.blockchain.decimals(),
|
||||
wallet.blockchain.currency)
|
||||
wallet.blockchain.decimals(),
|
||||
wallet.blockchain.currency)
|
||||
|
||||
val pendingTransactions = wallet.recentTransactions
|
||||
.toPendingTransactions(wallet.address)
|
||||
.toPendingTransactions(wallet.address)
|
||||
|
||||
val coinSendButton = coinAmountValue?.isZero() == false && pendingTransactions.isEmpty()
|
||||
val balanceStatus = if (pendingTransactions.isNotEmpty()) {
|
||||
|
|
@ -52,17 +52,19 @@ class OnWalletLoadedReducer {
|
|||
|
||||
val fiatAmount = walletData?.fiatRate?.let { coinAmountValue?.toFiatValue(it) }
|
||||
val newWalletData = walletData?.copy(
|
||||
currencyData = walletData.currencyData.copy(
|
||||
status = balanceStatus, currency = wallet.blockchain.fullName,
|
||||
currencySymbol = wallet.blockchain.currency,
|
||||
amount = formattedAmount,
|
||||
fiatAmount = fiatAmount,
|
||||
fiatAmountFormatted = fiatAmount?.toFormattedFiatValue(fiatCurrencySymbol)
|
||||
),
|
||||
pendingTransactions = pendingTransactions.removeUnknownTransactions(),
|
||||
mainButton = WalletMainButton.SendButton(coinSendButton),
|
||||
currency = Currency.Blockchain(wallet.blockchain),
|
||||
tradeCryptoState = TradeCryptoState.from(exchangeManager, walletData)
|
||||
currencyData = walletData.currencyData.copy(
|
||||
status = balanceStatus, currency = wallet.blockchain.fullName,
|
||||
currencySymbol = wallet.blockchain.currency,
|
||||
blockchainAmount = coinAmountValue,
|
||||
amount = coinAmountValue,
|
||||
amountFormatted = formattedAmount,
|
||||
fiatAmount = fiatAmount,
|
||||
fiatAmountFormatted = fiatAmount?.toFormattedFiatValue(fiatCurrencySymbol)
|
||||
),
|
||||
pendingTransactions = pendingTransactions.removeUnknownTransactions(),
|
||||
mainButton = WalletMainButton.SendButton(coinSendButton),
|
||||
currency = Currency.Blockchain(wallet.blockchain),
|
||||
tradeCryptoState = TradeCryptoState.from(exchangeManager, walletData),
|
||||
)
|
||||
|
||||
val tokens = wallet.getTokens().mapNotNull { token ->
|
||||
|
|
@ -73,20 +75,23 @@ class OnWalletLoadedReducer {
|
|||
pendingTransactions.isNotEmpty() -> BalanceStatus.SameCurrencyTransactionInProgress
|
||||
else -> BalanceStatus.VerifiedOnline
|
||||
}
|
||||
val tokenAmountValue = wallet.getTokenAmount(token)?.value
|
||||
val tokenFiatAmount = tokenWalletData?.fiatRate?.let { rate -> tokenAmountValue?.toFiatValue(rate)}
|
||||
val tokenAmountValue = wallet.getTokenAmount(token)?.value
|
||||
val tokenFiatAmount = tokenWalletData?.fiatRate?.let { rate -> tokenAmountValue?.toFiatValue(rate) }
|
||||
|
||||
val tokenSendButton = tokenAmountValue?.isZero() == false && tokenPendingTransactions.isEmpty()
|
||||
val tokenSendButton = newWalletData?.shouldEnableTokenSendButton() == true
|
||||
&& tokenPendingTransactions.isEmpty()
|
||||
tokenWalletData?.copy(
|
||||
currencyData = tokenWalletData.currencyData.copy(
|
||||
status = tokenBalanceStatus,
|
||||
amount = tokenAmountValue?.toFormattedCurrencyString(token.decimals, token.symbol),
|
||||
fiatAmount = tokenFiatAmount,
|
||||
fiatAmountFormatted = tokenFiatAmount?.toFormattedFiatValue(fiatCurrencySymbol)
|
||||
),
|
||||
pendingTransactions = tokenPendingTransactions.removeUnknownTransactions(),
|
||||
mainButton = WalletMainButton.SendButton(tokenSendButton),
|
||||
tradeCryptoState = TradeCryptoState.from(exchangeManager, tokenWalletData)
|
||||
currencyData = tokenWalletData.currencyData.copy(
|
||||
status = tokenBalanceStatus,
|
||||
blockchainAmount = coinAmountValue,
|
||||
amount = tokenAmountValue,
|
||||
amountFormatted = tokenAmountValue?.toFormattedCurrencyString(token.decimals, token.symbol),
|
||||
fiatAmount = tokenFiatAmount,
|
||||
fiatAmountFormatted = tokenFiatAmount?.toFormattedFiatValue(fiatCurrencySymbol)
|
||||
),
|
||||
pendingTransactions = tokenPendingTransactions.removeUnknownTransactions(),
|
||||
mainButton = WalletMainButton.SendButton(tokenSendButton),
|
||||
tradeCryptoState = TradeCryptoState.from(exchangeManager, tokenWalletData),
|
||||
)
|
||||
}
|
||||
val newWallets = (tokens + newWalletData).mapNotNull { it }
|
||||
|
|
@ -98,7 +103,7 @@ class OnWalletLoadedReducer {
|
|||
ProgressState.Done
|
||||
}
|
||||
return walletState.copy(
|
||||
state = state, wallets = wallets, error = null
|
||||
state = state, walletsData = wallets, error = null
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -128,15 +133,13 @@ class OnWalletLoadedReducer {
|
|||
}
|
||||
val amount = wallet.amounts[AmountType.Coin]?.value
|
||||
val formattedAmount = amount?.toFormattedCurrencyString(
|
||||
wallet.blockchain.decimals(),
|
||||
wallet.blockchain.currency)
|
||||
wallet.blockchain.decimals(),
|
||||
wallet.blockchain.currency)
|
||||
val fiatRate = walletState.primaryWallet?.fiatRate
|
||||
val fiatAmountRaw = fiatRate?.multiply(amount)?.setScale(2, RoundingMode.DOWN)
|
||||
val fiatAmount = fiatRate?.let { amount?.toFiatString(it, fiatCurrencySymbol) }
|
||||
|
||||
val pendingTransactions = wallet.recentTransactions
|
||||
.toPendingTransactions(wallet.address)
|
||||
|
||||
val pendingTransactions = wallet.recentTransactions.toPendingTransactions(wallet.address)
|
||||
val sendButtonEnabled = amount?.isZero() == false && pendingTransactions.isEmpty()
|
||||
val balanceStatus = if (pendingTransactions.isNotEmpty()) {
|
||||
BalanceStatus.TransactionInProgress
|
||||
|
|
@ -144,21 +147,23 @@ class OnWalletLoadedReducer {
|
|||
BalanceStatus.VerifiedOnline
|
||||
}
|
||||
val walletData = walletState.primaryWallet?.copy(
|
||||
currencyData = BalanceWidgetData(
|
||||
balanceStatus, wallet.blockchain.fullName,
|
||||
currencySymbol = wallet.blockchain.currency,
|
||||
formattedAmount,
|
||||
token = tokenData,
|
||||
fiatAmountFormatted = fiatAmount,
|
||||
fiatAmount = fiatAmountRaw
|
||||
),
|
||||
pendingTransactions = pendingTransactions.removeUnknownTransactions(),
|
||||
mainButton = WalletMainButton.SendButton(sendButtonEnabled),
|
||||
tradeCryptoState = TradeCryptoState.from(exchangeManager, walletState.primaryWallet)
|
||||
currencyData = BalanceWidgetData(
|
||||
balanceStatus, wallet.blockchain.fullName,
|
||||
currencySymbol = wallet.blockchain.currency,
|
||||
token = tokenData,
|
||||
blockchainAmount = amount,
|
||||
amount = amount,
|
||||
amountFormatted = formattedAmount,
|
||||
fiatAmountFormatted = fiatAmount,
|
||||
fiatAmount = fiatAmountRaw
|
||||
),
|
||||
pendingTransactions = pendingTransactions.removeUnknownTransactions(),
|
||||
mainButton = WalletMainButton.SendButton(sendButtonEnabled),
|
||||
tradeCryptoState = TradeCryptoState.from(exchangeManager, walletState.primaryWallet),
|
||||
)
|
||||
val wallets = walletData?.let { listOf(walletData) } ?: emptyList()
|
||||
return walletState.copy(
|
||||
state = ProgressState.Done, wallets = wallets, error = null
|
||||
state = ProgressState.Done, walletsData = wallets, error = null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -46,7 +46,7 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
|
|||
is WalletAction.EmptyWallet -> {
|
||||
newState = newState.copy(
|
||||
state = ProgressState.Done,
|
||||
wallets = listOf(
|
||||
walletsData = listOf(
|
||||
WalletData(
|
||||
currencyData = BalanceWidgetData(BalanceStatus.EmptyCard),
|
||||
mainButton = WalletMainButton.CreateWalletButton(true),
|
||||
|
|
@ -58,7 +58,7 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
|
|||
is WalletAction.LoadData.Failure -> {
|
||||
when (action.error) {
|
||||
is TapError.NoInternetConnection -> {
|
||||
val wallets = newState.wallets
|
||||
val wallets = newState.walletsData
|
||||
.map {
|
||||
it.copy(
|
||||
currencyData = it.currencyData.copy(
|
||||
|
|
@ -69,13 +69,13 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
|
|||
newState = newState.copy(
|
||||
state = ProgressState.Error,
|
||||
error = ErrorType.NoInternetConnection,
|
||||
wallets = wallets
|
||||
walletsData = wallets
|
||||
)
|
||||
}
|
||||
is TapError.UnknownBlockchain -> {
|
||||
newState = newState.copy(
|
||||
state = ProgressState.Done,
|
||||
wallets = listOf(
|
||||
walletsData = listOf(
|
||||
WalletData(
|
||||
currencyData = BalanceWidgetData(BalanceStatus.UnknownBlockchain),
|
||||
currency = Currency.Blockchain(Blockchain.Unknown)
|
||||
|
|
@ -94,7 +94,7 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
|
|||
}
|
||||
is WalletAction.LoadWallet -> {
|
||||
if (action.blockchain == null) {
|
||||
val wallets = newState.wallets.map { wallet ->
|
||||
val wallets = newState.walletsData.map { wallet ->
|
||||
|
||||
wallet.copy(
|
||||
currencyData = wallet.currencyData.copy(
|
||||
|
|
@ -108,14 +108,14 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
|
|||
}
|
||||
newState = newState.copy(
|
||||
state = ProgressState.Loading,
|
||||
wallets = wallets,
|
||||
walletsData = wallets,
|
||||
)
|
||||
} else {
|
||||
val walletManager = newState.getWalletManager(action.blockchain) ?: return newState
|
||||
val blockchain = walletManager.wallet.blockchain
|
||||
val currencies = listOf(Currency.Blockchain(blockchain)) +
|
||||
walletManager.cardTokens.map { Currency.Token(it) }
|
||||
val newWallets = newState.wallets.filter { currencies.contains(it.currency) }
|
||||
val newWallets = newState.walletsData.filter { currencies.contains(it.currency) }
|
||||
.map { wallet ->
|
||||
wallet.copy(
|
||||
currencyData = wallet.currencyData.copy(
|
||||
|
|
@ -128,14 +128,10 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
|
|||
)
|
||||
}
|
||||
val wallets = newState.replaceSomeWallets(newWallets)
|
||||
newState = newState.copy(wallets = newState.updateTradeCryptoState(exchangeManager, wallets))
|
||||
newState = newState.copy(walletsData = newState.updateTradeCryptoState(exchangeManager, wallets))
|
||||
}
|
||||
}
|
||||
is WalletAction.LoadWallet.Success -> newState =
|
||||
onWalletLoadedReducer.reduce(action.wallet, newState)
|
||||
is WalletAction.UpdateWallet.Success -> {
|
||||
newState = onWalletLoadedReducer.reduce(action.wallet, newState)
|
||||
}
|
||||
is WalletAction.LoadWallet.Success -> newState = onWalletLoadedReducer.reduce(action.wallet, newState)
|
||||
is WalletAction.LoadWallet.NoAccount -> {
|
||||
val walletData = newState.getWalletData(action.wallet.blockchain)?.copy(
|
||||
currencyData = BalanceWidgetData(
|
||||
|
|
@ -153,7 +149,7 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
|
|||
}
|
||||
newState = newState.copy(
|
||||
state = progressState,
|
||||
wallets = newState.updateTradeCryptoState(exchangeManager, wallets)
|
||||
walletsData = newState.updateTradeCryptoState(exchangeManager, wallets)
|
||||
)
|
||||
}
|
||||
is WalletAction.LoadWallet.Failure -> {
|
||||
|
|
@ -188,7 +184,7 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
|
|||
}
|
||||
newState = newState.copy(
|
||||
state = progressState,
|
||||
wallets = newState.updateTradeCryptoState(exchangeManager, wallets)
|
||||
walletsData = newState.updateTradeCryptoState(exchangeManager, wallets)
|
||||
)
|
||||
}
|
||||
is WalletAction.SetArtworkId -> {
|
||||
|
|
@ -228,7 +224,7 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
|
|||
is WalletAction.Send.Cancel -> newState = newState.copy(walletDialog = null)
|
||||
is WalletAction.TradeCryptoAction -> return newState
|
||||
is WalletAction.ChangeSelectedAddress -> {
|
||||
val selectedWalletData = newState.getWalletData(newState.selectedWallet)
|
||||
val selectedWalletData = newState.getWalletData(newState.selectedCurrency)
|
||||
|
||||
val walletAddresses =
|
||||
newState.getWalletData(selectedWalletData?.currency)?.walletAddresses
|
||||
|
|
@ -243,16 +239,16 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
|
|||
)
|
||||
)
|
||||
)
|
||||
newState = newState.copy(wallets = wallets)
|
||||
newState = newState.copy(walletsData = wallets)
|
||||
}
|
||||
is WalletAction.SetWalletRent -> {
|
||||
var walletData = newState.getWalletData(action.blockchain)
|
||||
if (walletData == null) {
|
||||
newState
|
||||
} else {
|
||||
walletData = walletData.copy(walletRent = WalletRent(action.minRent, action.rentExempt))
|
||||
walletData = walletData.copy(warningRent = WalletRent(action.minRent, action.rentExempt))
|
||||
newState = newState.copy(
|
||||
wallets = newState.replaceSomeWallets(listOf(walletData))
|
||||
walletsData = newState.replaceSomeWallets(listOf(walletData))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -343,7 +339,7 @@ private fun setMultiWalletFiatRate(
|
|||
),
|
||||
fiatRate = rate, fiatRateString = rateFormatted
|
||||
)
|
||||
return state.copy(wallets = state.replaceWalletInWallets(newWalletData))
|
||||
return state.copy(walletsData = state.replaceWalletInWallets(newWalletData))
|
||||
}
|
||||
|
||||
private fun setSingeWalletFiatRate(
|
||||
|
|
@ -361,7 +357,7 @@ private fun setSingeWalletFiatRate(
|
|||
fiatRate = rate,
|
||||
fiatRateString = rateFormatted
|
||||
)
|
||||
return state.copy(wallets = listOf(walletData))
|
||||
return state.copy(walletsData = listOf(walletData))
|
||||
} else if (currency is Currency.Token && currency.token == token) {
|
||||
val tokenFiatAmount = wallet.getTokenAmount(token)?.value?.toFiatString(rate, appCurrency)
|
||||
val tokenData = state.primaryWallet?.currencyData?.token?.copy(
|
||||
|
|
@ -376,7 +372,7 @@ private fun setSingeWalletFiatRate(
|
|||
)
|
||||
)
|
||||
val wallets = walletData?.let { listOf(walletData) } ?: emptyList()
|
||||
return state.copy(wallets = wallets)
|
||||
return state.copy(walletsData = wallets)
|
||||
}
|
||||
return state
|
||||
}
|
||||
|
|
@ -22,7 +22,9 @@ data class BalanceWidgetData(
|
|||
val status: BalanceStatus? = null,
|
||||
val currency: String? = null,
|
||||
val currencySymbol: String? = null,
|
||||
val amount: String? = null,
|
||||
val blockchainAmount: BigDecimal? = BigDecimal.ZERO,
|
||||
val amount: BigDecimal? = null,
|
||||
val amountFormatted: String? = null,
|
||||
val fiatAmountFormatted: String? = null,
|
||||
val fiatAmount: BigDecimal? = null,
|
||||
val token: TokenData? = null,
|
||||
|
|
@ -149,7 +151,7 @@ class BalanceWidget(
|
|||
tvCurrency.text = data.token?.tokenSymbol
|
||||
tvBaseCurrency.text = data.currency
|
||||
tvAmount.text = if (showAmount) data.token?.amount else ""
|
||||
tvBaseAmount.text = if (showAmount) data.amount else ""
|
||||
tvBaseAmount.text = if (showAmount) data.amountFormatted else ""
|
||||
if (showAmount) {
|
||||
tvFiatAmount.show()
|
||||
tvFiatAmount.text = data.token?.fiatAmount
|
||||
|
|
@ -160,7 +162,7 @@ class BalanceWidget(
|
|||
with(binding.lBalance) {
|
||||
groupBaseCurrency.hide()
|
||||
tvCurrency.text = data.currency
|
||||
tvAmount.text = if (showAmount) data.amount else ""
|
||||
tvAmount.text = if (showAmount) data.amountFormatted else ""
|
||||
if (showAmount) {
|
||||
tvFiatAmount.show()
|
||||
tvFiatAmount.text = data.fiatAmountFormatted
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details),
|
|||
|
||||
override fun newState(state: WalletState) {
|
||||
if (activity == null || view == null) return
|
||||
if (state.selectedWallet == null) return
|
||||
if (state.selectedCurrency == null) return
|
||||
val selectedWallet = state.getSelectedWalletData() ?: return
|
||||
|
||||
|
||||
|
|
@ -107,8 +107,8 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details),
|
|||
|
||||
handleDialogs(state.walletDialog)
|
||||
handleCurrencyIcon(selectedWallet)
|
||||
handleWalletRent(selectedWallet.walletRent)
|
||||
|
||||
handleWalletRent(selectedWallet.warningRent)
|
||||
handleNotEnoughFundsOnMainCurrency(selectedWallet)
|
||||
|
||||
binding.srlWalletDetails.setOnRefreshListener {
|
||||
if (selectedWallet.currencyData.status != BalanceStatus.Loading) {
|
||||
|
|
@ -153,14 +153,27 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details),
|
|||
|
||||
private fun handleWalletRent(rent: WalletRent?) = with(binding) {
|
||||
val rent = rent.guard {
|
||||
lRentWarning.root.hide()
|
||||
lWarning.root.hide()
|
||||
return
|
||||
}
|
||||
val warningMessage = requireContext().getString(
|
||||
R.string.solana_rent_warning, rent.minRentValue, rent.rentExemptValue
|
||||
)
|
||||
lRentWarning.tvRentWarningMessage.text = warningMessage
|
||||
lRentWarning.root.show()
|
||||
lWarning.tvWarningMessage.text = warningMessage
|
||||
lWarning.root.show()
|
||||
}
|
||||
|
||||
private fun handleNotEnoughFundsOnMainCurrency(selectedWalletData: WalletData) = with(binding) {
|
||||
if (selectedWalletData.shouldShowCoinAmountWarning()) {
|
||||
val blockchainName = selectedWalletData.currency.blockchain.fullName
|
||||
val warningMessage = requireContext().getString(
|
||||
R.string.token_details_send_blocked_fee_format, blockchainName, blockchainName
|
||||
)
|
||||
lWarning.tvWarningMessage.text = warningMessage
|
||||
lWarning.root.show()
|
||||
} else {
|
||||
lWarning.root.hide()
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleCurrencyIcon(wallet: WalletData) = with(binding.lWalletDetails.lBalance) {
|
||||
|
|
@ -234,7 +247,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details),
|
|||
lBalance.root.show()
|
||||
lBalance.groupBalance.show()
|
||||
lBalance.tvError.hide()
|
||||
lBalance.tvAmount.text = data.amount
|
||||
lBalance.tvAmount.text = data.amountFormatted
|
||||
lBalance.tvFiatAmount.text = data.fiatAmountFormatted
|
||||
lBalance.tvStatus.setLoadingStatus(R.string.wallet_balance_loading)
|
||||
}
|
||||
|
|
@ -244,7 +257,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details),
|
|||
lBalance.root.show()
|
||||
lBalance.groupBalance.show()
|
||||
lBalance.tvError.hide()
|
||||
lBalance.tvAmount.text = data.amount
|
||||
lBalance.tvAmount.text = data.amountFormatted
|
||||
lBalance.tvFiatAmount.text = data.fiatAmountFormatted
|
||||
when (data.status) {
|
||||
BalanceStatus.VerifiedOnline, BalanceStatus.SameCurrencyTransactionInProgress -> {
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
|
|||
}.select { it.walletState }
|
||||
}
|
||||
walletView.setFragment(this, binding)
|
||||
store.dispatch(WalletAction.UpdateWallet())
|
||||
store.dispatch(WalletAction.LoadWallet())
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
|
|
|
|||
|
|
@ -57,8 +57,8 @@ class WalletAdapter
|
|||
|
||||
fun bind(wallet: WalletData) = with(binding) {
|
||||
tvCurrency.text = wallet.currencyData.currency
|
||||
tvAmount.text = wallet.currencyData.amount?.takeWhile { !it.isWhitespace() }
|
||||
tvCurrencySymbol.text = wallet.currencyData.amount?.takeLastWhile { !it.isWhitespace() }
|
||||
tvAmount.text = wallet.currencyData.amountFormatted?.takeWhile { !it.isWhitespace() }
|
||||
tvCurrencySymbol.text = wallet.currencyData.amountFormatted?.takeLastWhile { !it.isWhitespace() }
|
||||
tvAmountFiat.text = wallet.currencyData.fiatAmountFormatted
|
||||
tvExchangeRate.text = wallet.fiatRateString
|
||||
cardWallet.setOnClickListener {
|
||||
|
|
@ -77,7 +77,7 @@ class WalletAdapter
|
|||
BalanceStatus.VerifiedOnline, BalanceStatus.SameCurrencyTransactionInProgress -> hideWarning()
|
||||
BalanceStatus.Loading -> {
|
||||
hideWarning()
|
||||
if (wallet.currencyData.amount == null) {
|
||||
if (wallet.currencyData.amountFormatted == null) {
|
||||
tvExchangeRate.text = root.getString(R.string.wallet_balance_loading)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,11 +94,11 @@ class MultiWalletView : WalletView {
|
|||
val fragment = fragment ?: return
|
||||
val binding = binding ?: return
|
||||
|
||||
walletsAdapter.submitList(state.wallets, state.primaryBlockchain, state.primaryToken)
|
||||
walletsAdapter.submitList(state.walletsData, state.primaryBlockchain, state.primaryToken)
|
||||
|
||||
binding.btnAddToken.setOnClickListener {
|
||||
store.dispatch(TokensAction.LoadCurrencies)
|
||||
store.dispatch(TokensAction.SetAddedCurrencies(state.wallets))
|
||||
store.dispatch(TokensAction.SetAddedCurrencies(state.walletsData))
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.AddTokens))
|
||||
}
|
||||
handleErrorStates(state = state, binding = binding, fragment = fragment)
|
||||
|
|
|
|||
|
|
@ -99,8 +99,8 @@
|
|||
app:layout_constraintTop_toBottomOf="@id/rv_pending_transaction" />
|
||||
|
||||
<include
|
||||
android:id="@+id/l_rent_warning"
|
||||
layout="@layout/layout_wallet_details_rent"
|
||||
android:id="@+id/l_warning"
|
||||
layout="@layout/layout_wallet_details_warning"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
|
|
@ -168,7 +168,7 @@
|
|||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/btn_sell"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/l_rent_warning"
|
||||
app:layout_constraintTop_toBottomOf="@+id/l_warning"
|
||||
app:layout_constraintVertical_bias="1" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
|
|
@ -185,7 +185,7 @@
|
|||
app:layout_constraintEnd_toStartOf="@id/btn_confirm"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintStart_toEndOf="@id/btn_trade"
|
||||
app:layout_constraintTop_toBottomOf="@+id/l_rent_warning"
|
||||
app:layout_constraintTop_toBottomOf="@+id/l_warning"
|
||||
app:layout_constraintVertical_bias="1" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
|
|
@ -201,7 +201,7 @@
|
|||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/btn_sell"
|
||||
app:layout_constraintTop_toBottomOf="@+id/l_rent_warning"
|
||||
app:layout_constraintTop_toBottomOf="@+id/l_warning"
|
||||
app:layout_constraintVertical_bias="1" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_rent_warning_title"
|
||||
android:id="@+id/tv_warning_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
|
|
@ -27,7 +27,7 @@
|
|||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_rent_warning_message"
|
||||
android:id="@+id/tv_warning_message"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
|
|
@ -39,7 +39,7 @@
|
|||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tv_rent_warning_title"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tv_warning_title"
|
||||
tools:text="@string/solana_rent_warning" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
<string name="shop_2_cards">2 cards</string>
|
||||
<string name="shop_shipping">Shipping</string>
|
||||
<string name="shop_free">Free</string>
|
||||
<string name="shop_i_have_a_promo_code">I have a promo code…</string>
|
||||
<string name="shop_i_have_a_promo_code">I have a promo code...</string>
|
||||
<string name="shop_total">Total</string>
|
||||
<string name="shop_other_payment_methods">Other payment methods</string>
|
||||
<string name="shop_buy_now">Buy now</string>
|
||||
|
|
@ -23,16 +23,17 @@
|
|||
<string name="story_awe_title">Revolutionary Hardware Wallet</string>
|
||||
<string name="story_awe_description">Store your crypto assets secure while keeping private keys contained in your card</string>
|
||||
<string name="story_backup_title">Ultra Secure Backup</string>
|
||||
<string name="story_backup_description">Up to 3 physical cards to one wallet</string>
|
||||
<string name="story_backup_description">Up to <b>3 physical cards</b> to one wallet</string>
|
||||
<string name="story_currencies_title">Thousands of Currencies</string>
|
||||
<string name="story_currencies_description">A hardware wallet for your Bitcoin, Ethereum and many more currencies simultaneously – all in one card</string>
|
||||
<string name="story_web3_title">DeFi Compatible</string>
|
||||
<string name="story_web3_description">Exchange, buy NFT’s, make loans and deposits in more than 100 different decentralized services</string>
|
||||
<string name="story_finish_title">The Wallet for Everyone</string>
|
||||
<string name="story_finish_description">Use it on the go, anywhere, anytime. No wires or batteries. Just tap the card to your phone when you need your crypto.</string>
|
||||
<string name="home_button_order">Order card</string>
|
||||
<string name="home_button_order">Order</string>
|
||||
<string name="home_button_search_tokens">Search tokens</string>
|
||||
<string name="search_tokens_title">Search tokens</string>
|
||||
<string name="alert_demo_message">You are currently running in Demo mode. All funds are not real.</string>
|
||||
<string name="alert_demo_feature_disabled">This feature is disabled in Demo mode</string>
|
||||
<string name="token_details_send_blocked_fee_format">Not enough funds for fee on your %s wallet to send a transaction. Top up your %s wallet first.</string>
|
||||
</resources>
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
<string name="shop_2_cards">2 cards</string>
|
||||
<string name="shop_shipping">Shipping</string>
|
||||
<string name="shop_free">Free</string>
|
||||
<string name="shop_i_have_a_promo_code">I have a promo code…</string>
|
||||
<string name="shop_i_have_a_promo_code">I have a promo code...</string>
|
||||
<string name="shop_total">Total</string>
|
||||
<string name="shop_other_payment_methods">Other payment methods</string>
|
||||
<string name="shop_buy_now">Buy now</string>
|
||||
|
|
@ -23,16 +23,17 @@
|
|||
<string name="story_awe_title">Revolutionary Hardware Wallet</string>
|
||||
<string name="story_awe_description">Store your crypto assets secure while keeping private keys contained in your card</string>
|
||||
<string name="story_backup_title">Ultra Secure Backup</string>
|
||||
<string name="story_backup_description">Up to 3 physical cards to one wallet</string>
|
||||
<string name="story_backup_description">Up to <b>3 physical cards</b> to one wallet</string>
|
||||
<string name="story_currencies_title">Thousands of Currencies</string>
|
||||
<string name="story_currencies_description">A hardware wallet for your Bitcoin, Ethereum and many more currencies simultaneously – all in one card</string>
|
||||
<string name="story_web3_title">DeFi Compatible</string>
|
||||
<string name="story_web3_description">Exchange, buy NFT’s, make loans and deposits in more than 100 different decentralized services</string>
|
||||
<string name="story_finish_title">The Wallet for Everyone</string>
|
||||
<string name="story_finish_description">Use it on the go, anywhere, anytime. No wires or batteries. Just tap the card to your phone when you need your crypto.</string>
|
||||
<string name="home_button_order">Order card</string>
|
||||
<string name="home_button_order">Order</string>
|
||||
<string name="home_button_search_tokens">Search tokens</string>
|
||||
<string name="search_tokens_title">Search tokens</string>
|
||||
<string name="alert_demo_message">You are currently running in Demo mode. All funds are not real.</string>
|
||||
<string name="alert_demo_feature_disabled">This feature is disabled in Demo mode</string>
|
||||
<string name="token_details_send_blocked_fee_format">Not enough funds for fee on your %s wallet to send a transaction. Top up your %s wallet first.</string>
|
||||
</resources>
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
<string name="shop_2_cards">2 cards</string>
|
||||
<string name="shop_shipping">Shipping</string>
|
||||
<string name="shop_free">Free</string>
|
||||
<string name="shop_i_have_a_promo_code">I have a promo code…</string>
|
||||
<string name="shop_i_have_a_promo_code">I have a promo code...</string>
|
||||
<string name="shop_total">Total</string>
|
||||
<string name="shop_other_payment_methods">Other payment methods</string>
|
||||
<string name="shop_buy_now">Buy now</string>
|
||||
|
|
@ -23,16 +23,17 @@
|
|||
<string name="story_awe_title">Revolutionary Hardware Wallet</string>
|
||||
<string name="story_awe_description">Store your crypto assets secure while keeping private keys contained in your card</string>
|
||||
<string name="story_backup_title">Ultra Secure Backup</string>
|
||||
<string name="story_backup_description">Up to 3 physical cards to one wallet</string>
|
||||
<string name="story_backup_description">Up to <b>3 physical cards</b> to one wallet</string>
|
||||
<string name="story_currencies_title">Thousands of Currencies</string>
|
||||
<string name="story_currencies_description">A hardware wallet for your Bitcoin, Ethereum and many more currencies simultaneously – all in one card</string>
|
||||
<string name="story_web3_title">DeFi Compatible</string>
|
||||
<string name="story_web3_description">Exchange, buy NFT’s, make loans and deposits in more than 100 different decentralized services</string>
|
||||
<string name="story_finish_title">The Wallet for Everyone</string>
|
||||
<string name="story_finish_description">Use it on the go, anywhere, anytime. No wires or batteries. Just tap the card to your phone when you need your crypto.</string>
|
||||
<string name="home_button_order">Order card</string>
|
||||
<string name="home_button_order">Order</string>
|
||||
<string name="home_button_search_tokens">Search tokens</string>
|
||||
<string name="search_tokens_title">Search tokens</string>
|
||||
<string name="alert_demo_message">You are currently running in Demo mode. All funds are not real.</string>
|
||||
<string name="alert_demo_feature_disabled">This feature is disabled in Demo mode</string>
|
||||
<string name="token_details_send_blocked_fee_format">Not enough funds for fee on your %s wallet to send a transaction. Top up your %s wallet first.</string>
|
||||
</resources>
|
||||
|
|
@ -23,7 +23,7 @@
|
|||
<string name="story_awe_title">Революционный аппаратный кошелек</string>
|
||||
<string name="story_awe_description">Держите свои криптосбережения в безопасности. Приватные ключи надежно хранятся на карте.</string>
|
||||
<string name="story_backup_title">Все ключи в безопасности</string>
|
||||
<string name="story_backup_description">До трех карт с одним кошельком</string>
|
||||
<string name="story_backup_description">До <b>трех карт</b> с одним кошельком</string>
|
||||
<string name="story_currencies_title">Тысячи криптовалют</string>
|
||||
<string name="story_currencies_description">Аппаратный кошелек для ваших биткоинов, эфира и многих других валют одновременно — все в одной карте</string>
|
||||
<string name="story_web3_title">Поддержка DeFi</string>
|
||||
|
|
@ -35,4 +35,5 @@
|
|||
<string name="search_tokens_title">Поиск токенов</string>
|
||||
<string name="alert_demo_message">Приложение работает в демонстрационном режиме. Средства на всех счетах ненастоящие.</string>
|
||||
<string name="alert_demo_feature_disabled">Эта функция недоступна в демонстрационном режиме</string>
|
||||
<string name="token_details_send_blocked_fee_format">Недостаточно средств для комиссии на вашем %s кошельке для отправки транзакции. Сначала пополните свой %s кошелек.</string>
|
||||
</resources>
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
<string name="shop_2_cards">2 cards</string>
|
||||
<string name="shop_shipping">Shipping</string>
|
||||
<string name="shop_free">Free</string>
|
||||
<string name="shop_i_have_a_promo_code">I have a promo code…</string>
|
||||
<string name="shop_i_have_a_promo_code">I have a promo code...</string>
|
||||
<string name="shop_total">Total</string>
|
||||
<string name="shop_other_payment_methods">Other payment methods</string>
|
||||
<string name="shop_buy_now">Buy now</string>
|
||||
|
|
@ -23,16 +23,17 @@
|
|||
<string name="story_awe_title">Revolutionary Hardware Wallet</string>
|
||||
<string name="story_awe_description">Store your crypto assets secure while keeping private keys contained in your card</string>
|
||||
<string name="story_backup_title">Ultra Secure Backup</string>
|
||||
<string name="story_backup_description">Up to 3 physical cards to one wallet</string>
|
||||
<string name="story_backup_description">Up to <b>3 physical cards</b> to one wallet</string>
|
||||
<string name="story_currencies_title">Thousands of Currencies</string>
|
||||
<string name="story_currencies_description">A hardware wallet for your Bitcoin, Ethereum and many more currencies simultaneously – all in one card</string>
|
||||
<string name="story_web3_title">DeFi Compatible</string>
|
||||
<string name="story_web3_description">Exchange, buy NFT’s, make loans and deposits in more than 100 different decentralized services</string>
|
||||
<string name="story_finish_title">The Wallet for Everyone</string>
|
||||
<string name="story_finish_description">Use it on the go, anywhere, anytime. No wires or batteries. Just tap the card to your phone when you need your crypto.</string>
|
||||
<string name="home_button_order">Order card</string>
|
||||
<string name="home_button_order">Order</string>
|
||||
<string name="home_button_search_tokens">Search tokens</string>
|
||||
<string name="search_tokens_title">Search tokens</string>
|
||||
<string name="alert_demo_message">You are currently running in Demo mode. All funds are not real.</string>
|
||||
<string name="alert_demo_feature_disabled">This feature is disabled in Demo mode</string>
|
||||
<string name="token_details_send_blocked_fee_format">Not enough funds for fee on your %s wallet to send a transaction. Top up your %s wallet first.</string>
|
||||
</resources>
|
||||
Loading…
Add table
Add a link
Reference in a new issue