Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatic refresh #1026

Merged
merged 11 commits into from
Jul 5, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,20 @@ import com.babylon.wallet.android.data.repository.tokenprice.FiatPriceRepository
import com.babylon.wallet.android.domain.RadixWalletException
import com.radixdlt.sargon.NetworkId
import com.radixdlt.sargon.ResourceAddress
import com.radixdlt.sargon.Timestamp
import com.radixdlt.sargon.extensions.init
import com.radixdlt.sargon.extensions.string
import com.radixdlt.sargon.extensions.toDecimal192
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.withContext
import okhttp3.ResponseBody
import rdx.works.core.domain.assets.FiatPrice
import rdx.works.core.domain.assets.SupportedCurrency
import rdx.works.core.domain.resources.XrdResource
import rdx.works.core.domain.toDouble
import rdx.works.peerdroid.di.IoDispatcher
import timber.log.Timber
import java.time.OffsetDateTime
import javax.inject.Inject
import javax.inject.Qualifier
import kotlin.random.Random
Expand Down Expand Up @@ -156,6 +160,8 @@ class TestnetFiatPriceRepository @Inject constructor(
"resource_rdx1tkk83magp3gjyxrpskfsqwkg4g949rmcjee4tu2xmw93ltw2cz94sq"
).map { ResourceAddress.init(it) }

private val testnetPricesCache: MutableMap<ResourceAddress, TestnetPrice> = mutableMapOf()

