Updated on 2026-08-14
This commit is contained in:
parent
1966925a94
commit
a98af7681e
22 changed files with 241 additions and 52 deletions
|
|
@ -4,6 +4,7 @@ import android.app.Application
|
|||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.common.redux.appReducer
|
||||
import com.tangem.tap.network.NetworkConnectivity
|
||||
import com.tangem.tap.persistence.PreferencesStorage
|
||||
import com.tangem.wallet.BuildConfig
|
||||
import org.rekotlin.Store
|
||||
import timber.log.Timber
|
||||
|
|
@ -13,10 +14,12 @@ val store = Store(
|
|||
middleware = AppState.getMiddleware(),
|
||||
state = AppState()
|
||||
)
|
||||
lateinit var preferencesStorage: PreferencesStorage
|
||||
|
||||
class TapApplication : Application() {
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
preferencesStorage = PreferencesStorage(this)
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
Timber.plant(Timber.DebugTree())
|
||||
|
|
|
|||
|
|
@ -5,6 +5,6 @@ package com.tangem.tap.common.entities
|
|||
*/
|
||||
class TapCurrency {
|
||||
companion object{
|
||||
val main = "USD"
|
||||
const val DEFAULT_FIAT_CURRENCY = "USD"
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,8 @@ import com.google.zxing.BarcodeFormat
|
|||
import com.google.zxing.EncodeHintType
|
||||
import com.google.zxing.qrcode.QRCodeWriter
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
|
||||
import com.tangem.tap.common.redux.global.FiatCurrencyName
|
||||
import com.tangem.tap.network.coinmarketcap.FiatCurrency
|
||||
import java.math.BigDecimal
|
||||
import java.math.RoundingMode
|
||||
import java.text.DecimalFormat
|
||||
|
|
@ -46,10 +48,10 @@ fun BigDecimal.toFormattedString(decimals: Int): String {
|
|||
return df.format(bd)
|
||||
}
|
||||
|
||||
fun BigDecimal.toFiatString(rateValue: BigDecimal): String? {
|
||||
fun BigDecimal.toFiatString(rateValue: BigDecimal, fiatCurrencyName: FiatCurrencyName): String? {
|
||||
var fiatValue = rateValue.multiply(this)
|
||||
fiatValue = fiatValue.setScale(2, RoundingMode.DOWN)
|
||||
return "≈ USD $fiatValue"
|
||||
return "≈ ${fiatCurrencyName} $fiatValue"
|
||||
}
|
||||
|
||||
fun BigDecimal.stripZeroPlainString(): String = this.stripTrailingZeros().toPlainString()
|
||||
|
|
@ -67,4 +69,6 @@ fun BigDecimal.isGreaterThanOrEqual(value: BigDecimal): Boolean {
|
|||
fun BigDecimal.isLessThanOrEqual(value: BigDecimal): Boolean {
|
||||
val compareResult = this.compareTo(value)
|
||||
return compareResult == -1 || compareResult == 0
|
||||
}
|
||||
}
|
||||
|
||||
fun FiatCurrency.toFormattedString(): String = "${this.name} (${this.symbol}) - ${this.sign}"
|
||||
|
|
@ -7,5 +7,11 @@ import java.math.BigDecimal
|
|||
sealed class GlobalAction : Action {
|
||||
|
||||
data class SaveScanNoteResponse(val scanNoteResponse: ScanNoteResponse) : GlobalAction()
|
||||
data class SetFiatRate(val fiatRates: Pair<String, BigDecimal>) : GlobalAction()
|
||||
data class SetFiatRate(
|
||||
val fiatRates: Pair<CryptoCurrencyName, BigDecimal>
|
||||
) : GlobalAction()
|
||||
data class ChangeAppCurrency(val appCurrency: FiatCurrencyName) : GlobalAction()
|
||||
object RestoreAppCurrency : GlobalAction() {
|
||||
data class Success(val appCurrency: FiatCurrencyName) : GlobalAction()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package com.tangem.tap.common.redux.global
|
||||
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.preferencesStorage
|
||||
import com.tangem.tap.store
|
||||
import org.rekotlin.Middleware
|
||||
|
||||
val globalMiddleware: Middleware<AppState> = { dispatch, appState ->
|
||||
{ nextDispatch ->
|
||||
{ action ->
|
||||
when (action) {
|
||||
is GlobalAction.RestoreAppCurrency -> {
|
||||
store.dispatch(GlobalAction.RestoreAppCurrency.Success(
|
||||
preferencesStorage.getAppCurrency()
|
||||
))
|
||||
}
|
||||
}
|
||||
nextDispatch(action)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -13,9 +13,15 @@ fun globalReducer(action: Action, state: AppState): GlobalState {
|
|||
is GlobalAction.SaveScanNoteResponse ->
|
||||
newState = newState.copy(scanNoteResponse = action.scanNoteResponse)
|
||||
is GlobalAction.SetFiatRate -> {
|
||||
val rates = newState.fiatRates.rates.toMutableMap()
|
||||
val rates = newState.conversionRates.rates.toMutableMap()
|
||||
rates[action.fiatRates.first] = action.fiatRates.second
|
||||
newState = newState.copy(fiatRates = FiatRates(rates))
|
||||
newState = newState.copy(conversionRates = ConversionRates(rates))
|
||||
}
|
||||
is GlobalAction.ChangeAppCurrency -> {
|
||||
newState = newState.copy(appCurrency = action.appCurrency, conversionRates = ConversionRates(mapOf()))
|
||||
}
|
||||
is GlobalAction.RestoreAppCurrency.Success -> {
|
||||
newState = newState.copy(appCurrency = action.appCurrency, conversionRates = ConversionRates(mapOf()))
|
||||
}
|
||||
}
|
||||
return newState
|
||||
|
|
|
|||
|
|
@ -1,22 +1,33 @@
|
|||
package com.tangem.tap.common.redux.global
|
||||
|
||||
import com.tangem.commands.common.network.TangemService
|
||||
import com.tangem.tap.common.entities.TapCurrency.Companion.DEFAULT_FIAT_CURRENCY
|
||||
import com.tangem.tap.domain.PayIdManager
|
||||
import com.tangem.tap.domain.TapWalletManager
|
||||
import com.tangem.tap.domain.tasks.ScanNoteResponse
|
||||
import com.tangem.tap.network.coinmarketcap.CoinMarketCapService
|
||||
import org.rekotlin.StateType
|
||||
import java.math.BigDecimal
|
||||
|
||||
data class GlobalState(
|
||||
val scanNoteResponse: ScanNoteResponse? = null,
|
||||
val tapWalletManager: TapWalletManager = TapWalletManager(),
|
||||
val fiatRates: FiatRates = FiatRates(emptyMap()),
|
||||
val payIdManager: PayIdManager = PayIdManager(),
|
||||
val coinMarketCapService: CoinMarketCapService = CoinMarketCapService(),
|
||||
val tangemService: TangemService = TangemService(),
|
||||
val conversionRates: ConversionRates = ConversionRates(emptyMap()),
|
||||
val appCurrency: FiatCurrencyName = DEFAULT_FIAT_CURRENCY
|
||||
) : StateType
|
||||
|
||||
data class FiatRates(
|
||||
val rates: Map<String, BigDecimal>
|
||||
data class ConversionRates(
|
||||
val rates: Map<CryptoCurrencyName, BigDecimal>,
|
||||
) {
|
||||
fun getRateForCryptoCurrency(currency: String): BigDecimal? {
|
||||
return rates[currency]
|
||||
|
||||
fun getRate(cryptoCurrency: CryptoCurrencyName): BigDecimal? {
|
||||
return rates[cryptoCurrency]
|
||||
}
|
||||
}
|
||||
|
||||
typealias CryptoCurrencyName = String
|
||||
typealias FiatCurrencyName = String
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import com.tangem.commands.common.network.Result
|
|||
import com.tangem.commands.common.network.TangemService
|
||||
import com.tangem.common.extensions.toHexString
|
||||
import com.tangem.tap.TapConfig
|
||||
import com.tangem.tap.common.redux.global.CryptoCurrencyName
|
||||
import com.tangem.tap.common.redux.global.FiatCurrencyName
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.domain.tasks.ScanNoteResponse
|
||||
import com.tangem.tap.features.wallet.redux.PayIdState
|
||||
|
|
@ -54,15 +56,15 @@ class TapWalletManager {
|
|||
result?.let { handlePayIdResult(it) }
|
||||
}
|
||||
|
||||
suspend fun loadFiatRate() {
|
||||
suspend fun loadFiatRate(fiatCurrency: FiatCurrencyName) {
|
||||
val wallet = store.state.globalState.scanNoteResponse?.walletManager?.wallet
|
||||
val blockchainCurrency = wallet?.blockchain?.currency
|
||||
val tokenCurrency = wallet?.token?.symbol
|
||||
|
||||
val blockchainRate = blockchainCurrency?.let { coinMarketCapService.getRate(it) }
|
||||
val tokenRate = tokenCurrency?.let { coinMarketCapService.getRate(it) }
|
||||
val blockchainRate = blockchainCurrency?.let { coinMarketCapService.getRate(it, fiatCurrency) }
|
||||
val tokenRate = tokenCurrency?.let { coinMarketCapService.getRate(it, fiatCurrency) }
|
||||
|
||||
val results = mutableListOf<Pair<String, Result<BigDecimal>?>>()
|
||||
val results = mutableListOf<Pair<CryptoCurrencyName, Result<BigDecimal>?>>()
|
||||
if (blockchainCurrency != null) results.add(blockchainCurrency to blockchainRate)
|
||||
if (tokenCurrency != null) results.add(tokenCurrency to tokenRate)
|
||||
|
||||
|
|
@ -83,7 +85,7 @@ class TapWalletManager {
|
|||
store.dispatch(WalletAction.LoadWallet)
|
||||
store.dispatch(WalletAction.LoadFiatRate)
|
||||
store.dispatch(WalletAction.LoadPayId)
|
||||
} else if (data.card.status == CardStatus.Empty){
|
||||
} else if (data.card.status == CardStatus.Empty) {
|
||||
store.dispatch(WalletAction.EmptyWallet)
|
||||
} else {
|
||||
store.dispatch(WalletAction.LoadData.Failure(TapError.UnknownBlockchain))
|
||||
|
|
@ -153,7 +155,7 @@ class TapWalletManager {
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun handleFiatRatesResult(results: List<Pair<String, Result<BigDecimal>?>>) {
|
||||
private suspend fun handleFiatRatesResult(results: List<Pair<CryptoCurrencyName, Result<BigDecimal>?>>) {
|
||||
withContext(Dispatchers.Main) {
|
||||
results.map {
|
||||
when (it.second) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
package com.tangem.tap.features.details.ui
|
||||
|
||||
import android.content.Context
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.tangem.tap.common.extensions.toFormattedString
|
||||
import com.tangem.tap.common.redux.global.FiatCurrencyName
|
||||
import com.tangem.tap.features.details.redux.DetailsAction
|
||||
import com.tangem.tap.network.coinmarketcap.FiatCurrency
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.wallet.R
|
||||
|
||||
class CurrencySelectionDialog {
|
||||
|
||||
var dialog: AlertDialog? = null
|
||||
|
||||
fun show(currencies: List<FiatCurrency>, currentAppCurrency: FiatCurrencyName, context: Context) {
|
||||
|
||||
if (dialog == null) {
|
||||
val currenciesToShow = currencies.map { it.toFormattedString() }.toTypedArray()
|
||||
var currentSelection = currencies.indexOfFirst { it.symbol == currentAppCurrency }
|
||||
|
||||
dialog = MaterialAlertDialogBuilder(context)
|
||||
.setTitle(context.getString(R.string.details_currency))
|
||||
.setNeutralButton(context.getString(R.string.generic_cancel)) { _, _ ->
|
||||
store.dispatch(DetailsAction.AppCurrencyAction.Cancel)
|
||||
}
|
||||
.setPositiveButton(context.getString(R.string.generic_done)) { _, _ ->
|
||||
val selectedCurrency = currencies[currentSelection]
|
||||
store.dispatch(DetailsAction.AppCurrencyAction.SelectAppCurrency(selectedCurrency.symbol))
|
||||
}
|
||||
.setOnDismissListener {
|
||||
store.dispatch(DetailsAction.AppCurrencyAction.Cancel)
|
||||
}
|
||||
.setSingleChoiceItems(currenciesToShow, currentSelection) { _, which ->
|
||||
currentSelection = which
|
||||
}.show()
|
||||
}
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
dialog = null
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ import android.net.Uri
|
|||
import androidx.core.content.ContextCompat.startActivity
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.common.redux.navigation.AppScreen
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.scope
|
||||
|
|
@ -25,6 +26,7 @@ val homeMiddleware: Middleware<AppState> = { dispatch, state ->
|
|||
withContext(Dispatchers.Main) {
|
||||
when (result) {
|
||||
is CompletionResult.Success -> {
|
||||
store.dispatch(GlobalAction.RestoreAppCurrency)
|
||||
store.state.globalState.tapWalletManager.onCardScanned(result.data)
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.Wallet))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package com.tangem.tap.features.send.redux.reducers
|
|||
|
||||
import com.tangem.common.extensions.isZero
|
||||
import com.tangem.tap.common.CurrencyConverter
|
||||
import com.tangem.tap.common.entities.TapCurrency
|
||||
import com.tangem.tap.common.extensions.isNegative
|
||||
import com.tangem.tap.common.extensions.stripZeroPlainString
|
||||
import com.tangem.tap.features.send.redux.AmountAction
|
||||
|
|
@ -13,6 +12,7 @@ import com.tangem.tap.features.send.redux.states.AmountState
|
|||
import com.tangem.tap.features.send.redux.states.MainCurrencyType
|
||||
import com.tangem.tap.features.send.redux.states.SendState
|
||||
import com.tangem.tap.features.send.redux.states.Value
|
||||
import com.tangem.tap.store
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
|
|
@ -42,7 +42,7 @@ class AmountReducer : SendInternalReducer {
|
|||
state.copy(
|
||||
viewAmountValue = fiatToSend.stripZeroPlainString(),
|
||||
viewBalanceValue = converter.toFiat(state.balanceCrypto).stripZeroPlainString(),
|
||||
mainCurrency = Value(MainCurrencyType.FIAT, TapCurrency.main),
|
||||
mainCurrency = Value(MainCurrencyType.FIAT, store.state.globalState.appCurrency),
|
||||
maxLengthOfAmount = sendState.getDecimals(action.mainCurrency),
|
||||
cursorAtTheSamePosition = false
|
||||
)
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@ package com.tangem.tap.features.send.redux.reducers
|
|||
import com.tangem.blockchain.common.AmountType
|
||||
import com.tangem.blockchain.common.Wallet
|
||||
import com.tangem.tap.common.CurrencyConverter
|
||||
import com.tangem.tap.common.entities.TapCurrency
|
||||
import com.tangem.tap.common.extensions.stripZeroPlainString
|
||||
import com.tangem.tap.features.send.redux.ReceiptAction.RefreshReceipt
|
||||
import com.tangem.tap.features.send.redux.SendScreenAction
|
||||
import com.tangem.tap.features.send.redux.states.*
|
||||
import com.tangem.tap.store
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
@ -163,7 +163,7 @@ class ReceiptReducer : SendInternalReducer {
|
|||
|
||||
private fun determineSymbols(wallet: Wallet): ReceiptSymbols {
|
||||
return ReceiptSymbols(
|
||||
fiat = TapCurrency.main,
|
||||
fiat = store.state.globalState.appCurrency,
|
||||
crypto = wallet.blockchain.currency,
|
||||
token = wallet.amounts[AmountType.Token]?.currencySymbol
|
||||
)
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ private class PrepareSendScreenStatesReducer : SendInternalReducer {
|
|||
}
|
||||
|
||||
private fun createCurrencyConverter(walletManager: WalletManager): CurrencyConverter {
|
||||
val rate = store.state.globalState.fiatRates.getRateForCryptoCurrency(walletManager.wallet.blockchain.currency)
|
||||
val rate = store.state.globalState.conversionRates.getRate(walletManager.wallet.blockchain.currency)
|
||||
return if (rate == null) CurrencyConverter(BigDecimal.ONE) else CurrencyConverter(rate)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import com.tangem.blockchain.common.AmountType
|
|||
import com.tangem.blockchain.common.WalletManager
|
||||
import com.tangem.common.extensions.isZero
|
||||
import com.tangem.tap.common.CurrencyConverter
|
||||
import com.tangem.tap.common.entities.TapCurrency
|
||||
import com.tangem.tap.features.send.redux.AmountAction
|
||||
import com.tangem.tap.store
|
||||
import org.rekotlin.StateType
|
||||
|
|
@ -60,7 +59,7 @@ enum class SendButtonState {
|
|||
data class AmountState(
|
||||
val viewAmountValue: String = BigDecimal.ZERO.toPlainString(),
|
||||
val viewBalanceValue: String = BigDecimal.ZERO.toPlainString(),
|
||||
val mainCurrency: Value<MainCurrencyType> = Value(MainCurrencyType.FIAT, TapCurrency.main),
|
||||
val mainCurrency: Value<MainCurrencyType> = Value(MainCurrencyType.FIAT, store.state.globalState.appCurrency),
|
||||
val typeOfAmount: AmountType = AmountType.Coin,
|
||||
val amountToSendCrypto: BigDecimal = BigDecimal.ZERO,
|
||||
val balanceCrypto: BigDecimal = BigDecimal.ZERO,
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) {
|
|||
|
||||
private fun restoreMainCurrency(): MainCurrencyType {
|
||||
val sp = requireContext().getSharedPreferences("SendScreen", Context.MODE_PRIVATE)
|
||||
val mainCurrency = sp.getString("mainCurrency", TapCurrency.main)
|
||||
val mainCurrency = sp.getString("mainCurrency", TapCurrency.DEFAULT_FIAT_CURRENCY)
|
||||
val foundType = MainCurrencyType.values()
|
||||
.firstOrNull { it.name.toLowerCase() == mainCurrency!!.toLowerCase() } ?: MainCurrencyType.FIAT
|
||||
return foundType
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.tangem.blockchain.common.Wallet
|
|||
import com.tangem.commands.Card
|
||||
import com.tangem.tap.common.redux.ErrorAction
|
||||
import com.tangem.tap.common.redux.NotificationAction
|
||||
import com.tangem.tap.common.redux.global.CryptoCurrencyName
|
||||
import com.tangem.tap.domain.TapError
|
||||
import com.tangem.wallet.R
|
||||
import org.rekotlin.Action
|
||||
|
|
@ -24,7 +25,7 @@ sealed class WalletAction : Action {
|
|||
}
|
||||
|
||||
object LoadFiatRate : WalletAction() {
|
||||
data class Success(val fiatRates: Pair<String, BigDecimal>) : WalletAction()
|
||||
data class Success(val fiatRates: Pair<CryptoCurrencyName, BigDecimal?>) : WalletAction()
|
||||
object Failure : WalletAction()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ val walletMiddleware: Middleware<AppState> = { dispatch, state ->
|
|||
}
|
||||
is WalletAction.LoadFiatRate -> {
|
||||
scope.launch {
|
||||
store.state.globalState.tapWalletManager.loadFiatRate()
|
||||
store.state.globalState.tapWalletManager.loadFiatRate(store.state.globalState.appCurrency)
|
||||
}
|
||||
}
|
||||
is WalletAction.LoadArtwork -> {
|
||||
|
|
|
|||
|
|
@ -86,10 +86,11 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
|
|||
)
|
||||
}
|
||||
is WalletAction.LoadWallet.Success -> {
|
||||
val fiatCurrencySymbol = state.globalState.appCurrency
|
||||
val token = action.wallet.amounts[AmountType.Token]
|
||||
val tokenData = if (token != null) {
|
||||
val tokenFiatRate = state.globalState.fiatRates.getRateForCryptoCurrency(token.currencySymbol)
|
||||
val tokenFiatAmount = tokenFiatRate?.let { token.value?.toFiatString(it) }
|
||||
val tokenFiatRate = state.globalState.conversionRates.getRate(token.currencySymbol)
|
||||
val tokenFiatAmount = tokenFiatRate?.let { token.value?.toFiatString(it, fiatCurrencySymbol) }
|
||||
TokenData(
|
||||
token.value?.toFormattedString(token.decimals) ?: "",
|
||||
token.currencySymbol, tokenFiatAmount)
|
||||
|
|
@ -97,8 +98,8 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
|
|||
null
|
||||
}
|
||||
val amount = action.wallet.amounts[AmountType.Coin]?.value
|
||||
val fiatRate = state.globalState.fiatRates.getRateForCryptoCurrency(action.wallet.blockchain.currency)
|
||||
val fiatAmount = fiatRate?.let { amount?.toFiatString(it) }
|
||||
val fiatRate = state.globalState.conversionRates.getRate(action.wallet.blockchain.currency)
|
||||
val fiatAmount = fiatRate?.let { amount?.toFiatString(it, fiatCurrencySymbol) }
|
||||
|
||||
val pendingTransactions = action.wallet.transactions
|
||||
.toPendingTransactions(action.wallet.address)
|
||||
|
|
@ -135,16 +136,24 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
|
|||
errorMessage = action.errorMessage
|
||||
)
|
||||
)
|
||||
is WalletAction.LoadFiatRate -> {
|
||||
newState.copy(currencyData = newState.currencyData.copy(
|
||||
fiatAmount = null,
|
||||
token = newState.currencyData.token?.copy(fiatAmount = null))
|
||||
)
|
||||
}
|
||||
is WalletAction.LoadFiatRate.Success -> {
|
||||
val rate = action.fiatRates.second
|
||||
val rate = action.fiatRates.second ?: return newState
|
||||
val currency = action.fiatRates.first
|
||||
val fiatAmount = if (currency == newState.wallet?.blockchain?.currency) {
|
||||
newState.wallet?.amounts?.get(AmountType.Coin)?.value?.toFiatString(rate)
|
||||
newState.wallet?.amounts?.get(AmountType.Coin)?.value
|
||||
?.toFiatString(rate, state.globalState.appCurrency)
|
||||
} else {
|
||||
newState.currencyData.fiatAmount
|
||||
}
|
||||
val tokenFiatAmount = if (currency == newState.wallet?.token?.symbol) {
|
||||
newState.wallet?.amounts?.get(AmountType.Token)?.value?.toFiatString(rate)
|
||||
newState.wallet?.amounts?.get(AmountType.Token)?.value
|
||||
?.toFiatString(rate, state.globalState.appCurrency)
|
||||
} else {
|
||||
newState.currencyData.token?.fiatAmount
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,9 +12,14 @@ interface CoinMarketCapApi {
|
|||
@GET("v1/tools/price-conversion")
|
||||
suspend fun getRateInfo(
|
||||
@Query("amount") amount: Int,
|
||||
@Query("symbol") cryptoId: String
|
||||
@Query("symbol") cryptoCurrencyName: String,
|
||||
@Query("convert") fiatCurrencyName: String? = null
|
||||
): RateInfoResponse
|
||||
|
||||
@GET("v1/fiat/map")
|
||||
suspend fun getFiatMap(): FiatMapResponse
|
||||
|
||||
|
||||
companion object {
|
||||
private const val baseUrl = "https://pro-api.coinmarketcap.com/"
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.tap.network.coinmarketcap
|
|||
|
||||
import com.tangem.commands.common.network.Result
|
||||
import com.tangem.commands.common.network.performRequest
|
||||
import com.tangem.tap.common.redux.global.FiatCurrencyName
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.math.BigDecimal
|
||||
|
|
@ -9,10 +10,20 @@ import java.math.BigDecimal
|
|||
class CoinMarketCapService {
|
||||
private val api: CoinMarketCapApi by lazy { CoinMarketCapApi.create() }
|
||||
|
||||
suspend fun getRate(currency: String): Result<BigDecimal> = withContext(Dispatchers.IO) {
|
||||
val response = performRequest { api.getRateInfo(1, currency) }
|
||||
suspend fun getRate(
|
||||
currency: String, fiatCurrency: FiatCurrencyName? = null
|
||||
): Result<BigDecimal> = withContext(Dispatchers.IO) {
|
||||
val response = performRequest { api.getRateInfo(1, currency, fiatCurrency) }
|
||||
return@withContext when (response) {
|
||||
is Result.Success -> Result.Success(response.data.data.quote.usd.price)
|
||||
is Result.Success -> Result.Success(response.data.data.getRate())
|
||||
is Result.Failure -> response
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getFiatCurrencies(): Result<List<FiatCurrency>> = withContext(Dispatchers.IO) {
|
||||
val response = performRequest { api.getFiatMap() }
|
||||
return@withContext when (response) {
|
||||
is Result.Success -> Result.Success(response.data.data.sortedBy { it.name })
|
||||
is Result.Failure -> response
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,21 +5,14 @@ import com.squareup.moshi.JsonClass
|
|||
import java.math.BigDecimal
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class RateInfoResponse(
|
||||
val status: Status,
|
||||
val data: RateData
|
||||
)
|
||||
class RateInfoResponse : CoinMarketResponse<RateData>()
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class RateData(
|
||||
val quote: Quote
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class Quote(
|
||||
@Json(name = "USD")
|
||||
val usd: CurrencyRate
|
||||
)
|
||||
val quote: Map<String, CurrencyRate>
|
||||
) {
|
||||
fun getRate(): BigDecimal = quote.values.first().price
|
||||
}
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class CurrencyRate(
|
||||
|
|
@ -38,4 +31,21 @@ data class Status(
|
|||
@Json(name = "credit_count")
|
||||
val creditCount: Int,
|
||||
val notice: String?
|
||||
)
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
class FiatMapResponse : CoinMarketResponse<List<FiatCurrency>>()
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
open class CoinMarketResponse<T : Any> {
|
||||
lateinit var status: Status
|
||||
lateinit var data: T
|
||||
}
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class FiatCurrency(
|
||||
val id: Int,
|
||||
val name: String,
|
||||
val sign: String,
|
||||
val symbol: String
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
package com.tangem.tap.persistence
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import com.squareup.moshi.JsonAdapter
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.squareup.moshi.Types
|
||||
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
|
||||
import com.tangem.tap.common.entities.TapCurrency.Companion.DEFAULT_FIAT_CURRENCY
|
||||
import com.tangem.tap.common.redux.global.FiatCurrencyName
|
||||
import com.tangem.tap.network.coinmarketcap.FiatCurrency
|
||||
|
||||
|
||||
class PreferencesStorage(applicationContext: Application) {
|
||||
|
||||
private val preferences: SharedPreferences by lazy {
|
||||
applicationContext.getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE)
|
||||
}
|
||||
|
||||
private val fiatCurrenciesAdapter: JsonAdapter<List<FiatCurrency>> by lazy {
|
||||
val moshi = Moshi.Builder()
|
||||
.add(KotlinJsonAdapterFactory())
|
||||
.build()
|
||||
val type = Types.newParameterizedType(List::class.java, FiatCurrency::class.java)
|
||||
moshi.adapter(type)
|
||||
}
|
||||
|
||||
fun getAppCurrency(): FiatCurrencyName {
|
||||
return preferences.getString(APP_CURRENCY_KEY, DEFAULT_FIAT_CURRENCY)
|
||||
?: DEFAULT_FIAT_CURRENCY
|
||||
}
|
||||
|
||||
fun saveAppCurrency(fiatCurrencyName: FiatCurrencyName) {
|
||||
return preferences.edit().putString(APP_CURRENCY_KEY, fiatCurrencyName).apply()
|
||||
}
|
||||
|
||||
fun getFiatCurrencies(): List<FiatCurrency>? {
|
||||
val json = preferences.getString(FIAT_CURRENCIES_KEY, "")
|
||||
return if (json.isNullOrBlank()) null else fiatCurrenciesAdapter.fromJson(json) as List<FiatCurrency>
|
||||
}
|
||||
|
||||
fun saveFiatCurrencies(currencies: List<FiatCurrency>) {
|
||||
val json: String = fiatCurrenciesAdapter.toJson(currencies)
|
||||
return preferences.edit().putString(FIAT_CURRENCIES_KEY, json).apply()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val PREFERENCES_NAME = "tapPrefs"
|
||||
private const val APP_CURRENCY_KEY = "appCurrency"
|
||||
private const val FIAT_CURRENCIES_KEY = "fiatCurrencies"
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue