Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.gemwallet.android.data.repositories.transactions

import com.gemwallet.android.data.repositories.perpetual.PerpetualRepository
import com.gemwallet.android.data.repositories.stake.StakeRepository
import com.gemwallet.android.domains.stake.rewardsBalance
import com.gemwallet.android.domains.stake.sumRewardsBalance
import com.gemwallet.android.domains.transaction.TransactionBalanceContext
import com.gemwallet.android.domains.transaction.balance
Expand Down Expand Up @@ -71,7 +72,7 @@ class TransactionBalanceService @Inject constructor(
): TransactionBalanceContext {
return when (params.txType) {
TransactionType.StakeRewards -> TransactionBalanceContext(
rewardsBalance = getRewardsBalance(assetInfo),
rewardsBalance = delegation?.rewardsBalance() ?: getRewardsBalance(assetInfo),
)
TransactionType.StakeUndelegate,
TransactionType.StakeRedelegate,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ import com.gemwallet.android.application.confirm.coordinators.ValidateBalance
import com.gemwallet.android.blockchain.services.SignerPreloaderProxy
import com.gemwallet.android.data.repositories.assets.AssetsRepository
import com.gemwallet.android.data.repositories.session.SessionRepository
import com.gemwallet.android.data.repositories.stake.StakeRepository
import com.gemwallet.android.data.repositories.transactions.TransactionBalanceService
import com.gemwallet.android.domains.stake.sumRewardsBalance
import com.gemwallet.android.domains.asset.chain
import com.gemwallet.android.ext.asset
import com.gemwallet.android.ext.getAccount
Expand Down Expand Up @@ -64,7 +62,6 @@ class ConfirmViewModel @Inject constructor(
private val sessionRepository: SessionRepository,
private val assetsRepository: AssetsRepository,
private val signerPreload: SignerPreloaderProxy,
private val stakeRepository: StakeRepository,
private val transactionBalanceService: TransactionBalanceService,
private val validateBalance: ValidateBalance,
private val confirmTransaction: ConfirmTransaction,
Expand Down Expand Up @@ -149,8 +146,7 @@ class ConfirmViewModel @Inject constructor(
}

val finalAmount = when {
preload.input is ConfirmParams.Stake.RewardsParams ->
stakeRepository.getRewards(preload.input.assetId, preload.input.from.address).sumRewardsBalance()
preload.input is ConfirmParams.Stake.RewardsParams -> preload.input.amount
preload.input.useMaxAmount && preload.input.assetId == preload.fee().feeAssetId ->
preload.input.amount - preload.fee().amount
else -> preload.input.amount
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.gemwallet.android.features.earn.delegation.presents

import androidx.compose.foundation.clickable
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
Expand Down Expand Up @@ -35,6 +37,7 @@ fun DelegationScene(
val properties by viewModel.properties.collectAsStateWithLifecycle()
val balances by viewModel.balances.collectAsStateWithLifecycle()
val actions by viewModel.actions.collectAsStateWithLifecycle()
val canClaimRewards by viewModel.canClaimRewards.collectAsStateWithLifecycle()

if (uiState == null) {
LoadingScene(title = stringResource(id = R.string.transfer_stake_title), onCancel = onCancel)
Expand Down Expand Up @@ -72,9 +75,16 @@ fun DelegationScene(
}

itemsPositioned(balances) { position, item ->
val modifier = if (canClaimRewards) {
Modifier.clickable { viewModel.onClaimRewards(onConfirm) }
} else {
Modifier
}
PropertyAssetBalanceItem(
model = item,
title = stringResource(R.string.stake_rewards),
modifier = modifier,
showChevron = canClaimRewards,
listPosition = position,
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import com.gemwallet.android.data.repositories.assets.AssetsRepository
import com.gemwallet.android.data.repositories.session.SessionRepository
import com.gemwallet.android.data.repositories.stake.StakeRepository
import com.gemwallet.android.domains.asset.chain
import com.gemwallet.android.domains.stake.rewardsBalance
import com.gemwallet.android.ext.byChain
import com.gemwallet.android.ext.claimed
import com.gemwallet.android.ext.redelegated
import com.gemwallet.android.model.AmountParams
import com.gemwallet.android.model.ConfirmParams
Expand Down Expand Up @@ -120,6 +122,20 @@ class DelegationViewModel @Inject constructor(
}
.stateIn(viewModelScope, SharingStarted.Eagerly, emptyList())

val canClaimRewards = combine(
delegation,
assetInfo,
sessionRepository.session().filterNotNull(),
) { delegation, assetInfo, session ->
if (delegation == null || assetInfo == null || session.wallet.type == WalletType.View) {
return@combine false
}
delegation.base.state == DelegationState.Active
&& assetInfo.asset.id.chain.claimed
&& delegation.rewardsBalance() > BigInteger.ZERO
}
.stateIn(viewModelScope, SharingStarted.Eagerly, false)

val delegationInfo = combine(
delegation,
assetInfo,
Expand Down Expand Up @@ -169,6 +185,20 @@ class DelegationViewModel @Inject constructor(
call(params)
}

fun onClaimRewards(call: ConfirmTransactionAction) {
val assetInfo = assetInfo.value ?: return
val from = assetInfo.owner ?: return
val delegation = delegation.value ?: return
call(
ConfirmParams.Stake.RewardsParams(
asset = assetInfo.asset,
from = from,
validators = listOf(delegation.validator),
amount = delegation.rewardsBalance(),
)
)
}

private fun buildStake(type: TransactionType): AmountParams {
return AmountParams.buildStake(
assetId = assetInfo.value?.asset?.id!!,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ fun StakeScene(
delegations: List<Delegation>,
amountAction: AmountTransactionAction,
onRefresh: () -> Unit,
onConfirm: () -> Unit,
onRewards: () -> Unit,
onDelegation: (String, String) -> Unit,
onCancel: () -> Unit,
) {
Expand Down Expand Up @@ -94,7 +94,7 @@ fun StakeScene(
isStakeEnabled = isStakeEnabled,
assetId = assetInfo.id(),
amountAction = amountAction,
onConfirm = onConfirm,
onRewards = onRewards,
)

energyItem(assetInfo.balance.metadata)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ import androidx.compose.runtime.getValue
import androidx.compose.ui.res.stringResource
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.gemwallet.android.model.ConfirmParams
import com.gemwallet.android.ui.R
import com.gemwallet.android.ui.components.screen.LoadingScene
import com.gemwallet.android.ui.models.actions.AmountTransactionAction
import com.gemwallet.android.ui.models.actions.ConfirmTransactionAction
import com.gemwallet.android.features.stake.viewmodels.StakeViewModel

@Composable
fun StakeScreen(
amountAction: AmountTransactionAction,
onConfirm: (ConfirmParams) -> Unit,
onConfirm: ConfirmTransactionAction,
onDelegation: (String, String) -> Unit,
onCancel: () -> Unit,
viewModel: StakeViewModel = hiltViewModel()
Expand All @@ -39,7 +39,7 @@ fun StakeScreen(
isStakeEnabled = isStakeEnabled,
onRefresh = viewModel::onRefresh,
amountAction = amountAction,
onConfirm = { viewModel.onRewards(onConfirm) },
onRewards = { viewModel.onRewards(amountAction, onConfirm) },
onDelegation = onDelegation,
onCancel = onCancel
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,19 @@ internal fun LazyListScope.stakeActions(
isStakeEnabled: Boolean,
assetId: AssetId,
amountAction: AmountTransactionAction,
onConfirm: () -> Unit
onRewards: () -> Unit
) {
item {
SubheaderItem(R.string.common_manage)
}
itemsPositioned(actions) { position, item ->
val title = when (item) {
is StakeAction.Rewards -> R.string.transfer_rewards_title
is StakeAction.Rewards -> R.string.transfer_claim_rewards_title
StakeAction.Stake -> R.string.transfer_stake_title
StakeAction.Freeze -> R.string.transfer_freeze_title
StakeAction.Unfreeze -> R.string.transfer_unfreeze_title
}
val onClick = when(item) {
val onClick = when (item) {
StakeAction.Stake,
StakeAction.Freeze,
StakeAction.Unfreeze -> {
Expand All @@ -45,7 +45,7 @@ internal fun LazyListScope.stakeActions(
)
}
}
is StakeAction.Rewards -> onConfirm
is StakeAction.Rewards -> onRewards
}
val enabled = !item.requiresValidators() || isStakeEnabled
PropertyItem(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,20 @@ import com.gemwallet.android.domains.stake.rewardsBalance
import com.gemwallet.android.domains.stake.sumRewardsBalance
import com.gemwallet.android.domains.asset.chain
import com.gemwallet.android.domains.asset.stakeChain
import com.gemwallet.android.ext.claimAllAvailable
import com.gemwallet.android.ext.claimed
import com.gemwallet.android.ext.freezed
import com.gemwallet.android.ext.getAccount
import com.gemwallet.android.ext.toIdentifier
import com.gemwallet.android.ext.toAssetId
import com.gemwallet.android.model.AmountParams
import com.gemwallet.android.model.ConfirmParams
import com.gemwallet.android.model.Crypto
import com.gemwallet.android.model.format
import com.gemwallet.android.ui.models.actions.AmountTransactionAction
import com.gemwallet.android.ui.models.actions.ConfirmTransactionAction
import com.gemwallet.android.features.stake.models.StakeAction
import com.wallet.core.primitives.TransactionType
import com.wallet.core.primitives.WalletType
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
Expand Down Expand Up @@ -100,7 +105,16 @@ class StakeViewModel @Inject constructor(
StakeAction.Unfreeze.takeIf { assetInfo.stakeChain?.freezed() == true },
rewardsBalance
.takeIf { assetInfo.chain.claimed && rewardsBalance > BigInteger.ZERO }
?.let { StakeAction.Rewards(assetInfo.asset.format(Crypto(rewardsBalance))) },
?.let {
StakeAction.Rewards(
data = assetInfo.asset.format(
crypto = Crypto(rewardsBalance),
decimalPlace = 2,
maxDecimals = assetInfo.asset.decimals,
dynamicPlace = true,
),
)
},
)
}.stateIn(viewModelScope, SharingStarted.Eagerly, emptyList())

Expand Down Expand Up @@ -129,20 +143,27 @@ class StakeViewModel @Inject constructor(
sync.update { true }
}

fun onRewards(onConfirm: (ConfirmParams) -> Unit) {
fun onRewards(onAmount: AmountTransactionAction, onConfirm: ConfirmTransactionAction) {
val assetInfo = assetInfo.value ?: return
val account = account.value ?: return
val validators = delegations.value.filter { it.rewardsBalance() > BigInteger.ZERO }
.map { it.validator }
.toSet()
.toList()
onConfirm(
ConfirmParams.Stake.RewardsParams(
asset = assetInfo.asset,
from = account,
validators = validators,
amount = rewardsBalance.value
val withRewards = delegations.value.filter { it.rewardsBalance() > BigInteger.ZERO }
val canClaimAllRewards = assetInfo.chain.claimAllAvailable || withRewards.size == 1
if (canClaimAllRewards) {
onConfirm(
ConfirmParams.Stake.RewardsParams(
asset = assetInfo.asset,
from = account,
validators = withRewards.map { it.validator },
amount = withRewards.sumOf { it.rewardsBalance() },
)
)
)
} else {
onAmount(
AmountParams.buildStake(
assetId = assetInfo.asset.id,
txType = TransactionType.StakeRewards,
)
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.gemwallet.android.model.ConfirmParams
import com.gemwallet.android.ui.R
import com.gemwallet.android.ui.components.screen.LoadingScene
import com.gemwallet.android.features.transfer_amount.models.ValidatorsSource
import com.gemwallet.android.features.transfer_amount.viewmodels.AmountViewModel
import com.wallet.core.primitives.Currency
import com.wallet.core.primitives.TransactionType

@Composable
fun AmountScreen(
Expand Down Expand Up @@ -73,15 +75,25 @@ fun AmountScreen(
label = "stake"
) { state ->
when (state) {
true -> ValidatorsScreen(
chain = assetInfo?.asset?.id?.chain ?: return@AnimatedContent,
selectedValidatorId = validatorState?.id!!,
onCancel = { isSelectValidator = false },
onSelect = {
isSelectValidator = false
viewModel.setDelegatorValidator(it)
true -> {
val asset = assetInfo?.asset ?: return@AnimatedContent
val source = when (params?.txType) {
TransactionType.StakeRewards -> ValidatorsSource.Rewards(
assetId = asset.id,
owner = assetInfo?.owner?.address ?: return@AnimatedContent,
)
else -> ValidatorsSource.ChainValidators(chain = asset.id.chain)
}
)
ValidatorsScreen(
source = source,
selectedValidatorId = validatorState?.id!!,
onCancel = { isSelectValidator = false },
onSelect = {
isSelectValidator = false
viewModel.setDelegatorValidator(it)
}
)
}
false -> AmountScene(
amount = viewModel.amount,
amountPrefill = amountPrefill,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,20 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.gemwallet.android.ui.R
import com.gemwallet.android.ui.components.screen.FatalStateScene
import com.gemwallet.android.ui.components.screen.LoadingScene
import com.gemwallet.android.features.transfer_amount.models.ValidatorsSource
import com.gemwallet.android.features.transfer_amount.models.ValidatorsUIState
import com.gemwallet.android.features.transfer_amount.viewmodels.ValidatorsViewModel
import com.wallet.core.primitives.Chain

@Composable
fun ValidatorsScreen(
chain: Chain,
source: ValidatorsSource,
selectedValidatorId: String,
viewModel: ValidatorsViewModel = hiltViewModel(),
onCancel: () -> Unit,
onSelect: (String) -> Unit
) {
DisposableEffect(chain) {

viewModel.init(chain)

DisposableEffect(source) {
viewModel.init(source)
onDispose { }
}

Expand All @@ -44,4 +42,4 @@ fun ValidatorsScreen(
)
ValidatorsUIState.Loading -> LoadingScene(stringResource(id = R.string.stake_validators), onCancel)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.gemwallet.android.features.transfer_amount.models

import com.wallet.core.primitives.AssetId
import com.wallet.core.primitives.Chain

sealed interface ValidatorsSource {
val chain: Chain

data class ChainValidators(override val chain: Chain) : ValidatorsSource

data class Rewards(
val assetId: AssetId,
val owner: String,
) : ValidatorsSource {
override val chain: Chain get() = assetId.chain
}
}
Loading