override suspend fun updateFiatPrices(currency: SupportedCurrency): Result<Unit> {
if (!BuildConfig.EXPERIMENTAL_FEATURES_ENABLED) {
return Result.failure(FiatPriceRepository.PricesNotSupportedInNetwork())
Expand Down Expand Up @@ -191,8 +197,7 @@ class TestnetFiatPriceRepository @Inject constructor(
if (priceRequestAddress.address in XrdResource.addressesPerNetwork().values) {
priceRequestAddress.address to xrdPrice
} else {
val randomPrice = prices.entries.elementAt(Random.nextInt(prices.entries.size)).value
priceRequestAddress.address to randomPrice
priceRequestAddress.address to getTestnetPrice(address = priceRequestAddress.address, isRefreshing = isRefreshing)
}
}.mapNotNull { addressAndFiatPrice ->
addressAndFiatPrice.value?.let { fiatPrice -> addressAndFiatPrice.key to fiatPrice }
Expand All @@ -202,4 +207,50 @@ class TestnetFiatPriceRepository @Inject constructor(
}
}
}

private fun getTestnetPrice(address: ResourceAddress, isRefreshing: Boolean): FiatPrice {
val cachedPrice = testnetPricesCache[address]

return if (cachedPrice == null) {
FiatPrice(
price = Random.nextDouble(from = 0.01, until = 1.0).toDecimal192(),
currency = SupportedCurrency.USD
).also {
testnetPricesCache[address] = TestnetPrice(
price = it,
updatedAt = Timestamp.now()
)
}
} else {
val lastUpdatedAt = cachedPrice.updatedAt
if (isRefreshing || lastUpdatedAt.isBefore(OffsetDateTime.now().minusMinutes(MEMORY_CACHE_VALIDITY_MINUTES))) {
val price = cachedPrice.price.price.toDouble()
FiatPrice(
price = Random.nextDouble(
from = (price - PRICE_FLUCTUATION).coerceAtLeast(PRICE_MINIMUM),
until = price + PRICE_FLUCTUATION
).toDecimal192(),
currency = SupportedCurrency.USD
).also {
testnetPricesCache[address] = TestnetPrice(
price = it,
updatedAt = Timestamp.now()
)
}
} else {
cachedPrice.price
}
}
}

private data class TestnetPrice(
val price: FiatPrice,
val updatedAt: Timestamp
)

companion object {
private const val MEMORY_CACHE_VALIDITY_MINUTES = 5L
private const val PRICE_FLUCTUATION = 0.01
private const val PRICE_MINIMUM = 0.01
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.babylon.wallet.android.domain.usecases

import com.radixdlt.sargon.AddressOfAccountOrPersona
import com.radixdlt.sargon.FactorSource
import com.radixdlt.sargon.FactorSourceId
import com.radixdlt.sargon.extensions.ProfileEntity
Expand Down Expand Up @@ -78,6 +79,16 @@ data class EntityWithSecurityPrompt(
val prompts: Set<SecurityPromptType>
)

fun List<EntityWithSecurityPrompt>.accountPrompts() = mapNotNull {
val accountAddress = it.entity.address as? AddressOfAccountOrPersona.Account ?: return@mapNotNull null
accountAddress.v1 to it.prompts
}.associate { it }

fun List<EntityWithSecurityPrompt>.personaPrompts() = mapNotNull {
val identityAddress = it.entity.address as? AddressOfAccountOrPersona.Identity ?: return@mapNotNull null
identityAddress.v1 to it.prompts
}.associate { it }

enum class SecurityPromptType {
WRITE_DOWN_SEED_PHRASE,
RECOVERY_REQUIRED,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ import com.babylon.wallet.android.designsystem.theme.RadixTheme
import com.babylon.wallet.android.designsystem.theme.gradient
import com.babylon.wallet.android.domain.model.assets.AccountWithAssets
import com.babylon.wallet.android.domain.usecases.SecurityPromptType
import com.babylon.wallet.android.presentation.account.AccountViewModel.Event
import com.babylon.wallet.android.presentation.account.AccountViewModel.State
import com.babylon.wallet.android.presentation.transfer.assets.AssetsTab
import com.babylon.wallet.android.presentation.ui.RadixWalletPreviewTheme
import com.babylon.wallet.android.presentation.ui.composables.ApplySecuritySettingsLabel
Expand Down Expand Up @@ -87,9 +89,9 @@ fun AccountScreen(
LaunchedEffect(Unit) {
viewModel.oneOffEvent.collect {
when (it) {
is AccountEvent.NavigateToSecurityCenter -> onNavigateToSecurityCenter()
is AccountEvent.OnFungibleClick -> onFungibleResourceClick(it.resource, it.account)
is AccountEvent.OnNonFungibleClick -> onNonFungibleResourceClick(it.resource, it.item, it.account)
is Event.NavigateToSecurityCenter -> onNavigateToSecurityCenter()
is Event.OnFungibleClick -> onFungibleResourceClick(it.resource, it.account)
is Event.OnNonFungibleClick -> onNonFungibleResourceClick(it.resource, it.item, it.account)
}
}
}
Expand Down Expand Up @@ -127,7 +129,7 @@ fun AccountScreen(
@Composable
private fun AccountScreenContent(
modifier: Modifier = Modifier,
state: AccountUiState,
state: State,
onShowHideBalanceToggle: (isVisible: Boolean) -> Unit,
onAccountPreferenceClick: (address: AccountAddress) -> Unit,
onBackClick: () -> Unit,
Expand Down Expand Up @@ -235,7 +237,7 @@ private fun AccountScreenContent(
fun AssetsContent(
modifier: Modifier = Modifier,
lazyListState: LazyListState,
state: AccountUiState,
state: State,
onShowHideBalanceToggle: (isVisible: Boolean) -> Unit,
onTabClick: (AssetsTab) -> Unit,
onCollectionClick: (String) -> Unit,
Expand All @@ -259,10 +261,10 @@ fun AssetsContent(
state.accountWithAssets?.account?.address
}

val assetsViewData = remember(state.accountWithAssets?.assets, state.assetsWithAssetsPrices, state.epoch) {
val assetsViewData = remember(state.accountWithAssets?.assets, state.assetsWithPrices, state.epoch) {
AssetsViewData.from(
assets = state.accountWithAssets?.assets,
prices = state.assetsWithAssetsPrices,
prices = state.assetsWithPrices,
epoch = state.epoch
)
}
Expand Down Expand Up @@ -291,7 +293,7 @@ fun AssetsContent(
)
}

if (state.isFiatBalancesEnabled) {
if (!state.isPricesDisabled) {
TotalFiatBalanceView(
modifier = Modifier.padding(bottom = RadixTheme.dimensions.paddingXXLarge),
fiatPrice = state.totalFiatValue,
Expand Down Expand Up @@ -370,17 +372,13 @@ fun AssetsContent(
}

assetsView(
assetsViewData = if (state.isFiatBalancesEnabled) {
assetsViewData = if (!state.isPricesDisabled) {
assetsViewData
} else {
assetsViewData?.copy(prices = null)
},
state = state.assetsViewState,
isLoadingBalance = if (state.isFiatBalancesEnabled) {
state.isAccountBalanceLoading
} else {
false
},
isLoadingBalance = state.isAccountBalanceLoading,
action = AssetsViewAction.Click(
onFungibleClick = onFungibleTokenClick,
onNonFungibleItemClick = onNonFungibleItemClick,
Expand Down Expand Up @@ -450,11 +448,11 @@ private fun HistoryButton(
fun AccountContentPreview() {
RadixWalletPreviewTheme {
AccountScreenContent(
state = AccountUiState(
state = State(
pricesState = State.PricesState.Enabled(emptyMap()),
accountWithAssets = AccountWithAssets(
account = Account.sampleMainnet()
),
assetsWithAssetsPrices = emptyMap(),
securityPrompts = listOf(
SecurityPromptType.WRITE_DOWN_SEED_PHRASE,
SecurityPromptType.CONFIGURATION_BACKUP_PROBLEM
Expand Down Expand Up @@ -486,12 +484,11 @@ fun AccountContentPreview() {
fun AccountContentWithFiatBalancesDisabledPreview() {
RadixWalletPreviewTheme {
AccountScreenContent(
state = AccountUiState(
isFiatBalancesEnabled = false,
state = State(
pricesState = State.PricesState.Disabled,
accountWithAssets = AccountWithAssets(
account = Account.sampleMainnet()
),
assetsWithAssetsPrices = emptyMap()
)
),
onShowHideBalanceToggle = {},
onAccountPreferenceClick = { _ -> },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import com.babylon.wallet.android.R
import com.babylon.wallet.android.designsystem.composable.RadixSecondaryButton
import com.babylon.wallet.android.designsystem.theme.RadixTheme
import com.babylon.wallet.android.domain.usecases.SecurityPromptType
import com.babylon.wallet.android.presentation.account.AccountViewModel.State
import com.babylon.wallet.android.presentation.ui.composables.ApplySecuritySettingsLabel
import com.babylon.wallet.android.presentation.ui.composables.actionableaddress.ActionableAddressView
import com.babylon.wallet.android.presentation.ui.composables.toText
Expand All @@ -42,7 +43,7 @@ import com.radixdlt.sargon.Address
@Composable
fun AccountTopBar(
modifier: Modifier = Modifier,
state: AccountUiState,
state: State,
lazyListState: LazyListState,
onBackClick: () -> Unit,
onAccountPreferenceClick: (AccountAddress) -> Unit,
Expand Down
Loading
Loading