From e5b4550490886cbe1dd911b94af8d61616063d26 Mon Sep 17 00:00:00 2001 From: Jakub Porzuczek Date: Fri, 12 Jan 2024 14:47:59 +0100 Subject: [PATCH 1/5] pool redemption/contribution tx preview types --- .../extensions/StateEntityDetailsApiHelper.kt | 18 +- .../repository/cache/database/PoolEntity.kt | 39 +++- .../repository/cache/database/StateDao.kt | 19 +- .../cache/database/StateDaoExtensions.kt | 6 +- .../cache/database/StateDatabase.kt | 7 +- .../repository/cache/database/Wrappers.kt | 2 + .../repository/state/AccountsStateCache.kt | 3 +- .../data/repository/state/StateRepository.kt | 25 ++- .../android/domain/SampleDataProvider.kt | 106 +++++++++++ .../android/domain/model/Transferable.kt | 11 ++ .../android/domain/model/resources/Pool.kt | 4 +- .../usecases/assets/GetPoolDetailsUseCase.kt | 13 ++ .../assets/GetPoolUnitDetailsUseCase.kt | 4 +- .../status/assets/lsu/LSUAssetDialog.kt | 2 +- .../transaction/TransactionReviewScreen.kt | 15 +- .../transaction/TransactionReviewViewModel.kt | 59 ++++--- .../analysis/GeneralTransferAnalysis.kt | 8 +- .../analysis/PoolContributionAnalysis.kt | 83 +++++++++ .../analysis/PoolRedemptionAnalysis.kt | 82 +++++++++ .../transaction/analysis/StakeAnalysis.kt | 4 +- .../analysis/StakeClaimAnalysis.kt | 4 +- .../analysis/TransactionAnalysisDelegate.kt | 40 ++++- .../transaction/analysis/TransferAnalysis.kt | 2 +- .../transaction/analysis/UnstakeAnalysis.kt | 6 +- .../composables/CommonTransferContent.kt | 72 ++++++++ .../composables/PoolTypeContent.kt | 65 +++++++ .../transaction/composables/PoolsContent.kt | 166 ++++++++++++++++++ .../composables/StakeTypeContent.kt | 68 ++----- .../composables/TransactionAccountCard.kt | 128 +++++++++++++- .../composables/TransferTypeContent.kt | 59 ++----- .../composables/ValidatorsContent.kt | 4 +- .../TransactionGuaranteesDelegate.kt | 2 +- .../ui/composables/PoolDetailsItem.kt | 34 ++++ .../presentation/ui/composables/Thumbnail.kt | 18 ++ .../{resources => }/ValidatorDetailsItem.kt | 3 +- .../ui/composables/assets/AssetsView.kt | 10 +- .../usecases/SearchFeePayersUseCaseTest.kt | 2 +- .../login/DAppAuthorizedLoginViewModelTest.kt | 2 +- .../TransactionReviewViewModelTest.kt | 6 +- .../3.json | 12 +- .../res/drawable/ic_pools_contribution.xml | 13 ++ 41 files changed, 1029 insertions(+), 197 deletions(-) create mode 100644 app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/GetPoolDetailsUseCase.kt create mode 100644 app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/PoolContributionAnalysis.kt create mode 100644 app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/PoolRedemptionAnalysis.kt create mode 100644 app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/CommonTransferContent.kt create mode 100644 app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/PoolTypeContent.kt create mode 100644 app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/PoolsContent.kt create mode 100644 app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/PoolDetailsItem.kt rename app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/{resources => }/ValidatorDetailsItem.kt (88%) create mode 100644 designsystem/src/main/res/drawable/ic_pools_contribution.xml diff --git a/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/StateEntityDetailsApiHelper.kt b/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/StateEntityDetailsApiHelper.kt index 5eee6808b9..a4892b1c56 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/StateEntityDetailsApiHelper.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/StateEntityDetailsApiHelper.kt @@ -86,9 +86,10 @@ suspend fun StateApi.fetchAccountGatewayDetails( suspend fun StateApi.fetchPools( poolAddresses: Set, stateVersion: Long -): Map> { - if (poolAddresses.isEmpty()) return emptyMap() +): List { + if (poolAddresses.isEmpty()) return emptyList() + val poolDetails = mutableMapOf() val poolWithResources = mutableMapOf>() val resourceToPoolComponentAssociation = mutableMapOf() @@ -98,6 +99,7 @@ suspend fun StateApi.fetchPools( stateVersion = stateVersion, ) { poolComponents -> poolComponents.items.forEach { pool -> + poolDetails[pool.address] = pool val metadata = pool.explicitMetadata?.toMetadata().orEmpty() val associatedResource = metadata.poolUnit().orEmpty() resourceToPoolComponentAssociation[associatedResource] = pool.address @@ -105,7 +107,7 @@ suspend fun StateApi.fetchPools( } } - val result = mutableMapOf>() + val result = mutableListOf() paginateDetails( addresses = resourceToPoolComponentAssociation.keys, // Request details for resources metadataKeys = ExplicitMetadataKey.forAssets, @@ -113,13 +115,21 @@ suspend fun StateApi.fetchPools( ) { resourcesDetails -> resourcesDetails.items.forEach { resourceDetails -> val poolAddress = resourceToPoolComponentAssociation[resourceDetails.address] - result[resourceDetails] = poolWithResources[poolAddress].orEmpty() + poolDetails[poolAddress]?.let { poolDetails -> + result.add(FetchPoolsResult(poolDetails, resourceDetails, poolWithResources[poolAddress].orEmpty())) + } } } return result } +data class FetchPoolsResult( + val poolDetails: StateEntityDetailsResponseItem, + val poolUnitDetails: StateEntityDetailsResponseItem, + val poolResourcesDetails: List +) + suspend fun StateApi.fetchValidators( validatorsAddresses: Set, stateVersion: Long diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/PoolEntity.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/PoolEntity.kt index 53ae05a417..dfe84ef6a1 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/PoolEntity.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/PoolEntity.kt @@ -5,10 +5,12 @@ import androidx.room.Entity import androidx.room.ForeignKey import androidx.room.Index import androidx.room.PrimaryKey -import com.babylon.wallet.android.data.gateway.generated.models.FungibleResourcesCollectionItem +import com.babylon.wallet.android.data.gateway.extensions.FetchPoolsResult +import com.babylon.wallet.android.data.gateway.extensions.toMetadata import com.babylon.wallet.android.data.gateway.generated.models.StateEntityDetailsResponseItem import com.babylon.wallet.android.data.repository.cache.database.PoolResourceJoin.Companion.asPoolResourceJoin import com.babylon.wallet.android.data.repository.cache.database.ResourceEntity.Companion.asEntity +import com.babylon.wallet.android.domain.model.resources.metadata.poolUnit @Entity( foreignKeys = [ @@ -25,23 +27,42 @@ import com.babylon.wallet.android.data.repository.cache.database.ResourceEntity. data class PoolEntity( @PrimaryKey val address: String, + val metadata: MetadataColumn?, @ColumnInfo("resource_address") val resourceAddress: String ) { companion object { @Suppress("UnsafeCallOnNullableType") - fun Map>.asPoolsResourcesJoin( + fun List.asPoolsResourcesJoin( syncInfo: SyncInfo - ): Map>> = - map { (poolResource, itemsInPool) -> - val poolResourceEntity = poolResource.asEntity(syncInfo.synced) + ): List = + mapNotNull { fetchedPoolDetails -> + val poolResourceEntity = fetchedPoolDetails.poolUnitDetails.asEntity(syncInfo.synced) - val resourcesInPool = itemsInPool.map { fungibleItem -> + val resourcesInPool = fetchedPoolDetails.poolResourcesDetails.map { fungibleItem -> fungibleItem.asPoolResourceJoin(poolAddress = poolResourceEntity.poolAddress!!, syncInfo) } - - poolResourceEntity to resourcesInPool - }.toMap() + val poolEntity = fetchedPoolDetails.poolDetails.asPoolEntity() + poolEntity?.let { + PoolWithResourcesJoinResult(poolEntity, poolResourceEntity, resourcesInPool) + } + } } } + +fun StateEntityDetailsResponseItem.asPoolEntity(): PoolEntity? { + val metadata = this.metadata.toMetadata() + val poolUnitResourceAddress = metadata.poolUnit() ?: return null + return PoolEntity( + address = address, + metadata = MetadataColumn(metadata), + resourceAddress = poolUnitResourceAddress + ) +} + +data class PoolWithResourcesJoinResult( + val pool: PoolEntity, + val poolUnitResource: ResourceEntity, + val resources: List> +) diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/StateDao.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/StateDao.kt index 5323941337..a011a42449 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/StateDao.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/StateDao.kt @@ -53,18 +53,14 @@ interface StateDao { @Suppress("UnsafeCallOnNullableType") @Transaction - fun updatePools(pools: Map>>) { - val poolEntities = pools.keys.map { - PoolEntity( - address = it.poolAddress!!, - resourceAddress = it.address - ) - } - insertPoolDetails(poolEntities) + fun updatePools(pools: List) { + insertPoolDetails(pools.map { it.pool }) - val resourcesInvolved = pools.map { entry -> listOf(entry.key) + entry.value.map { it.second } }.flatten() + val resourcesInvolved = pools.map { pool -> + listOf(pool.poolUnitResource) + pool.resources.map { it.second } + }.flatten() insertOrReplaceResources(resourcesInvolved) - val join = pools.values.map { poolResource -> poolResource.map { it.first } }.flatten() + val join = pools.map { poolResource -> poolResource.resources.map { it.first } }.flatten() insertPoolResources(join) } @@ -128,7 +124,8 @@ interface StateDao { """ SELECT PoolEntity.address AS pool_entity_address, - PoolEntity.resource_address AS pool_unit_address, + PoolEntity.resource_address AS pool_unit_address, + PoolEntity.metadata AS pool_metadata, PoolResourceJoin.state_version AS account_state_version, PoolResourceJoin.amount AS amount, ResourceEntity.* diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/StateDaoExtensions.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/StateDaoExtensions.kt index 76eca9f771..f669b36c37 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/StateDaoExtensions.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/StateDaoExtensions.kt @@ -27,7 +27,11 @@ fun StateDao.getCachedPools(poolAddresses: Set, atStateVersion: Long): M val pool = pools[poolResource.poolAddress] pools[poolResource.poolAddress!!] = pool?.copy( resources = pool.resources.toMutableList().apply { add(resource) } - ) ?: Pool(address = join.address, poolUnitAddress = join.poolUnitAddress, resources = listOf(resource)) + ) ?: Pool( + address = join.address, + resources = listOf(resource), + metadata = join.poolMetadata?.metadata.orEmpty(), + ) } return pools } diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/StateDatabase.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/StateDatabase.kt index f8b7d889e2..fe329b6715 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/StateDatabase.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/StateDatabase.kt @@ -18,7 +18,7 @@ import androidx.room.TypeConverters PoolResourceJoin::class, DAppEntity::class ], - version = StateDatabase.VERSION_3 + version = StateDatabase.VERSION_4 ) @TypeConverters(StateDatabaseConverters::class) abstract class StateDatabase : RoomDatabase() { @@ -32,9 +32,12 @@ abstract class StateDatabase : RoomDatabase() { @Deprecated("Updated metadata schema") const val VERSION_2 = 2 - // Add DAppEntity to schema + @Deprecated("Add DAppEntity to schema") const val VERSION_3 = 3 + // Add PoolEntity.metadata to schema + const val VERSION_4 = 4 + private const val NAME = "STATE_DATABASE" fun factory(applicationContext: Context): StateDatabase = Room diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/Wrappers.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/Wrappers.kt index 9c8c4ca9df..482a53ecaa 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/Wrappers.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/Wrappers.kt @@ -69,6 +69,8 @@ data class PoolWithResourceResponse( val poolUnitAddress: String, @ColumnInfo("account_state_version") val accountStateVersion: Long?, + @ColumnInfo("pool_metadata") + val poolMetadata: MetadataColumn?, val amount: BigDecimal?, // From ResourceEntity (@Embed does not work here since making ResourceEntity nullable does not work) diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/state/AccountsStateCache.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/state/AccountsStateCache.kt index f0d0ff8316..f13652a8b1 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/state/AccountsStateCache.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/state/AccountsStateCache.kt @@ -29,6 +29,7 @@ import com.babylon.wallet.android.domain.model.resources.Pool import com.babylon.wallet.android.domain.model.resources.Resource import com.babylon.wallet.android.domain.model.resources.XrdResource import com.babylon.wallet.android.domain.model.resources.metadata.AccountType +import com.babylon.wallet.android.domain.model.resources.metadata.poolUnit import com.babylon.wallet.android.utils.truncatedHash import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope @@ -328,7 +329,7 @@ class AccountsStateCache @Inject constructor( val pool = pools[fungible.poolAddress]?.takeIf { pool -> // The fungible claims that it is part of the poolAddress. // We need to check if pool points back to this resource - pool.poolUnitAddress == fungible.resourceAddress + pool.metadata.poolUnit() == fungible.resourceAddress } if (pool != null) { resultingPoolUnits.add( diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/state/StateRepository.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/state/StateRepository.kt index ae51af304d..d831a20069 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/state/StateRepository.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/state/StateRepository.kt @@ -1,6 +1,7 @@ package com.babylon.wallet.android.data.repository.state import com.babylon.wallet.android.data.gateway.apis.StateApi +import com.babylon.wallet.android.data.gateway.extensions.fetchPools import com.babylon.wallet.android.data.gateway.extensions.fetchValidators import com.babylon.wallet.android.data.gateway.extensions.getNextNftItems import com.babylon.wallet.android.data.gateway.extensions.paginateDetails @@ -10,6 +11,7 @@ import com.babylon.wallet.android.data.gateway.model.ExplicitMetadataKey import com.babylon.wallet.android.data.repository.cache.database.DAppEntity import com.babylon.wallet.android.data.repository.cache.database.MetadataColumn import com.babylon.wallet.android.data.repository.cache.database.NFTEntity.Companion.asEntity +import com.babylon.wallet.android.data.repository.cache.database.PoolEntity.Companion.asPoolsResourcesJoin import com.babylon.wallet.android.data.repository.cache.database.ResourceEntity import com.babylon.wallet.android.data.repository.cache.database.ResourceEntity.Companion.asEntity import com.babylon.wallet.android.data.repository.cache.database.StateDao @@ -52,7 +54,7 @@ interface StateRepository { suspend fun getResources(addresses: Set, underAccountAddress: String?, withDetails: Boolean): Result> - suspend fun getPool(poolAddress: String): Result + suspend fun getPools(poolAddresses: Set): Result> suspend fun getValidator(validatorAddress: String): Result @@ -285,13 +287,26 @@ class StateRepositoryImpl @Inject constructor( } } - override suspend fun getPool(poolAddress: String): Result = withContext(dispatcher) { + override suspend fun getPools(poolAddresses: Set): Result> = withContext(dispatcher) { runCatching { val stateVersion = stateDao.getLatestStateVersion() ?: error("No cached state version found") - stateDao.getCachedPools( - poolAddresses = setOf(poolAddress), + var cachedPools = stateDao.getCachedPools( + poolAddresses = poolAddresses, atStateVersion = stateVersion - )[poolAddress] ?: error("Pool $poolAddress does not exist") + ).values.toList() + val unknownPools = poolAddresses - cachedPools.map { it.address }.toSet() + if (unknownPools.isNotEmpty()) { + val newPools = stateApi.fetchPools(unknownPools, stateVersion) + if (newPools.isNotEmpty()) { + val join = newPools.asPoolsResourcesJoin(SyncInfo(InstantGenerator(), stateVersion)) + stateDao.updatePools(pools = join) + cachedPools = stateDao.getCachedPools( + poolAddresses = poolAddresses, + atStateVersion = stateVersion + ).values.toList() + } + } + cachedPools } } diff --git a/app/src/main/java/com/babylon/wallet/android/domain/SampleDataProvider.kt b/app/src/main/java/com/babylon/wallet/android/domain/SampleDataProvider.kt index 4ada5478ef..8ca43ee9ef 100644 --- a/app/src/main/java/com/babylon/wallet/android/domain/SampleDataProvider.kt +++ b/app/src/main/java/com/babylon/wallet/android/domain/SampleDataProvider.kt @@ -12,7 +12,9 @@ import com.babylon.wallet.android.domain.model.Transferable import com.babylon.wallet.android.domain.model.TransferableResource import com.babylon.wallet.android.domain.model.assets.AccountWithAssets import com.babylon.wallet.android.domain.model.assets.Assets +import com.babylon.wallet.android.domain.model.assets.PoolUnit import com.babylon.wallet.android.domain.model.assets.ValidatorDetail +import com.babylon.wallet.android.domain.model.resources.Pool import com.babylon.wallet.android.domain.model.resources.Resource import com.babylon.wallet.android.domain.model.resources.XrdResource import com.babylon.wallet.android.domain.model.resources.metadata.Metadata @@ -132,6 +134,73 @@ class SampleDataProvider { ) ) + val transferableDepositingPool = Transferable.Depositing( + transferable = TransferableResource.Pool( + pool = PoolUnit( + Resource.FungibleResource( + resourceAddress = "resource_tdx_e_1tkawacgvcw7z9xztccgjrged25c7nqtnd4nllh750s2ny64m0cltmg", + ownedAmount = null, + currentSupply = BigDecimal("69696969696969.666999666999666999"), + metadata = listOf( + Metadata.Primitive(key = ExplicitMetadataKey.NAME.key, value = "XXX", valueType = MetadataType.String), + Metadata.Primitive(key = ExplicitMetadataKey.SYMBOL.key, value = "XXX", valueType = MetadataType.String), + Metadata.Primitive( + key = ExplicitMetadataKey.DESCRIPTION.key, + value = "a very xxx token", + valueType = MetadataType.String + ) + ) + ), + pool = Pool( + address = "pool_tdx_19jd32jd3928jd3892jd329", + metadata = listOf( + Metadata.Primitive(key = ExplicitMetadataKey.NAME.key, value = "My Pool", valueType = MetadataType.String), + Metadata.Primitive(key = ExplicitMetadataKey.ICON_URL.key, value = "XXX", valueType = MetadataType.Url), + Metadata.Primitive( + key = ExplicitMetadataKey.POOL_UNIT.key, + value = "resource_tdx_19jd32jd3928jd3892jd329", + valueType = MetadataType.Address + ) + ), + resources = listOf( + Resource.FungibleResource( + resourceAddress = "resource_tdx_e_1tkawacgvcw7z9xztccgjrged25c7nqtnd4nllh750s2ny64m0clt12", + ownedAmount = null, + currentSupply = BigDecimal("69696969696969.666999666999666999"), + metadata = listOf( + Metadata.Primitive(key = ExplicitMetadataKey.NAME.key, value = "XXX", valueType = MetadataType.String), + Metadata.Primitive(key = ExplicitMetadataKey.SYMBOL.key, value = "XXX", valueType = MetadataType.String), + Metadata.Primitive( + key = ExplicitMetadataKey.DESCRIPTION.key, + value = "pool 1 token", + valueType = MetadataType.String + ) + ) + ), + Resource.FungibleResource( + resourceAddress = "resource_tdx_e_1tkawacgvcw7z9xztccgjrged25c7nqtnd4nllh750s2ny64m0clt21", + ownedAmount = null, + currentSupply = BigDecimal("69696969696969.666999666999666999"), + metadata = listOf( + Metadata.Primitive(key = ExplicitMetadataKey.NAME.key, value = "XXX", valueType = MetadataType.String), + Metadata.Primitive(key = ExplicitMetadataKey.SYMBOL.key, value = "XXX", valueType = MetadataType.String), + Metadata.Primitive( + key = ExplicitMetadataKey.DESCRIPTION.key, + value = "pool 2 token", + valueType = MetadataType.String + ) + ) + ) + ) + ), + ), + contributionPerResource = mapOf( + "resource_tdx_e_1tkawacgvcw7z9xztccgjrged25c7nqtnd4nllh750s2ny64m0clt12" to BigDecimal(100), + "resource_tdx_e_1tkawacgvcw7z9xztccgjrged25c7nqtnd4nllh750s2ny64m0clt21" to BigDecimal(200) + ) + ) + ) + val accountWithTransferableResourcesOwned = AccountWithTransferableResources.Owned( account = Network.Account( address = "account_tdx_e_12yeuyl924ml5v9qks4s3cegpm6gl355r96cd9d5z99qtlxvwq7y3sz", @@ -170,6 +239,43 @@ class SampleDataProvider { ) val accountWithTransferableResourceLsu = AccountWithTransferableResources.Owned( + account = Network.Account( + address = "account_tdx_e_12yeuyl924ml5v9qks4s3cegpm6gl355r96cd9d5z99qtlxvwq7y3sz", + appearanceID = 0, + displayName = "666", + networkID = 14, + securityState = SecurityState.Unsecured( + unsecuredEntityControl = SecurityState.UnsecuredEntityControl( + transactionSigning = FactorInstance( + badge = FactorInstance.Badge.VirtualSource.HierarchicalDeterministic( + derivationPath = DerivationPath.forAccount( + networkId = Radix.Gateway.default.network.networkId(), + accountIndex = 0, + keyType = KeyType.TRANSACTION_SIGNING + ), + publicKey = FactorInstance.PublicKey.curve25519PublicKey( + "c294ecdd8752e2197ad0027fe4557d464362df12b587537234f0b106237462f5" + ) + ), + factorSourceId = FactorSource.FactorSourceID.FromHash( + kind = FactorSourceKind.DEVICE, + body = HexCoded32Bytes("ba6a7bd3e91b2a83e21f05c22eaddecd12e75ab01c492e9d4e62d6445600c142") + ) + ) + ) + ), + onLedgerSettings = Network.Account.OnLedgerSettings( + thirdPartyDeposits = Network.Account.OnLedgerSettings.ThirdPartyDeposits( + depositRule = Network.Account.OnLedgerSettings.ThirdPartyDeposits.DepositRule.AcceptAll, + assetsExceptionList = emptyList(), + depositorsAllowList = emptyList() + ) + ) + ), + resources = listOf(transferableDepositingLsu) + ) + + val accountWithTransferablePool = AccountWithTransferableResources.Owned( account = Network.Account( address = "account_tdx_e_12yeuyl924ml5v9qks4s3cegpm6gl355r96cd9d5z99qtlxvwq7y3sz", appearanceID = 0, diff --git a/app/src/main/java/com/babylon/wallet/android/domain/model/Transferable.kt b/app/src/main/java/com/babylon/wallet/android/domain/model/Transferable.kt index 60677da696..b038598ea4 100644 --- a/app/src/main/java/com/babylon/wallet/android/domain/model/Transferable.kt +++ b/app/src/main/java/com/babylon/wallet/android/domain/model/Transferable.kt @@ -1,6 +1,7 @@ package com.babylon.wallet.android.domain.model import androidx.annotation.FloatRange +import com.babylon.wallet.android.domain.model.assets.PoolUnit import com.babylon.wallet.android.domain.model.assets.ValidatorDetail import com.babylon.wallet.android.domain.model.resources.Resource import java.math.BigDecimal @@ -33,6 +34,7 @@ sealed interface Transferable { is TransferableResource.LsuAmount -> null is TransferableResource.StakeClaimNft -> null + is TransferableResource.Pool -> null } } @@ -124,4 +126,13 @@ sealed interface TransferableResource { val validatorDetail: ValidatorDetail, override val isNewlyCreated: Boolean = false ) : TransferableResource + + data class Pool( + val pool: PoolUnit, + val contributionPerResource: Map, + override val isNewlyCreated: Boolean = false, + ) : TransferableResource { + override val resource: Resource + get() = pool.stake + } } diff --git a/app/src/main/java/com/babylon/wallet/android/domain/model/resources/Pool.kt b/app/src/main/java/com/babylon/wallet/android/domain/model/resources/Pool.kt index 53e008c9fb..1909babe7d 100644 --- a/app/src/main/java/com/babylon/wallet/android/domain/model/resources/Pool.kt +++ b/app/src/main/java/com/babylon/wallet/android/domain/model/resources/Pool.kt @@ -1,7 +1,9 @@ package com.babylon.wallet.android.domain.model.resources +import com.babylon.wallet.android.domain.model.resources.metadata.Metadata + data class Pool( val address: String, - val poolUnitAddress: String, + val metadata: List, val resources: List ) diff --git a/app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/GetPoolDetailsUseCase.kt b/app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/GetPoolDetailsUseCase.kt new file mode 100644 index 0000000000..a6bc5b3ad8 --- /dev/null +++ b/app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/GetPoolDetailsUseCase.kt @@ -0,0 +1,13 @@ +package com.babylon.wallet.android.domain.usecases.assets + +import com.babylon.wallet.android.data.repository.state.StateRepository +import com.babylon.wallet.android.domain.model.resources.Pool +import javax.inject.Inject + +class GetPoolDetailsUseCase @Inject constructor( + private val stateRepository: StateRepository +) { + + suspend operator fun invoke(poolAddresses: Set): Result> = + stateRepository.getPools(poolAddresses) +} diff --git a/app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/GetPoolUnitDetailsUseCase.kt b/app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/GetPoolUnitDetailsUseCase.kt index 0591311042..b2c535338f 100644 --- a/app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/GetPoolUnitDetailsUseCase.kt +++ b/app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/GetPoolUnitDetailsUseCase.kt @@ -23,10 +23,10 @@ class GetPoolUnitDetailsUseCase @Inject constructor( val poolAddress = poolResource.poolAddress ?: return@then runCatching { error("Resource $resourceAddress is not associated with a pool") } - stateRepository.getPool(poolAddress).map { + stateRepository.getPools(setOf(poolAddress)).map { PoolUnit( stake = poolResource, - pool = it + pool = it.first() ) } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUAssetDialog.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUAssetDialog.kt index b5334bd3a2..66661dda83 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUAssetDialog.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUAssetDialog.kt @@ -42,6 +42,7 @@ import com.babylon.wallet.android.presentation.account.composable.AssetMetadataR import com.babylon.wallet.android.presentation.ui.composables.BottomSheetDialogWrapper import com.babylon.wallet.android.presentation.ui.composables.SnackbarUiMessageHandler import com.babylon.wallet.android.presentation.ui.composables.Thumbnail +import com.babylon.wallet.android.presentation.ui.composables.ValidatorDetailsItem import com.babylon.wallet.android.presentation.ui.composables.assets.Behaviour import com.babylon.wallet.android.presentation.ui.composables.assets.Tag import com.babylon.wallet.android.presentation.ui.composables.assets.assetOutlineBorder @@ -49,7 +50,6 @@ import com.babylon.wallet.android.presentation.ui.composables.icon import com.babylon.wallet.android.presentation.ui.composables.name import com.babylon.wallet.android.presentation.ui.composables.resources.AddressRow import com.babylon.wallet.android.presentation.ui.composables.resources.TokenBalance -import com.babylon.wallet.android.presentation.ui.composables.resources.ValidatorDetailsItem import com.babylon.wallet.android.presentation.ui.modifier.radixPlaceholder import rdx.works.core.displayableQuantity import java.math.BigDecimal diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewScreen.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewScreen.kt index e72df16c4f..e9fc10ca93 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewScreen.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewScreen.kt @@ -47,6 +47,7 @@ import com.babylon.wallet.android.presentation.transaction.composables.AccountDe import com.babylon.wallet.android.presentation.transaction.composables.FeesSheet import com.babylon.wallet.android.presentation.transaction.composables.GuaranteesSheet import com.babylon.wallet.android.presentation.transaction.composables.NetworkFeeContent +import com.babylon.wallet.android.presentation.transaction.composables.PoolTypeContent import com.babylon.wallet.android.presentation.transaction.composables.PresentingProofsContent import com.babylon.wallet.android.presentation.transaction.composables.RawManifestView import com.babylon.wallet.android.presentation.transaction.composables.StakeTypeContent @@ -284,7 +285,7 @@ private fun TransactionPreviewContent( } is PreviewType.NonConforming -> {} - is PreviewType.Transfer -> { + is PreviewType.Transfer.GeneralTransfer -> { TransferTypeContent( modifier = Modifier.background(RadixTheme.colors.gray5), state = state, @@ -308,7 +309,7 @@ private fun TransactionPreviewContent( ReceiptEdge(modifier = Modifier.fillMaxWidth(), color = RadixTheme.colors.gray5) } - is PreviewType.Staking -> { + is PreviewType.Transfer.Staking -> { StakeTypeContent( modifier = Modifier.background(RadixTheme.colors.gray5), state = state, @@ -318,6 +319,16 @@ private fun TransactionPreviewContent( ) ReceiptEdge(modifier = Modifier.fillMaxWidth(), color = RadixTheme.colors.gray5) } + + is PreviewType.Transfer.Pool -> { + PoolTypeContent( + modifier = Modifier.background(RadixTheme.colors.gray5), + state = state, + onFungibleResourceClick = onFungibleResourceClick, + previewType = preview + ) + ReceiptEdge(modifier = Modifier.fillMaxWidth(), color = RadixTheme.colors.gray5) + } } NetworkFeeContent( fees = state.transactionFees, diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModel.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModel.kt index 1c7ae882b8..3b01adadba 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModel.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModel.kt @@ -326,7 +326,7 @@ class TransactionReviewViewModel @Inject constructor( ) val isRawManifestToggleVisible: Boolean - get() = previewType is PreviewType.Transfer + get() = true // previewType is PreviewType.Transfer val rawManifest: String = request ?.transactionManifestData @@ -365,7 +365,7 @@ class TransactionReviewViewModel @Inject constructor( // In cases were it is not a transfer type, then it means the user // will not spend any other XRD rather than the ones spent for the fees val xrdUsed = when (previewType) { - is PreviewType.Transfer -> { + is PreviewType.Transfer.GeneralTransfer -> { val candidateAddressWithdrawn = previewType.from.find { it.address == candidateAddress } if (candidateAddressWithdrawn != null) { val xrdResourceWithdrawn = candidateAddressWithdrawn.resources.map { @@ -382,7 +382,8 @@ class TransactionReviewViewModel @Inject constructor( is PreviewType.NonConforming -> BigDecimal.ZERO is PreviewType.None -> BigDecimal.ZERO is PreviewType.UnacceptableManifest -> BigDecimal.ZERO - is PreviewType.Staking -> BigDecimal.ZERO + is PreviewType.Transfer.Pool -> BigDecimal.ZERO + is PreviewType.Transfer.Staking -> BigDecimal.ZERO } return xrdInCandidateAccount - xrdUsed < transactionFees.transactionFeeToLock @@ -463,26 +464,42 @@ sealed interface PreviewType { val accountsWithDepositSettingsChanges: List = emptyList() ) : PreviewType - data class Transfer( - val from: List, - val to: List, - val badges: List = emptyList(), - val dApps: List> = emptyList() - ) : PreviewType { + sealed interface Transfer : PreviewType { + val from: List + val to: List + + data class Staking( + override val from: List, + override val to: List, + val validators: List, + val actionType: ActionType + ) : Transfer { + enum class ActionType { + Stake, Unstake, ClaimStake + } + } - fun getNewlyCreatedResources() = (from + to).map { allTransfers -> - allTransfers.resources.filter { it.transferable.isNewlyCreated }.map { it.transferable } - }.flatten() - } + data class Pool( + override val from: List, + override val to: List, + val pools: List, + val actionType: ActionType + ) : Transfer { + enum class ActionType { + Contribution, Redemption + } + } + + data class GeneralTransfer( + override val from: List, + override val to: List, + val badges: List = emptyList(), + val dApps: List> = emptyList() + ) : Transfer { - data class Staking( - val from: List, - val to: List, - val validators: List, - val actionType: ActionType - ) : PreviewType { - enum class ActionType { - Stake, Unstake, ClaimStake + fun getNewlyCreatedResources() = (from + to).map { allTransfers -> + allTransfers.resources.filter { it.transferable.isNewlyCreated }.map { it.transferable } + }.flatten() } } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/GeneralTransferAnalysis.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/GeneralTransferAnalysis.kt index 756a17aae6..dd28f91e2f 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/GeneralTransferAnalysis.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/GeneralTransferAnalysis.kt @@ -16,7 +16,7 @@ import rdx.works.profile.domain.accountsOnCurrentNetwork import rdx.works.profile.domain.defaultDepositGuarantee // Generic transaction resolver -suspend fun ExecutionSummary.resolveGeneralTransfer( +suspend fun ExecutionSummary.resolveGeneralTransaction( resources: List, getTransactionBadgesUseCase: GetTransactionBadgesUseCase, getProfileUseCase: GetProfileUseCase, @@ -26,14 +26,14 @@ suspend fun ExecutionSummary.resolveGeneralTransfer( val dApps = resolveDApps(resolveDAppInTransactionUseCase).distinctBy { it.first.definitionAddresses } - + val involvedAccountAddresses = accountWithdraws.keys + accountDeposits.keys val allAccounts = getProfileUseCase.accountsOnCurrentNetwork().filter { - it.address in accountWithdraws.keys || it.address in accountDeposits.keys + it.address in involvedAccountAddresses } val defaultDepositGuarantee = getProfileUseCase.defaultDepositGuarantee() - return PreviewType.Transfer( + return PreviewType.Transfer.GeneralTransfer( from = resolveFromAccounts(resources, allAccounts), to = resolveToAccounts(resources, allAccounts, defaultDepositGuarantee), badges = badges, diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/PoolContributionAnalysis.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/PoolContributionAnalysis.kt new file mode 100644 index 0000000000..7374c93821 --- /dev/null +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/PoolContributionAnalysis.kt @@ -0,0 +1,83 @@ +package com.babylon.wallet.android.presentation.transaction.analysis + +import com.babylon.wallet.android.domain.model.Transferable +import com.babylon.wallet.android.domain.model.TransferableResource +import com.babylon.wallet.android.domain.model.assets.PoolUnit +import com.babylon.wallet.android.domain.model.resources.Pool +import com.babylon.wallet.android.domain.model.resources.Resource +import com.babylon.wallet.android.domain.model.resources.metadata.poolUnit +import com.babylon.wallet.android.presentation.transaction.AccountWithTransferableResources +import com.babylon.wallet.android.presentation.transaction.PreviewType +import com.radixdlt.ret.DetailedManifestClass +import com.radixdlt.ret.ExecutionSummary +import rdx.works.profile.data.model.pernetwork.Network +import rdx.works.profile.domain.GetProfileUseCase +import rdx.works.profile.domain.accountOnCurrentNetwork +import rdx.works.profile.domain.accountsOnCurrentNetwork + +suspend fun DetailedManifestClass.PoolContribution.resolve( + executionSummary: ExecutionSummary, + getProfileUseCase: GetProfileUseCase, + resources: List, + involvedPools: List +): PreviewType { + val accountsWithdrawnFrom = executionSummary.accountWithdraws.keys + val ownedAccountsWithdrawnFrom = getProfileUseCase.accountsOnCurrentNetwork().filter { + accountsWithdrawnFrom.contains(it.address) + } + val from = executionSummary.extractWithdraws(ownedAccountsWithdrawnFrom, resources) + val to = executionSummary.accountDeposits.map { depositsPerAddress -> + val ownedAccount = getProfileUseCase.accountOnCurrentNetwork(depositsPerAddress.key) ?: error("No account found") + val deposits = depositsPerAddress.value.map { deposit -> + val resourceAddress = deposit.resourceAddress + val contribution = poolContributions.find { it.poolUnitsResourceAddress.addressString() == resourceAddress } + ?: error("No contribution found") + val pool = involvedPools.find { it.address == contribution.poolAddress.addressString() } + ?: error("No pool found") + val poolResource = resources.find { it.resourceAddress == pool.metadata.poolUnit() } as? Resource.FungibleResource + ?: error("No pool resource found") + val contributedResourceAddresses = contribution.contributedResources.keys + Transferable.Depositing( + transferable = TransferableResource.Pool( + PoolUnit( + stake = poolResource, + pool = pool + ), + contributedResourceAddresses.associateWith { contributedResourceAddress -> + val contributionValue = contribution.contributedResources[contributedResourceAddress] + ?: error("No contribution value found") + contributionValue.asStr().toBigDecimal() + }, + ) + ) + } + AccountWithTransferableResources.Owned( + account = ownedAccount, + resources = deposits + ) + } + return PreviewType.Transfer.Pool( + from = from, + to = to, + pools = involvedPools, + actionType = PreviewType.Transfer.Pool.ActionType.Contribution + ) +} + +private fun ExecutionSummary.extractWithdraws(allOwnedAccounts: List, resources: List) = + accountWithdraws.entries.map { transferEntry -> + val accountOnNetwork = allOwnedAccounts.find { it.address == transferEntry.key } + + val withdrawing = transferEntry.value.map { resourceIndicator -> + Transferable.Withdrawing(resourceIndicator.toTransferableResource(resources)) + } + accountOnNetwork?.let { account -> + AccountWithTransferableResources.Owned( + account = account, + resources = withdrawing + ) + } ?: AccountWithTransferableResources.Other( + address = transferEntry.key, + resources = withdrawing + ) + } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/PoolRedemptionAnalysis.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/PoolRedemptionAnalysis.kt new file mode 100644 index 0000000000..e260891443 --- /dev/null +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/PoolRedemptionAnalysis.kt @@ -0,0 +1,82 @@ +package com.babylon.wallet.android.presentation.transaction.analysis + +import com.babylon.wallet.android.domain.model.Transferable +import com.babylon.wallet.android.domain.model.TransferableResource +import com.babylon.wallet.android.domain.model.assets.PoolUnit +import com.babylon.wallet.android.domain.model.resources.Pool +import com.babylon.wallet.android.domain.model.resources.Resource +import com.babylon.wallet.android.domain.model.resources.metadata.poolUnit +import com.babylon.wallet.android.presentation.transaction.AccountWithTransferableResources +import com.babylon.wallet.android.presentation.transaction.PreviewType +import com.radixdlt.ret.DetailedManifestClass +import com.radixdlt.ret.ExecutionSummary +import rdx.works.profile.data.model.pernetwork.Network +import rdx.works.profile.domain.GetProfileUseCase +import rdx.works.profile.domain.accountOnCurrentNetwork +import rdx.works.profile.domain.accountsOnCurrentNetwork + +suspend fun DetailedManifestClass.PoolRedemption.resolve( + executionSummary: ExecutionSummary, + getProfileUseCase: GetProfileUseCase, + resources: List, + involvedPools: List +): PreviewType { + val accountsWithdrawnFrom = executionSummary.accountDeposits.keys + val ownedAccountsWithdrawnFrom = getProfileUseCase.accountsOnCurrentNetwork().filter { + accountsWithdrawnFrom.contains(it.address) + } + val to = executionSummary.extractDeposits(ownedAccountsWithdrawnFrom, resources) + val from = executionSummary.accountWithdraws.map { withdrawsPerAddress -> + val ownedAccount = getProfileUseCase.accountOnCurrentNetwork(withdrawsPerAddress.key) ?: error("No account found") + val deposits = withdrawsPerAddress.value.map { withdraw -> + val resourceAddress = withdraw.resourceAddress + val redemption = poolRedemptions.find { it.poolUnitsResourceAddress.addressString() == resourceAddress } + ?: error("No redemption found") + val pool = involvedPools.find { it.address == redemption.poolAddress.addressString() } + ?: error("No pool found") + val poolResource = resources.find { it.resourceAddress == pool.metadata.poolUnit() } as? Resource.FungibleResource + ?: error("No pool resource found") + val redemptionResourceAddresses = redemption.redeemedResources.keys + Transferable.Withdrawing( + transferable = TransferableResource.Pool( + PoolUnit( + stake = poolResource, + pool = pool + ), + redemptionResourceAddresses.associateWith { contributedResourceAddress -> + val redemptionValue = redemption.redeemedResources[contributedResourceAddress] ?: error("No redemption value found") + redemptionValue.asStr().toBigDecimal() + }, + ) + ) + } + AccountWithTransferableResources.Owned( + account = ownedAccount, + resources = deposits + ) + } + return PreviewType.Transfer.Pool( + from = from, + to = to, + pools = involvedPools, + actionType = PreviewType.Transfer.Pool.ActionType.Redemption + ) +} + +private fun ExecutionSummary.extractDeposits(allOwnedAccounts: List, resources: List) = + accountDeposits.entries.map { transferEntry -> + val accountOnNetwork = allOwnedAccounts.find { it.address == transferEntry.key } + + val withdrawing = transferEntry.value.map { resourceIndicator -> + Transferable.Depositing(resourceIndicator.toTransferableResource(resources)) + } + accountOnNetwork?.let { account -> + AccountWithTransferableResources.Owned( + account = account, + resources = withdrawing + ) + } ?: AccountWithTransferableResources.Other( + address = transferEntry.key, + resources = withdrawing + ) + } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/StakeAnalysis.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/StakeAnalysis.kt index a0ef3d5a06..f2259eb5d7 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/StakeAnalysis.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/StakeAnalysis.kt @@ -26,11 +26,11 @@ suspend fun DetailedManifestClass.ValidatorStake.resolve( resources = resources, involvedValidators = involvedValidators ) - return PreviewType.Staking( + return PreviewType.Transfer.Staking( from = fromAccounts, to = toAccounts, validators = involvedValidators, - actionType = PreviewType.Staking.ActionType.Stake + actionType = PreviewType.Transfer.Staking.ActionType.Stake ) } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/StakeClaimAnalysis.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/StakeClaimAnalysis.kt index 1e6029938b..2d246d105e 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/StakeClaimAnalysis.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/StakeClaimAnalysis.kt @@ -29,11 +29,11 @@ suspend fun DetailedManifestClass.ValidatorClaim.resolve( involvedValidators = involvedValidators, stakeClaimsNfts = stakeClaimsNfts ) - return PreviewType.Staking( + return PreviewType.Transfer.Staking( validators = involvedValidators, from = fromAccounts, to = toAccounts, - actionType = PreviewType.Staking.ActionType.ClaimStake + actionType = PreviewType.Transfer.Staking.ActionType.ClaimStake ) } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/TransactionAnalysisDelegate.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/TransactionAnalysisDelegate.kt index d945d04075..504bc00eb6 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/TransactionAnalysisDelegate.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/TransactionAnalysisDelegate.kt @@ -1,5 +1,6 @@ package com.babylon.wallet.android.presentation.transaction.analysis +import com.babylon.wallet.android.data.manifest.toPrettyString import com.babylon.wallet.android.data.transaction.NotaryAndSigners import com.babylon.wallet.android.data.transaction.TransactionClient import com.babylon.wallet.android.domain.RadixWalletException @@ -11,6 +12,7 @@ import com.babylon.wallet.android.domain.usecases.ResolveNotaryAndSignersUseCase import com.babylon.wallet.android.domain.usecases.SearchFeePayersUseCase import com.babylon.wallet.android.domain.usecases.assets.CacheNewlyCreatedEntitiesUseCase import com.babylon.wallet.android.domain.usecases.assets.GetNFTDetailsUseCase +import com.babylon.wallet.android.domain.usecases.assets.GetPoolDetailsUseCase import com.babylon.wallet.android.domain.usecases.transaction.GetTransactionBadgesUseCase import com.babylon.wallet.android.presentation.common.ViewModelDelegate import com.babylon.wallet.android.presentation.transaction.PreviewType @@ -41,6 +43,8 @@ class TransactionAnalysisDelegate @Inject constructor( private val getTransactionBadgesUseCase: GetTransactionBadgesUseCase, private val getNFTDetailsUseCase: GetNFTDetailsUseCase, private val resolveDAppInTransactionUseCase: ResolveDAppInTransactionUseCase, + private val searchFeePayersUseCase: SearchFeePayersUseCase, + private val getPoolDetailsUseCase: GetPoolDetailsUseCase private val resolveNotaryAndSignersUseCase: ResolveNotaryAndSignersUseCase, private val searchFeePayersUseCase: SearchFeePayersUseCase ) : ViewModelDelegate() { @@ -113,7 +117,7 @@ class TransactionAnalysisDelegate @Inject constructor( processConformingManifest() } - if (previewType is PreviewType.Transfer) { + if (previewType is PreviewType.Transfer.GeneralTransfer) { val newlyCreated = previewType.getNewlyCreatedResources() if (newlyCreated.isNotEmpty()) { cacheNewlyCreatedEntitiesUseCase(newlyCreated.map { it.resource }) @@ -149,6 +153,7 @@ class TransactionAnalysisDelegate @Inject constructor( } } + @Suppress("LongMethod") private suspend fun ExecutionSummary.processConformingManifest(): PreviewType { val networkId = requireNotNull(getProfileUseCase.currentNetwork()?.knownNetworkId) val xrdAddress = XrdResource.address(networkId) @@ -156,12 +161,14 @@ class TransactionAnalysisDelegate @Inject constructor( val resources = getResourcesUseCase(addresses = involvedResourceAddresses + xrdAddress).getOrThrow() return when (transactionType) { - is DetailedManifestClass.General -> resolveGeneralTransfer( - resources = resources, - getTransactionBadgesUseCase = getTransactionBadgesUseCase, - getProfileUseCase = getProfileUseCase, - resolveDAppInTransactionUseCase = resolveDAppInTransactionUseCase - ) + is DetailedManifestClass.General -> { + resolveGeneralTransaction( + resources = resources, + getTransactionBadgesUseCase = getTransactionBadgesUseCase, + getProfileUseCase = getProfileUseCase, + resolveDAppInTransactionUseCase = resolveDAppInTransactionUseCase + ) + } is DetailedManifestClass.AccountDepositSettingsUpdate -> transactionType.resolve( getProfileUseCase = getProfileUseCase, @@ -203,6 +210,25 @@ class TransactionAnalysisDelegate @Inject constructor( ) } + is DetailedManifestClass.PoolContribution -> { + val pools = getPoolDetailsUseCase(transactionType.poolAddresses.map { it.addressString() }.toSet()).getOrThrow() + transactionType.resolve( + getProfileUseCase = getProfileUseCase, + resources = resources, + involvedPools = pools, + executionSummary = this + ) + } + is DetailedManifestClass.PoolRedemption -> { + val pools = getPoolDetailsUseCase(transactionType.poolAddresses.map { it.addressString() }.toSet()).getOrThrow() + transactionType.resolve( + getProfileUseCase = getProfileUseCase, + resources = resources, + involvedPools = pools, + executionSummary = this + ) + } + else -> PreviewType.NonConforming } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/TransferAnalysis.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/TransferAnalysis.kt index f8009ddccf..eb6c457650 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/TransferAnalysis.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/TransferAnalysis.kt @@ -21,7 +21,7 @@ suspend fun ExecutionSummary.resolveTransfer( val to = extractDeposits(allOwnedAccounts, resources) val from = extractWithdraws(allOwnedAccounts, resources) - return PreviewType.Transfer( + return PreviewType.Transfer.GeneralTransfer( from = from, to = to ) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/UnstakeAnalysis.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/UnstakeAnalysis.kt index 883dcb0d20..5741fb7f23 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/UnstakeAnalysis.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/UnstakeAnalysis.kt @@ -20,11 +20,11 @@ suspend fun DetailedManifestClass.ValidatorUnstake.resolve( val fromAccounts = extractWithdrawals(executionSummary, getProfileUseCase, resources, involvedValidators) val toAccounts = extractDeposits(executionSummary, getProfileUseCase, resources, involvedValidators) val validatorAddressesSet = validatorAddresses.map { it.addressString() }.toSet() - return PreviewType.Staking( + return PreviewType.Transfer.Staking( from = fromAccounts, to = toAccounts, validators = involvedValidators.filter { it.address in validatorAddressesSet }, - actionType = PreviewType.Staking.ActionType.Unstake + actionType = PreviewType.Transfer.Staking.ActionType.Unstake ) } @@ -45,8 +45,6 @@ private suspend fun DetailedManifestClass.ValidatorUnstake.extractDeposits( val validator = involvedValidators.find { validatorUnstake.validatorAddress.addressString() == it.address } ?: error("No validator found") val stakeClaimNftItems = validatorUnstake.claimNftIds.map { localId -> - // TODO for a claim that has multiple claimNftLocalIds, we don't have a way now to determine its XRD worth - // this will need to be changed once RET provide xrd worth of each claim Resource.NonFungibleResource.Item( collectionAddress = resourceAddress, localId = Resource.NonFungibleResource.Item.ID.from(localId) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/CommonTransferContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/CommonTransferContent.kt new file mode 100644 index 0000000000..ead8b5e804 --- /dev/null +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/CommonTransferContent.kt @@ -0,0 +1,72 @@ +package com.babylon.wallet.android.presentation.transaction.composables + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.babylon.wallet.android.designsystem.theme.RadixTheme +import com.babylon.wallet.android.domain.model.resources.Resource +import com.babylon.wallet.android.presentation.transaction.PreviewType +import com.babylon.wallet.android.presentation.transaction.TransactionReviewViewModel +import kotlinx.collections.immutable.toPersistentList + +@Composable +fun CommonTransferContent( + modifier: Modifier = Modifier, + state: TransactionReviewViewModel.State, + onFungibleResourceClick: (fungibleResource: Resource.FungibleResource, Boolean) -> Unit, + onNonFungibleResourceClick: (nonFungibleResource: Resource.NonFungibleResource, Resource.NonFungibleResource.Item, Boolean) -> Unit, + previewType: PreviewType.Transfer, + onPromptForGuarantees: () -> Unit, + middleSection: @Composable () -> Unit +) { + Column( + modifier = modifier.fillMaxSize() + ) { + Column { + state.message?.let { + TransactionMessageContent( + modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingDefault), + transactionMessage = it + ) + + Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) + } + + WithdrawAccountContent( + modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingDefault), + from = previewType.from.toPersistentList(), + onFungibleResourceClick = { fungibleResource, isNewlyCreated -> + onFungibleResourceClick(fungibleResource, isNewlyCreated) + }, + onNonFungibleResourceClick = { nonFungibleResource, nonFungibleResourceItem, isNewlyCreated -> + onNonFungibleResourceClick(nonFungibleResource, nonFungibleResourceItem, isNewlyCreated) + } + ) + + middleSection() + + DepositAccountContent( + modifier = Modifier.padding( + start = RadixTheme.dimensions.paddingDefault, + end = RadixTheme.dimensions.paddingDefault, + bottom = RadixTheme.dimensions.paddingLarge + ), + to = previewType.to.toPersistentList(), + promptForGuarantees = onPromptForGuarantees, + showStrokeLine = true, + onFungibleResourceClick = { fungibleResource, isNewlyCreated -> + onFungibleResourceClick(fungibleResource, isNewlyCreated) + }, + onNonFungibleResourceClick = { nonFungibleResource, nonFungibleResourceItem, isNewlyCreated -> + onNonFungibleResourceClick(nonFungibleResource, nonFungibleResourceItem, isNewlyCreated) + } + ) + + Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) + } + } +} diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/PoolTypeContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/PoolTypeContent.kt new file mode 100644 index 0000000000..4104a91a7c --- /dev/null +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/PoolTypeContent.kt @@ -0,0 +1,65 @@ +package com.babylon.wallet.android.presentation.transaction.composables + +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import com.babylon.wallet.android.designsystem.theme.RadixTheme +import com.babylon.wallet.android.designsystem.theme.RadixWalletTheme +import com.babylon.wallet.android.domain.SampleDataProvider +import com.babylon.wallet.android.domain.model.resources.Resource +import com.babylon.wallet.android.presentation.transaction.PreviewType +import com.babylon.wallet.android.presentation.transaction.TransactionReviewViewModel +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toPersistentList + +@Composable +fun PoolTypeContent( + modifier: Modifier = Modifier, + state: TransactionReviewViewModel.State, + onFungibleResourceClick: (fungibleResource: Resource.FungibleResource, Boolean) -> Unit, + previewType: PreviewType.Transfer.Pool +) { + val poolSectionLabel = when (previewType.actionType) { + PreviewType.Transfer.Pool.ActionType.Contribution -> "Contributing to pools" + PreviewType.Transfer.Pool.ActionType.Redemption -> "Redeeming from pools" + } + CommonTransferContent( + modifier = modifier.fillMaxSize(), + state = state, + onFungibleResourceClick = onFungibleResourceClick, + onNonFungibleResourceClick = { _, _, _ -> }, + previewType = previewType, + onPromptForGuarantees = {}, + middleSection = { + PoolsContent( + modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingDefault), + pools = previewType.pools.toPersistentList(), + text = poolSectionLabel, + ) + } + ) +} + +@Preview(showBackground = true) +@Composable +fun PoolTypePreview() { + RadixWalletTheme { + PoolTypeContent( + state = TransactionReviewViewModel.State( + request = SampleDataProvider().transactionRequest, + isLoading = false, + isNetworkFeeLoading = false, + previewType = PreviewType.NonConforming + ), + onFungibleResourceClick = { _, _ -> }, + previewType = PreviewType.Transfer.Pool( + to = persistentListOf(), + from = listOf(SampleDataProvider().accountWithTransferablePool).toPersistentList(), + pools = persistentListOf(), + actionType = PreviewType.Transfer.Pool.ActionType.Contribution + ), + ) + } +} diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/PoolsContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/PoolsContent.kt new file mode 100644 index 0000000000..417a149f0d --- /dev/null +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/PoolsContent.kt @@ -0,0 +1,166 @@ +package com.babylon.wallet.android.presentation.transaction.composables + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.babylon.wallet.android.data.gateway.model.ExplicitMetadataKey +import com.babylon.wallet.android.designsystem.theme.RadixTheme +import com.babylon.wallet.android.designsystem.theme.RadixWalletTheme +import com.babylon.wallet.android.domain.model.resources.Pool +import com.babylon.wallet.android.domain.model.resources.metadata.Metadata +import com.babylon.wallet.android.domain.model.resources.metadata.MetadataType +import com.babylon.wallet.android.presentation.ui.composables.DSR +import com.babylon.wallet.android.presentation.ui.composables.PoolDetailsItem +import com.babylon.wallet.android.presentation.ui.composables.assets.dashedCircleBorder +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf + +@Composable +fun PoolsContent( + pools: ImmutableList, + modifier: Modifier = Modifier, + text: String +) { + var expanded by rememberSaveable { mutableStateOf(true) } + Box( + modifier = modifier.fillMaxWidth(), + contentAlignment = Alignment.CenterStart + ) { + Row( + modifier = Modifier + .clickable { expanded = !expanded }, + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(RadixTheme.dimensions.paddingMedium) + ) { + Image( + modifier = Modifier + .size(24.dp) + .dashedCircleBorder(RadixTheme.colors.gray3), + painter = painterResource(id = DSR.ic_pools_contribution), + contentDescription = null, + colorFilter = ColorFilter.tint(RadixTheme.colors.gray2), + contentScale = ContentScale.Inside + ) + Row( + Modifier.weight(1f), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(RadixTheme.dimensions.paddingMedium) + ) { + Text( + modifier = Modifier.weight(1f, false), + maxLines = 2, + text = text, + style = RadixTheme.typography.body1Link, + color = RadixTheme.colors.gray2, + overflow = TextOverflow.Ellipsis, + ) + val iconRes = if (expanded) { + com.babylon.wallet.android.designsystem.R.drawable.ic_arrow_up + } else { + com.babylon.wallet.android.designsystem.R.drawable.ic_arrow_down + } + Icon( + painter = painterResource(id = iconRes), + tint = RadixTheme.colors.gray2, + contentDescription = "arrow" + ) + } + if (expanded) { + StrokeLine(modifier = Modifier.padding(end = RadixTheme.dimensions.paddingLarge), height = 60.dp) + } else { + Spacer(modifier = Modifier.height(60.dp)) + } + } + } + + AnimatedVisibility( + visible = expanded, + enter = fadeIn(), + exit = fadeOut() + ) { + Column( + modifier = Modifier + .padding(horizontal = RadixTheme.dimensions.paddingDefault) + .fillMaxWidth() + ) { + pools.forEach { pool -> + PoolDetailsItem( + iconSize = 44.dp, + pool = pool, + modifier = Modifier + .fillMaxWidth() + .background(RadixTheme.colors.defaultBackground, RadixTheme.shapes.roundedRectMedium) + .padding(RadixTheme.dimensions.paddingDefault) + ) + Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingMedium)) + } + } + } +} + +@Preview(showBackground = true) +@Composable +fun PoolsContentPreview() { + RadixWalletTheme { + Column { + PoolsContent( + pools = persistentListOf( + Pool( + "pool_tdx_19jd32jd3928jd3892jd329", + listOf( + Metadata.Primitive(key = ExplicitMetadataKey.NAME.key, value = "My Pool", valueType = MetadataType.String), + Metadata.Primitive(key = ExplicitMetadataKey.ICON_URL.key, value = "XXX", valueType = MetadataType.Url), + Metadata.Primitive( + key = ExplicitMetadataKey.POOL_UNIT.key, + value = "resource_tdx_19jd32jd3928jd3892jd329", + valueType = MetadataType.Address + ) + ), + emptyList() + ), + Pool( + "pool_tdx_19jd32jd3928jd3892jd328", + listOf( + Metadata.Primitive(key = ExplicitMetadataKey.NAME.key, value = "My Pool2", valueType = MetadataType.String), + Metadata.Primitive(key = ExplicitMetadataKey.ICON_URL.key, value = "XXX", valueType = MetadataType.Url), + Metadata.Primitive( + key = ExplicitMetadataKey.POOL_UNIT.key, + value = "resource_tdx_19jd32jd3928jd3892jd329", + valueType = MetadataType.Address + ) + ), + emptyList() + ) + ), + text = "Contributing to pools".uppercase() + ) + } + } +} diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/StakeTypeContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/StakeTypeContent.kt index 0436460ebf..b224f5353c 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/StakeTypeContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/StakeTypeContent.kt @@ -1,9 +1,6 @@ package com.babylon.wallet.android.presentation.transaction.composables -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -25,63 +22,28 @@ fun StakeTypeContent( state: TransactionReviewViewModel.State, onFungibleResourceClick: (fungibleResource: Resource.FungibleResource, Boolean) -> Unit, onNonFungibleResourceClick: (nonFungibleResource: Resource.NonFungibleResource, Resource.NonFungibleResource.Item, Boolean) -> Unit, - previewType: PreviewType.Staking + previewType: PreviewType.Transfer.Staking ) { val validatorSectionText = when (previewType.actionType) { - PreviewType.Staking.ActionType.Stake -> stringResource(id = R.string.transactionReview_validators_stake).uppercase() - PreviewType.Staking.ActionType.Unstake -> stringResource(id = R.string.transactionReview_validators_unstake).uppercase() - PreviewType.Staking.ActionType.ClaimStake -> stringResource(id = R.string.transactionReview_validators_claim).uppercase() + PreviewType.Transfer.Staking.ActionType.Stake -> stringResource(id = R.string.transactionReview_validators_stake).uppercase() + PreviewType.Transfer.Staking.ActionType.Unstake -> stringResource(id = R.string.transactionReview_validators_unstake).uppercase() + PreviewType.Transfer.Staking.ActionType.ClaimStake -> stringResource(id = R.string.transactionReview_validators_claim).uppercase() } - Column( - modifier = modifier.fillMaxSize() - ) { - Column { - state.message?.let { - TransactionMessageContent( - modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingDefault), - transactionMessage = it - ) - - Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) - } - - WithdrawAccountContent( - modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingDefault), - from = previewType.from.toPersistentList(), - onFungibleResourceClick = { fungibleResource, isNewlyCreated -> - onFungibleResourceClick(fungibleResource, isNewlyCreated) - }, - onNonFungibleResourceClick = { nonFungibleResource, nonFungibleResourceItem, isNewlyCreated -> - onNonFungibleResourceClick(nonFungibleResource, nonFungibleResourceItem, isNewlyCreated) - } - ) - + CommonTransferContent( + modifier = modifier.fillMaxSize(), + state = state, + onFungibleResourceClick = onFungibleResourceClick, + onNonFungibleResourceClick = onNonFungibleResourceClick, + previewType = previewType, + onPromptForGuarantees = {}, + middleSection = { ValidatorsContent( modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingDefault), validators = previewType.validators.toPersistentList(), text = validatorSectionText, ) - - DepositAccountContent( - modifier = Modifier.padding( - start = RadixTheme.dimensions.paddingDefault, - end = RadixTheme.dimensions.paddingDefault, - bottom = RadixTheme.dimensions.paddingLarge - ), - to = previewType.to.toPersistentList(), - promptForGuarantees = {}, - showStrokeLine = true, - onFungibleResourceClick = { fungibleResource, isNewlyCreated -> - onFungibleResourceClick(fungibleResource, isNewlyCreated) - }, - onNonFungibleResourceClick = { nonFungibleResource, nonFungibleResourceItem, isNewlyCreated -> - onNonFungibleResourceClick(nonFungibleResource, nonFungibleResourceItem, isNewlyCreated) - } - ) - - Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) } - } + ) } @Preview(showBackground = true) @@ -97,11 +59,11 @@ fun StakeUnstakeTypePreview() { ), onFungibleResourceClick = { _, _ -> }, onNonFungibleResourceClick = { _, _, _ -> }, - previewType = PreviewType.Staking( + previewType = PreviewType.Transfer.Staking( to = persistentListOf(), from = listOf(SampleDataProvider().accountWithTransferableResourceLsu).toPersistentList(), validators = persistentListOf(), - actionType = PreviewType.Staking.ActionType.Stake + actionType = PreviewType.Transfer.Staking.ActionType.Stake ), ) } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/TransactionAccountCard.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/TransactionAccountCard.kt index aecca78880..ba05e53bc9 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/TransactionAccountCard.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/TransactionAccountCard.kt @@ -43,6 +43,7 @@ import com.babylon.wallet.android.domain.model.TransferableResource import com.babylon.wallet.android.domain.model.resources.Resource import com.babylon.wallet.android.domain.model.resources.XrdResource import com.babylon.wallet.android.domain.model.resources.asLsu +import com.babylon.wallet.android.domain.model.resources.metadata.name import com.babylon.wallet.android.presentation.transaction.AccountWithTransferableResources import com.babylon.wallet.android.presentation.transaction.AccountWithTransferableResources.Other import com.babylon.wallet.android.presentation.transaction.AccountWithTransferableResources.Owned @@ -84,6 +85,10 @@ fun TransactionAccountCard( account.resources.filter { it.transferable is TransferableResource.StakeClaimNft } } + val poolUnitTransferables = remember(account.resources) { + account.resources.filter { it.transferable is TransferableResource.Pool } + } + // Fungibles amountTransferables.forEachIndexed { index, amountTransferable -> val lastItem = if (nftTransferables.isEmpty()) index == amountTransferables.lastIndex else false @@ -144,6 +149,21 @@ fun TransactionAccountCard( HorizontalDivider(color = RadixTheme.colors.gray4) } } + + poolUnitTransferables.forEachIndexed { index, transferable -> + val lastItem = index == poolUnitTransferables.lastIndex + val shape = if (lastItem) RadixTheme.shapes.roundedRectBottomMedium else RectangleShape + val transferablePoolUnit = transferable.transferable as TransferableResource.Pool + + TransferablePoolUnitItemContent( + transferable = transferablePoolUnit, + shape = shape, + onFungibleResourceClick = onFungibleResourceClick + ) + if (lastItem.not()) { + HorizontalDivider(color = RadixTheme.colors.gray4) + } + } } } @@ -247,17 +267,14 @@ private fun TransferableItemContent( ) } - is TransferableResource.StakeClaimNft, - is TransferableResource.LsuAmount -> { - } + else -> {} } Text( modifier = Modifier.weight(1f), text = when (val resource = transferable.transferable) { is TransferableResource.Amount -> resource.resource.displayTitle is TransferableResource.NFTs -> resource.resource.name - is TransferableResource.LsuAmount, - is TransferableResource.StakeClaimNft -> "" + else -> "" }.ifEmpty { stringResource(id = R.string.transactionReview_unknown) }, style = RadixTheme.typography.body2HighImportance, color = RadixTheme.colors.gray1, @@ -518,6 +535,107 @@ private fun TransferableStakeClaimNftItemContent( } } +@Composable +private fun TransferablePoolUnitItemContent( + modifier: Modifier = Modifier, + transferable: TransferableResource.Pool, + shape: Shape, + onFungibleResourceClick: (fungibleResource: Resource.FungibleResource, Boolean) -> Unit +) { + Column( + modifier = modifier + .height(IntrinsicSize.Min) + .background( + color = RadixTheme.colors.gray5, + shape = shape + ) + .padding( + horizontal = RadixTheme.dimensions.paddingDefault, + vertical = RadixTheme.dimensions.paddingMedium + ) + ) { + Row( + verticalAlignment = CenterVertically, + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(RadixTheme.dimensions.paddingMedium) + ) { + Thumbnail.PoolUnit( + modifier = Modifier.size(44.dp), + poolUnit = transferable.pool + ) + Column(modifier = Modifier.weight(1f)) { + Text( + modifier = Modifier.fillMaxWidth(), + text = transferable.pool.stake.displayTitle.ifEmpty { stringResource(id = R.string.transactionReview_unknown) }, + style = RadixTheme.typography.body2HighImportance, + color = RadixTheme.colors.gray1, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + Text( + text = transferable.pool.pool?.metadata?.name().orEmpty().ifEmpty { "Unknown pool" }, // TODO crowdin + style = RadixTheme.typography.body2Regular, + color = RadixTheme.colors.gray2, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + } + Icon(painter = painterResource(id = DSR.ic_info_outline), contentDescription = null, tint = RadixTheme.colors.gray3) + } + Text( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = RadixTheme.dimensions.paddingSmall), + text = stringResource(id = R.string.transactionReview_worth).uppercase(), + style = RadixTheme.typography.body2HighImportance, + color = RadixTheme.colors.gray2, + maxLines = 1 + ) + val poolResources = transferable.pool.pool?.resources.orEmpty() + Column(modifier = Modifier.border(1.dp, RadixTheme.colors.gray3, shape = RadixTheme.shapes.roundedRectSmall)) { + poolResources.forEachIndexed { index, item -> + val addDivider = index != poolResources.lastIndex + Row( + modifier = Modifier + .clip(RadixTheme.shapes.roundedRectSmall) + .clickable { + onFungibleResourceClick( + item, + transferable.isNewlyCreated + ) + } + .fillMaxWidth() + .padding(RadixTheme.dimensions.paddingDefault), + verticalAlignment = CenterVertically, + horizontalArrangement = Arrangement.spacedBy(RadixTheme.dimensions.paddingMedium) + ) { + Thumbnail.Fungible( + modifier = Modifier.size(44.dp), + token = item, + ) + Text( + text = item.displayTitle, + style = RadixTheme.typography.body2HighImportance, + color = RadixTheme.colors.gray1, + maxLines = 2 + ) + Text( + modifier = Modifier.weight(1f), + text = transferable.contributionPerResource[item.resourceAddress]?.displayableQuantity().orEmpty(), + style = RadixTheme.typography.secondaryHeader, + color = RadixTheme.colors.gray1, + textAlign = TextAlign.End, + maxLines = 2 + ) + } + if (addDivider) { + HorizontalDivider(color = RadixTheme.colors.gray3) + } + } + } + } +} + @Composable private fun TransferableNftItemContent( modifier: Modifier = Modifier, diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/TransferTypeContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/TransferTypeContent.kt index 106d416c06..3c2ab629a3 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/TransferTypeContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/TransferTypeContent.kt @@ -1,9 +1,6 @@ package com.babylon.wallet.android.presentation.transaction.composables -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -22,35 +19,20 @@ import kotlinx.collections.immutable.toPersistentList fun TransferTypeContent( modifier: Modifier = Modifier, state: TransactionReviewViewModel.State, - preview: PreviewType.Transfer, + preview: PreviewType.Transfer.GeneralTransfer, onPromptForGuarantees: () -> Unit, onDappClick: (DApp) -> Unit, onFungibleResourceClick: (fungibleResource: Resource.FungibleResource, Boolean) -> Unit, onNonFungibleResourceClick: (nonFungibleResource: Resource.NonFungibleResource, Resource.NonFungibleResource.Item, Boolean) -> Unit ) { - Column( - modifier = modifier.fillMaxSize() - ) { - Column { - state.message?.let { - TransactionMessageContent( - modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingDefault), - transactionMessage = it - ) - - Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) - } - - WithdrawAccountContent( - modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingDefault), - from = preview.from.toPersistentList(), - onFungibleResourceClick = { fungibleResource, isNewlyCreated -> - onFungibleResourceClick(fungibleResource, isNewlyCreated) - }, - onNonFungibleResourceClick = { nonFungibleResource, nonFungibleResourceItem, isNewlyCreated -> - onNonFungibleResourceClick(nonFungibleResource, nonFungibleResourceItem, isNewlyCreated) - } - ) + CommonTransferContent( + modifier = modifier.fillMaxSize(), + state = state, + onFungibleResourceClick = onFungibleResourceClick, + onNonFungibleResourceClick = onNonFungibleResourceClick, + previewType = preview, + onPromptForGuarantees = onPromptForGuarantees, + middleSection = { if (preview.dApps.toPersistentList().isNotEmpty()) { StrokeLine(modifier = Modifier.padding(end = RadixTheme.dimensions.paddingLarge), height = 60.dp) } @@ -59,27 +41,8 @@ fun TransferTypeContent( connectedDApps = preview.dApps.toPersistentList(), onDAppClick = onDappClick ) - - DepositAccountContent( - modifier = Modifier.padding( - start = RadixTheme.dimensions.paddingDefault, - end = RadixTheme.dimensions.paddingDefault, - bottom = RadixTheme.dimensions.paddingLarge - ), - to = preview.to.toPersistentList(), - promptForGuarantees = onPromptForGuarantees, - showStrokeLine = true, - onFungibleResourceClick = { fungibleResource, isNewlyCreated -> - onFungibleResourceClick(fungibleResource, isNewlyCreated) - }, - onNonFungibleResourceClick = { nonFungibleResource, nonFungibleResourceItem, isNewlyCreated -> - onNonFungibleResourceClick(nonFungibleResource, nonFungibleResourceItem, isNewlyCreated) - } - ) - - Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) } - } + ) } @Preview(showBackground = true) @@ -93,7 +56,7 @@ fun TransactionPreviewTypePreview() { isNetworkFeeLoading = false, previewType = PreviewType.NonConforming ), - preview = PreviewType.Transfer( + preview = PreviewType.Transfer.GeneralTransfer( from = emptyList(), to = listOf(SampleDataProvider().accountWithTransferableResourcesOwned) ), diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/ValidatorsContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/ValidatorsContent.kt index b066c9d24b..e140985b94 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/ValidatorsContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/ValidatorsContent.kt @@ -34,8 +34,8 @@ import com.babylon.wallet.android.designsystem.theme.RadixTheme import com.babylon.wallet.android.designsystem.theme.RadixWalletTheme import com.babylon.wallet.android.domain.model.assets.ValidatorDetail import com.babylon.wallet.android.presentation.ui.composables.DSR +import com.babylon.wallet.android.presentation.ui.composables.ValidatorDetailsItem import com.babylon.wallet.android.presentation.ui.composables.assets.dashedCircleBorder -import com.babylon.wallet.android.presentation.ui.composables.resources.ValidatorDetailsItem import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import java.math.BigDecimal @@ -92,6 +92,8 @@ fun ValidatorsContent( } if (expanded) { StrokeLine(modifier = Modifier.padding(end = RadixTheme.dimensions.paddingLarge), height = 60.dp) + } else { + Spacer(modifier = Modifier.height(60.dp)) } } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/guarantees/TransactionGuaranteesDelegate.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/guarantees/TransactionGuaranteesDelegate.kt index c71721e158..2bdff23aba 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/guarantees/TransactionGuaranteesDelegate.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/guarantees/TransactionGuaranteesDelegate.kt @@ -116,7 +116,7 @@ class TransactionGuaranteesDelegate @Inject constructor() : ViewModelDelegate { + override suspend fun getPools(poolAddresses: Set): Result> { error("Not needed") } diff --git a/app/src/test/java/com/babylon/wallet/android/presentation/dapp/login/DAppAuthorizedLoginViewModelTest.kt b/app/src/test/java/com/babylon/wallet/android/presentation/dapp/login/DAppAuthorizedLoginViewModelTest.kt index cc4a81ae86..bb440534c1 100644 --- a/app/src/test/java/com/babylon/wallet/android/presentation/dapp/login/DAppAuthorizedLoginViewModelTest.kt +++ b/app/src/test/java/com/babylon/wallet/android/presentation/dapp/login/DAppAuthorizedLoginViewModelTest.kt @@ -318,7 +318,7 @@ class DAppAuthorizedLoginViewModelTest : StateViewModelTest { + override suspend fun getPools(poolAddresses: Set): Result> { error("Not needed") } diff --git a/app/src/test/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModelTest.kt b/app/src/test/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModelTest.kt index 4461111e82..d488c1a25a 100644 --- a/app/src/test/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModelTest.kt +++ b/app/src/test/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModelTest.kt @@ -26,6 +26,7 @@ import com.babylon.wallet.android.domain.usecases.ResolveNotaryAndSignersUseCase import com.babylon.wallet.android.domain.usecases.SearchFeePayersUseCase import com.babylon.wallet.android.domain.usecases.assets.CacheNewlyCreatedEntitiesUseCase import com.babylon.wallet.android.domain.usecases.assets.GetNFTDetailsUseCase +import com.babylon.wallet.android.domain.usecases.assets.GetPoolDetailsUseCase import com.babylon.wallet.android.domain.usecases.transaction.GetTransactionBadgesUseCase import com.babylon.wallet.android.domain.usecases.transaction.SubmitTransactionUseCase import com.babylon.wallet.android.mockdata.account @@ -108,6 +109,7 @@ internal class TransactionReviewViewModelTest : StateViewModelTest() private val deviceCapabilityHelper = mockk() private val getValidatorsUseCase = mockk() + private val getPoolDetailsUseCase = mockk() private val savedStateHandle = mockk() private val exceptionMessageProvider = mockk() private val getDAppsUseCase = mockk() @@ -199,6 +201,7 @@ internal class TransactionReviewViewModelTest : StateViewModelTest + + + + + From e88aef49d34034cab1953e6d2cdeb50dbe303c32 Mon Sep 17 00:00:00 2001 From: Jakub Porzuczek Date: Mon, 15 Jan 2024 10:54:19 +0100 Subject: [PATCH 2/5] aggregate pool contributions --- .../android/domain/SampleDataProvider.kt | 5 +- .../android/domain/model/Transferable.kt | 13 +++-- .../analysis/PoolContributionAnalysis.kt | 47 +++++++++++-------- .../analysis/PoolRedemptionAnalysis.kt | 16 ++++--- .../analysis/TransactionAnalysisDelegate.kt | 5 +- .../analysis/TransactionTypeExtensions.kt | 17 +++++++ .../composables/TransactionAccountCard.kt | 6 +-- 7 files changed, 73 insertions(+), 36 deletions(-) diff --git a/app/src/main/java/com/babylon/wallet/android/domain/SampleDataProvider.kt b/app/src/main/java/com/babylon/wallet/android/domain/SampleDataProvider.kt index 8ca43ee9ef..0b11424b80 100644 --- a/app/src/main/java/com/babylon/wallet/android/domain/SampleDataProvider.kt +++ b/app/src/main/java/com/babylon/wallet/android/domain/SampleDataProvider.kt @@ -135,7 +135,7 @@ class SampleDataProvider { ) val transferableDepositingPool = Transferable.Depositing( - transferable = TransferableResource.Pool( + transferable = TransferableResource.PoolUnitAmount( pool = PoolUnit( Resource.FungibleResource( resourceAddress = "resource_tdx_e_1tkawacgvcw7z9xztccgjrged25c7nqtnd4nllh750s2ny64m0cltmg", @@ -197,7 +197,8 @@ class SampleDataProvider { contributionPerResource = mapOf( "resource_tdx_e_1tkawacgvcw7z9xztccgjrged25c7nqtnd4nllh750s2ny64m0clt12" to BigDecimal(100), "resource_tdx_e_1tkawacgvcw7z9xztccgjrged25c7nqtnd4nllh750s2ny64m0clt21" to BigDecimal(200) - ) + ), + amount = BigDecimal(300) ) ) diff --git a/app/src/main/java/com/babylon/wallet/android/domain/model/Transferable.kt b/app/src/main/java/com/babylon/wallet/android/domain/model/Transferable.kt index b038598ea4..f5115013fe 100644 --- a/app/src/main/java/com/babylon/wallet/android/domain/model/Transferable.kt +++ b/app/src/main/java/com/babylon/wallet/android/domain/model/Transferable.kt @@ -32,9 +32,15 @@ sealed interface Transferable { instructionIndex = predicted.instructionIndex ) - is TransferableResource.LsuAmount -> null + is TransferableResource.LsuAmount -> GuaranteeAssertion.ForAmount( + amount = transferable.amount * predicted.guaranteeOffset.toBigDecimal(), + instructionIndex = predicted.instructionIndex + ) is TransferableResource.StakeClaimNft -> null - is TransferableResource.Pool -> null + is TransferableResource.PoolUnitAmount -> GuaranteeAssertion.ForAmount( + amount = transferable.amount * predicted.guaranteeOffset.toBigDecimal(), + instructionIndex = predicted.instructionIndex + ) } } @@ -127,7 +133,8 @@ sealed interface TransferableResource { override val isNewlyCreated: Boolean = false ) : TransferableResource - data class Pool( + data class PoolUnitAmount( + val amount: BigDecimal, val pool: PoolUnit, val contributionPerResource: Map, override val isNewlyCreated: Boolean = false, diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/PoolContributionAnalysis.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/PoolContributionAnalysis.kt index 7374c93821..cde0f35e3c 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/PoolContributionAnalysis.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/PoolContributionAnalysis.kt @@ -14,6 +14,7 @@ import rdx.works.profile.data.model.pernetwork.Network import rdx.works.profile.domain.GetProfileUseCase import rdx.works.profile.domain.accountOnCurrentNetwork import rdx.works.profile.domain.accountsOnCurrentNetwork +import timber.log.Timber suspend fun DetailedManifestClass.PoolContribution.resolve( executionSummary: ExecutionSummary, @@ -28,28 +29,34 @@ suspend fun DetailedManifestClass.PoolContribution.resolve( val from = executionSummary.extractWithdraws(ownedAccountsWithdrawnFrom, resources) val to = executionSummary.accountDeposits.map { depositsPerAddress -> val ownedAccount = getProfileUseCase.accountOnCurrentNetwork(depositsPerAddress.key) ?: error("No account found") - val deposits = depositsPerAddress.value.map { deposit -> + depositsPerAddress.value.forEach { + Timber.d("depositing: ${it.resourceAddress}") + } + val deposits = depositsPerAddress.value.mapNotNull { deposit -> val resourceAddress = deposit.resourceAddress - val contribution = poolContributions.find { it.poolUnitsResourceAddress.addressString() == resourceAddress } - ?: error("No contribution found") - val pool = involvedPools.find { it.address == contribution.poolAddress.addressString() } - ?: error("No pool found") - val poolResource = resources.find { it.resourceAddress == pool.metadata.poolUnit() } as? Resource.FungibleResource - ?: error("No pool resource found") - val contributedResourceAddresses = contribution.contributedResources.keys - Transferable.Depositing( - transferable = TransferableResource.Pool( - PoolUnit( - stake = poolResource, - pool = pool - ), - contributedResourceAddresses.associateWith { contributedResourceAddress -> - val contributionValue = contribution.contributedResources[contributedResourceAddress] - ?: error("No contribution value found") - contributionValue.asStr().toBigDecimal() - }, + val contributions = poolContributions.filter { it.poolUnitsResourceAddress.addressString() == resourceAddress } + if (contributions.isEmpty()) { + null + } else { + val pool = involvedPools.find { it.address == contributions.first().poolAddress.addressString() } + ?: error("No pool found") + val poolResource = resources.find { it.resourceAddress == pool.metadata.poolUnit() } as? Resource.FungibleResource + ?: error("No pool resource found") + val contributedResourceAddresses = contributions.first().contributedResources.keys + Transferable.Depositing( + transferable = TransferableResource.PoolUnitAmount( + amount = contributions.map { it.poolUnitsAmount.asStr().toBigDecimal() }.sumOf { it }, + PoolUnit( + stake = poolResource, + pool = pool + ), + contributedResourceAddresses.associateWith { contributedResourceAddress -> + contributions.mapNotNull { it.contributedResources[contributedResourceAddress]?.asStr()?.toBigDecimal() } + .sumOf { it } + }, + ) ) - ) + } } AccountWithTransferableResources.Owned( account = ownedAccount, diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/PoolRedemptionAnalysis.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/PoolRedemptionAnalysis.kt index e260891443..e2e7a02211 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/PoolRedemptionAnalysis.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/PoolRedemptionAnalysis.kt @@ -30,22 +30,24 @@ suspend fun DetailedManifestClass.PoolRedemption.resolve( val ownedAccount = getProfileUseCase.accountOnCurrentNetwork(withdrawsPerAddress.key) ?: error("No account found") val deposits = withdrawsPerAddress.value.map { withdraw -> val resourceAddress = withdraw.resourceAddress - val redemption = poolRedemptions.find { it.poolUnitsResourceAddress.addressString() == resourceAddress } - ?: error("No redemption found") - val pool = involvedPools.find { it.address == redemption.poolAddress.addressString() } + val redemptions = poolRedemptions.filter { + it.poolUnitsResourceAddress.addressString() == resourceAddress + } + val pool = involvedPools.find { it.address == redemptions.first().poolAddress.addressString() } ?: error("No pool found") val poolResource = resources.find { it.resourceAddress == pool.metadata.poolUnit() } as? Resource.FungibleResource ?: error("No pool resource found") - val redemptionResourceAddresses = redemption.redeemedResources.keys + val redemptionResourceAddresses = redemptions.first().redeemedResources.keys Transferable.Withdrawing( - transferable = TransferableResource.Pool( + transferable = TransferableResource.PoolUnitAmount( + amount = redemptions.map { it.poolUnitsAmount.asStr().toBigDecimal() }.sumOf { it }, PoolUnit( stake = poolResource, pool = pool ), redemptionResourceAddresses.associateWith { contributedResourceAddress -> - val redemptionValue = redemption.redeemedResources[contributedResourceAddress] ?: error("No redemption value found") - redemptionValue.asStr().toBigDecimal() + redemptions.mapNotNull { it.redeemedResources[contributedResourceAddress]?.asStr()?.toBigDecimal() } + .sumOf { it } }, ) ) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/TransactionAnalysisDelegate.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/TransactionAnalysisDelegate.kt index 504bc00eb6..4e65e0dc39 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/TransactionAnalysisDelegate.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/TransactionAnalysisDelegate.kt @@ -157,7 +157,9 @@ class TransactionAnalysisDelegate @Inject constructor( private suspend fun ExecutionSummary.processConformingManifest(): PreviewType { val networkId = requireNotNull(getProfileUseCase.currentNetwork()?.knownNetworkId) val xrdAddress = XrdResource.address(networkId) - val transactionType = detailedClassification.first() + val transactionType = detailedClassification.firstOrNull { + it.isConformingManifestType() + } ?: return PreviewType.NonConforming val resources = getResourcesUseCase(addresses = involvedResourceAddresses + xrdAddress).getOrThrow() return when (transactionType) { @@ -219,6 +221,7 @@ class TransactionAnalysisDelegate @Inject constructor( executionSummary = this ) } + is DetailedManifestClass.PoolRedemption -> { val pools = getPoolDetailsUseCase(transactionType.poolAddresses.map { it.addressString() }.toSet()).getOrThrow() transactionType.resolve( diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/TransactionTypeExtensions.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/TransactionTypeExtensions.kt index 2dfc0a875e..b4a2878567 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/TransactionTypeExtensions.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/TransactionTypeExtensions.kt @@ -221,6 +221,23 @@ fun ResourceIndicator.toWithdrawingTransferableResource( } } +fun DetailedManifestClass.isConformingManifestType(): Boolean { + return when (this) { + is DetailedManifestClass.AccountDepositSettingsUpdate -> { + true + } + + DetailedManifestClass.General -> true + is DetailedManifestClass.PoolContribution -> true + is DetailedManifestClass.PoolRedemption -> true + is DetailedManifestClass.Transfer -> true + is DetailedManifestClass.ValidatorClaim -> true + is DetailedManifestClass.ValidatorStake -> true + is DetailedManifestClass.ValidatorUnstake -> true + else -> false + } +} + private fun FungibleResourceIndicator.toGuaranteeType(defaultDepositGuarantees: Double): GuaranteeType { return when (this) { is FungibleResourceIndicator.Guaranteed -> GuaranteeType.Guaranteed diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/TransactionAccountCard.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/TransactionAccountCard.kt index ba05e53bc9..5c174f154b 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/TransactionAccountCard.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/TransactionAccountCard.kt @@ -86,7 +86,7 @@ fun TransactionAccountCard( } val poolUnitTransferables = remember(account.resources) { - account.resources.filter { it.transferable is TransferableResource.Pool } + account.resources.filter { it.transferable is TransferableResource.PoolUnitAmount } } // Fungibles @@ -153,7 +153,7 @@ fun TransactionAccountCard( poolUnitTransferables.forEachIndexed { index, transferable -> val lastItem = index == poolUnitTransferables.lastIndex val shape = if (lastItem) RadixTheme.shapes.roundedRectBottomMedium else RectangleShape - val transferablePoolUnit = transferable.transferable as TransferableResource.Pool + val transferablePoolUnit = transferable.transferable as TransferableResource.PoolUnitAmount TransferablePoolUnitItemContent( transferable = transferablePoolUnit, @@ -538,7 +538,7 @@ private fun TransferableStakeClaimNftItemContent( @Composable private fun TransferablePoolUnitItemContent( modifier: Modifier = Modifier, - transferable: TransferableResource.Pool, + transferable: TransferableResource.PoolUnitAmount, shape: Shape, onFungibleResourceClick: (fungibleResource: Resource.FungibleResource, Boolean) -> Unit ) { From 0c3f81fc820091768d8d18cb363afcaded36b68a Mon Sep 17 00:00:00 2001 From: Jakub Porzuczek Date: Mon, 15 Jan 2024 13:55:18 +0100 Subject: [PATCH 3/5] display guarantees for pool units --- .../android/domain/SampleDataProvider.kt | 4 +- .../android/domain/model/Transferable.kt | 42 ++++- .../transaction/TransactionReviewScreen.kt | 2 + .../transaction/TransactionReviewViewModel.kt | 18 +- .../analysis/PoolContributionAnalysis.kt | 13 +- .../transaction/analysis/StakeAnalysis.kt | 2 +- .../analysis/StakeClaimAnalysis.kt | 2 +- .../analysis/TransactionTypeExtensions.kt | 8 +- .../composables/PoolTypeContent.kt | 6 +- .../composables/StakeTypeContent.kt | 6 +- .../composables/TransactionAccountCard.kt | 178 ++++++++++-------- .../TransactionAccountWithGuaranteesCard.kt | 10 +- .../TransactionGuaranteesDelegate.kt | 77 ++++++-- 13 files changed, 234 insertions(+), 134 deletions(-) diff --git a/app/src/main/java/com/babylon/wallet/android/domain/SampleDataProvider.kt b/app/src/main/java/com/babylon/wallet/android/domain/SampleDataProvider.kt index 0b11424b80..6b0bc190f0 100644 --- a/app/src/main/java/com/babylon/wallet/android/domain/SampleDataProvider.kt +++ b/app/src/main/java/com/babylon/wallet/android/domain/SampleDataProvider.kt @@ -89,7 +89,7 @@ class SampleDataProvider { ) val transferableDepositing = Transferable.Depositing( - transferable = TransferableResource.Amount( + transferable = TransferableResource.FungibleAmount( amount = BigDecimal(69), resource = Resource.FungibleResource( resourceAddress = "resource_tdx_e_1tkawacgvcw7z9xztccgjrged25c7nqtnd4nllh750s2ny64m0cltmg", @@ -136,7 +136,7 @@ class SampleDataProvider { val transferableDepositingPool = Transferable.Depositing( transferable = TransferableResource.PoolUnitAmount( - pool = PoolUnit( + poolUnit = PoolUnit( Resource.FungibleResource( resourceAddress = "resource_tdx_e_1tkawacgvcw7z9xztccgjrged25c7nqtnd4nllh750s2ny64m0cltmg", ownedAmount = null, diff --git a/app/src/main/java/com/babylon/wallet/android/domain/model/Transferable.kt b/app/src/main/java/com/babylon/wallet/android/domain/model/Transferable.kt index f5115013fe..bdb5088cd7 100644 --- a/app/src/main/java/com/babylon/wallet/android/domain/model/Transferable.kt +++ b/app/src/main/java/com/babylon/wallet/android/domain/model/Transferable.kt @@ -23,7 +23,7 @@ sealed interface Transferable { val predicted = guaranteeType as? GuaranteeType.Predicted ?: return null when (val transferable = transferable) { - is TransferableResource.Amount -> GuaranteeAssertion.ForAmount( + is TransferableResource.FungibleAmount -> GuaranteeAssertion.ForAmount( amount = transferable.amount * predicted.guaranteeOffset.toBigDecimal(), instructionIndex = predicted.instructionIndex ) @@ -36,6 +36,7 @@ sealed interface Transferable { amount = transferable.amount * predicted.guaranteeOffset.toBigDecimal(), instructionIndex = predicted.instructionIndex ) + is TransferableResource.StakeClaimNft -> null is TransferableResource.PoolUnitAmount -> GuaranteeAssertion.ForAmount( amount = transferable.amount * predicted.guaranteeOffset.toBigDecimal(), @@ -48,6 +49,14 @@ sealed interface Transferable { } } + val hasEditableGuarantees: Boolean + get() { + return when (this) { + is Depositing -> guaranteeType is GuaranteeType.Predicted && !transferable.isNewlyCreated + is Withdrawing -> false + } + } + data class Depositing( override val transferable: TransferableResource, val guaranteeType: GuaranteeType = GuaranteeType.Guaranteed @@ -107,19 +116,25 @@ sealed interface TransferableResource { get() = resource.resourceAddress val isNewlyCreated: Boolean - data class Amount( - val amount: BigDecimal, + data class FungibleAmount( + override val amount: BigDecimal, override val resource: Resource.FungibleResource, override val isNewlyCreated: Boolean - ) : TransferableResource + ) : TransferableResource, TransferableWithGuarantees { + override val fungibleResource: Resource.FungibleResource + get() = resource + } data class LsuAmount( - val amount: BigDecimal, + override val amount: BigDecimal, override val resource: Resource.FungibleResource, val validatorDetail: ValidatorDetail, val xrdWorth: BigDecimal, override val isNewlyCreated: Boolean = false - ) : TransferableResource + ) : TransferableResource, TransferableWithGuarantees { + override val fungibleResource: Resource.FungibleResource + get() = resource + } data class NFTs( override val resource: Resource.NonFungibleResource, @@ -134,12 +149,19 @@ sealed interface TransferableResource { ) : TransferableResource data class PoolUnitAmount( - val amount: BigDecimal, - val pool: PoolUnit, + override val amount: BigDecimal, + val poolUnit: PoolUnit, val contributionPerResource: Map, override val isNewlyCreated: Boolean = false, - ) : TransferableResource { + ) : TransferableResource, TransferableWithGuarantees { override val resource: Resource - get() = pool.stake + get() = poolUnit.stake + override val fungibleResource: Resource.FungibleResource + get() = poolUnit.stake } } + +interface TransferableWithGuarantees { + val fungibleResource: Resource.FungibleResource + val amount: BigDecimal +} diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewScreen.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewScreen.kt index e9fc10ca93..088245eb9f 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewScreen.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewScreen.kt @@ -315,6 +315,7 @@ private fun TransactionPreviewContent( state = state, onFungibleResourceClick = onFungibleResourceClick, onNonFungibleResourceClick = onNonFungibleResourceClick, + onPromptForGuarantees = promptForGuarantees, previewType = preview ) ReceiptEdge(modifier = Modifier.fillMaxWidth(), color = RadixTheme.colors.gray5) @@ -325,6 +326,7 @@ private fun TransactionPreviewContent( modifier = Modifier.background(RadixTheme.colors.gray5), state = state, onFungibleResourceClick = onFungibleResourceClick, + onPromptForGuarantees = promptForGuarantees, previewType = preview ) ReceiptEdge(modifier = Modifier.fillMaxWidth(), color = RadixTheme.colors.gray5) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModel.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModel.kt index 3b01adadba..cf406ab803 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModel.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/TransactionReviewViewModel.kt @@ -17,6 +17,7 @@ import com.babylon.wallet.android.domain.model.GuaranteeAssertion import com.babylon.wallet.android.domain.model.MessageFromDataChannel import com.babylon.wallet.android.domain.model.Transferable import com.babylon.wallet.android.domain.model.TransferableResource +import com.babylon.wallet.android.domain.model.TransferableWithGuarantees import com.babylon.wallet.android.domain.model.assets.ValidatorDetail import com.babylon.wallet.android.domain.model.resources.Badge import com.babylon.wallet.android.domain.model.resources.Resource @@ -370,7 +371,7 @@ class TransactionReviewViewModel @Inject constructor( if (candidateAddressWithdrawn != null) { val xrdResourceWithdrawn = candidateAddressWithdrawn.resources.map { it.transferable - }.filterIsInstance().find { it.resource.isXrd } + }.filterIsInstance().find { it.resource.isXrd } xrdResourceWithdrawn?.amount ?: BigDecimal.ZERO } else { @@ -534,9 +535,8 @@ data class AccountWithDepositSettingsChanges( @Suppress("MagicNumber") sealed interface AccountWithPredictedGuarantee { - val address: String - val transferableAmount: TransferableResource.Amount + val transferable: TransferableWithGuarantees val instructionIndex: Long val guaranteeAmountString: String @@ -545,7 +545,7 @@ sealed interface AccountWithPredictedGuarantee { get() = (guaranteeAmountString.toDoubleOrNull() ?: 0.0).div(100.0) val guaranteedAmount: BigDecimal - get() = transferableAmount.amount * guaranteeOffsetDecimal.toBigDecimal() + get() = transferable.amount * guaranteeOffsetDecimal.toBigDecimal() fun increase(): AccountWithPredictedGuarantee { val newOffset = (guaranteeOffsetDecimal.toBigDecimal().plus(BigDecimal(0.001))) @@ -580,11 +580,11 @@ sealed interface AccountWithPredictedGuarantee { } fun isTheSameGuaranteeItem(with: AccountWithPredictedGuarantee): Boolean = address == with.address && - transferableAmount.resourceAddress == with.transferableAmount.resourceAddress + transferable.fungibleResource.resourceAddress == with.transferable.fungibleResource.resourceAddress data class Owned( val account: Network.Account, - override val transferableAmount: TransferableResource.Amount, + override val transferable: TransferableWithGuarantees, override val instructionIndex: Long, override val guaranteeAmountString: String ) : AccountWithPredictedGuarantee { @@ -594,7 +594,7 @@ sealed interface AccountWithPredictedGuarantee { data class Other( override val address: String, - override val transferableAmount: TransferableResource.Amount, + override val transferable: TransferableWithGuarantees, override val instructionIndex: Long, override val guaranteeAmountString: String ) : AccountWithPredictedGuarantee @@ -628,12 +628,12 @@ sealed interface AccountWithTransferableResources { val resources = resources.mapWhen( predicate = { depositing -> resourcesWithGuaranteesForAccount.any { - it.address == address && it.transferableAmount.resourceAddress == depositing.transferable.resourceAddress + it.address == address && it.transferable.fungibleResource.resourceAddress == depositing.transferable.resourceAddress } }, mutation = { depositing -> val accountWithGuarantee = resourcesWithGuaranteesForAccount.find { - it.transferableAmount.resourceAddress == depositing.transferable.resourceAddress + it.transferable.fungibleResource.resourceAddress == depositing.transferable.resourceAddress } if (accountWithGuarantee != null) { diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/PoolContributionAnalysis.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/PoolContributionAnalysis.kt index cde0f35e3c..a528f09511 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/PoolContributionAnalysis.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/PoolContributionAnalysis.kt @@ -1,5 +1,6 @@ package com.babylon.wallet.android.presentation.transaction.analysis +import com.babylon.wallet.android.domain.model.GuaranteeType import com.babylon.wallet.android.domain.model.Transferable import com.babylon.wallet.android.domain.model.TransferableResource import com.babylon.wallet.android.domain.model.assets.PoolUnit @@ -10,11 +11,12 @@ import com.babylon.wallet.android.presentation.transaction.AccountWithTransferab import com.babylon.wallet.android.presentation.transaction.PreviewType import com.radixdlt.ret.DetailedManifestClass import com.radixdlt.ret.ExecutionSummary +import com.radixdlt.ret.ResourceIndicator +import kotlinx.coroutines.flow.first import rdx.works.profile.data.model.pernetwork.Network import rdx.works.profile.domain.GetProfileUseCase import rdx.works.profile.domain.accountOnCurrentNetwork import rdx.works.profile.domain.accountsOnCurrentNetwork -import timber.log.Timber suspend fun DetailedManifestClass.PoolContribution.resolve( executionSummary: ExecutionSummary, @@ -22,6 +24,7 @@ suspend fun DetailedManifestClass.PoolContribution.resolve( resources: List, involvedPools: List ): PreviewType { + val defaultDepositGuarantees = getProfileUseCase.invoke().first().appPreferences.transaction.defaultDepositGuarantee val accountsWithdrawnFrom = executionSummary.accountWithdraws.keys val ownedAccountsWithdrawnFrom = getProfileUseCase.accountsOnCurrentNetwork().filter { accountsWithdrawnFrom.contains(it.address) @@ -29,9 +32,6 @@ suspend fun DetailedManifestClass.PoolContribution.resolve( val from = executionSummary.extractWithdraws(ownedAccountsWithdrawnFrom, resources) val to = executionSummary.accountDeposits.map { depositsPerAddress -> val ownedAccount = getProfileUseCase.accountOnCurrentNetwork(depositsPerAddress.key) ?: error("No account found") - depositsPerAddress.value.forEach { - Timber.d("depositing: ${it.resourceAddress}") - } val deposits = depositsPerAddress.value.mapNotNull { deposit -> val resourceAddress = deposit.resourceAddress val contributions = poolContributions.filter { it.poolUnitsResourceAddress.addressString() == resourceAddress } @@ -43,6 +43,8 @@ suspend fun DetailedManifestClass.PoolContribution.resolve( val poolResource = resources.find { it.resourceAddress == pool.metadata.poolUnit() } as? Resource.FungibleResource ?: error("No pool resource found") val contributedResourceAddresses = contributions.first().contributedResources.keys + val guaranteeType = (deposit as? ResourceIndicator.Fungible)?.indicator?.toGuaranteeType(defaultDepositGuarantees) + ?: GuaranteeType.Guaranteed Transferable.Depositing( transferable = TransferableResource.PoolUnitAmount( amount = contributions.map { it.poolUnitsAmount.asStr().toBigDecimal() }.sumOf { it }, @@ -54,7 +56,8 @@ suspend fun DetailedManifestClass.PoolContribution.resolve( contributions.mapNotNull { it.contributedResources[contributedResourceAddress]?.asStr()?.toBigDecimal() } .sumOf { it } }, - ) + ), + guaranteeType = guaranteeType, ) } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/StakeAnalysis.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/StakeAnalysis.kt index f2259eb5d7..f4a90cecb1 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/StakeAnalysis.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/StakeAnalysis.kt @@ -77,7 +77,7 @@ private suspend fun extractWithdrawals( account = ownedAccount, resources = listOf( element = Transferable.Withdrawing( - transferable = TransferableResource.Amount( + transferable = TransferableResource.FungibleAmount( entry.value.sumOf { it.amount }, xrdResource, false diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/StakeClaimAnalysis.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/StakeClaimAnalysis.kt index 2d246d105e..7162af1dba 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/StakeClaimAnalysis.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/StakeClaimAnalysis.kt @@ -98,7 +98,7 @@ private suspend fun extractDeposits( account = ownedAccount, resources = listOf( element = Transferable.Depositing( - transferable = TransferableResource.Amount( + transferable = TransferableResource.FungibleAmount( entry.value.sumOf { it.amount }, xrdResource, false diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/TransactionTypeExtensions.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/TransactionTypeExtensions.kt index b4a2878567..56f562b62c 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/TransactionTypeExtensions.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/TransactionTypeExtensions.kt @@ -121,7 +121,7 @@ fun ResourceIndicator.toTransferableResource(resources: List): Transfe resourceAddress = resourceAddress, ownedAmount = BigDecimal.ZERO ) - TransferableResource.Amount( + TransferableResource.FungibleAmount( amount = amount, resource = resource, isNewlyCreated = false @@ -238,7 +238,7 @@ fun DetailedManifestClass.isConformingManifestType(): Boolean { } } -private fun FungibleResourceIndicator.toGuaranteeType(defaultDepositGuarantees: Double): GuaranteeType { +fun FungibleResourceIndicator.toGuaranteeType(defaultDepositGuarantees: Double): GuaranteeType { return when (this) { is FungibleResourceIndicator.Guaranteed -> GuaranteeType.Guaranteed is FungibleResourceIndicator.Predicted -> GuaranteeType.Predicted( @@ -258,14 +258,14 @@ private fun ResourceIndicator.Fungible.toTransferableResource( resources: List, newlyCreatedMetadata: Map>, newlyCreatedEntities: List
-): TransferableResource.Amount { +): TransferableResource.FungibleAmount { val resource = resources.findFungible( resourceAddress.addressString() ) ?: Resource.FungibleResource.from( resourceAddress = resourceAddress, metadata = newlyCreatedMetadata[resourceAddress.addressString()].orEmpty() ) - return TransferableResource.Amount( + return TransferableResource.FungibleAmount( amount = amount, resource = resource, isNewlyCreated = resourceAddress.addressString() in newlyCreatedEntities.map { it.addressString() } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/PoolTypeContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/PoolTypeContent.kt index 4104a91a7c..e6d0996512 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/PoolTypeContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/PoolTypeContent.kt @@ -19,7 +19,8 @@ fun PoolTypeContent( modifier: Modifier = Modifier, state: TransactionReviewViewModel.State, onFungibleResourceClick: (fungibleResource: Resource.FungibleResource, Boolean) -> Unit, - previewType: PreviewType.Transfer.Pool + previewType: PreviewType.Transfer.Pool, + onPromptForGuarantees: () -> Unit ) { val poolSectionLabel = when (previewType.actionType) { PreviewType.Transfer.Pool.ActionType.Contribution -> "Contributing to pools" @@ -31,7 +32,7 @@ fun PoolTypeContent( onFungibleResourceClick = onFungibleResourceClick, onNonFungibleResourceClick = { _, _, _ -> }, previewType = previewType, - onPromptForGuarantees = {}, + onPromptForGuarantees = onPromptForGuarantees, middleSection = { PoolsContent( modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingDefault), @@ -60,6 +61,7 @@ fun PoolTypePreview() { pools = persistentListOf(), actionType = PreviewType.Transfer.Pool.ActionType.Contribution ), + onPromptForGuarantees = {}, ) } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/StakeTypeContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/StakeTypeContent.kt index b224f5353c..af13dcd11c 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/StakeTypeContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/StakeTypeContent.kt @@ -22,7 +22,8 @@ fun StakeTypeContent( state: TransactionReviewViewModel.State, onFungibleResourceClick: (fungibleResource: Resource.FungibleResource, Boolean) -> Unit, onNonFungibleResourceClick: (nonFungibleResource: Resource.NonFungibleResource, Resource.NonFungibleResource.Item, Boolean) -> Unit, - previewType: PreviewType.Transfer.Staking + previewType: PreviewType.Transfer.Staking, + onPromptForGuarantees: () -> Unit ) { val validatorSectionText = when (previewType.actionType) { PreviewType.Transfer.Staking.ActionType.Stake -> stringResource(id = R.string.transactionReview_validators_stake).uppercase() @@ -35,7 +36,7 @@ fun StakeTypeContent( onFungibleResourceClick = onFungibleResourceClick, onNonFungibleResourceClick = onNonFungibleResourceClick, previewType = previewType, - onPromptForGuarantees = {}, + onPromptForGuarantees = onPromptForGuarantees, middleSection = { ValidatorsContent( modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingDefault), @@ -65,6 +66,7 @@ fun StakeUnstakeTypePreview() { validators = persistentListOf(), actionType = PreviewType.Transfer.Staking.ActionType.Stake ), + onPromptForGuarantees = {}, ) } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/TransactionAccountCard.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/TransactionAccountCard.kt index 5c174f154b..e3718d7678 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/TransactionAccountCard.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/TransactionAccountCard.kt @@ -40,6 +40,7 @@ import com.babylon.wallet.android.domain.SampleDataProvider import com.babylon.wallet.android.domain.model.GuaranteeAssertion import com.babylon.wallet.android.domain.model.Transferable import com.babylon.wallet.android.domain.model.TransferableResource +import com.babylon.wallet.android.domain.model.TransferableWithGuarantees import com.babylon.wallet.android.domain.model.resources.Resource import com.babylon.wallet.android.domain.model.resources.XrdResource import com.babylon.wallet.android.domain.model.resources.asLsu @@ -69,8 +70,8 @@ fun TransactionAccountCard( shape = RadixTheme.shapes.roundedRectTopMedium ) - val amountTransferables = remember(account.resources) { - account.resources.filter { it.transferable is TransferableResource.Amount } + val fungibleAmountTransferables = remember(account.resources) { + account.resources.filter { it.transferable is TransferableResource.FungibleAmount } } val nftTransferables = remember(account.resources) { @@ -90,14 +91,14 @@ fun TransactionAccountCard( } // Fungibles - amountTransferables.forEachIndexed { index, amountTransferable -> - val lastItem = if (nftTransferables.isEmpty()) index == amountTransferables.lastIndex else false + fungibleAmountTransferables.forEachIndexed { index, amountTransferable -> + val lastItem = if (nftTransferables.isEmpty()) index == fungibleAmountTransferables.lastIndex else false val shape = if (lastItem) RadixTheme.shapes.roundedRectBottomMedium else RectangleShape - val transferableAmount = amountTransferable.transferable as TransferableResource.Amount + val transferableFungibleAmount = amountTransferable.transferable as TransferableResource.FungibleAmount TransferableItemContent( modifier = Modifier.clickable { - onFungibleResourceClick(transferableAmount.resource, transferableAmount.isNewlyCreated) + onFungibleResourceClick(transferableFungibleAmount.resource, transferableFungibleAmount.isNewlyCreated) }, transferable = amountTransferable, shape = shape, @@ -128,7 +129,7 @@ fun TransactionAccountCard( modifier = Modifier.clickable { onFungibleResourceClick(transferableLsu.resource, transferableLsu.isNewlyCreated) }, - transferable = transferableLsu, + transferable = transferable, shape = shape, ) if (lastItem.not()) { @@ -153,10 +154,9 @@ fun TransactionAccountCard( poolUnitTransferables.forEachIndexed { index, transferable -> val lastItem = index == poolUnitTransferables.lastIndex val shape = if (lastItem) RadixTheme.shapes.roundedRectBottomMedium else RectangleShape - val transferablePoolUnit = transferable.transferable as TransferableResource.PoolUnitAmount TransferablePoolUnitItemContent( - transferable = transferablePoolUnit, + transferable = transferable, shape = shape, onFungibleResourceClick = onFungibleResourceClick ) @@ -252,7 +252,7 @@ private fun TransferableItemContent( horizontalArrangement = Arrangement.spacedBy(RadixTheme.dimensions.paddingMedium) ) { when (val resource = transferable.transferable) { - is TransferableResource.Amount -> { + is TransferableResource.FungibleAmount -> { Thumbnail.Fungible( modifier = Modifier.size(44.dp), token = resource.resource, @@ -272,7 +272,7 @@ private fun TransferableItemContent( Text( modifier = Modifier.weight(1f), text = when (val resource = transferable.transferable) { - is TransferableResource.Amount -> resource.resource.displayTitle + is TransferableResource.FungibleAmount -> resource.resource.displayTitle is TransferableResource.NFTs -> resource.resource.name else -> "" }.ifEmpty { stringResource(id = R.string.transactionReview_unknown) }, @@ -281,59 +281,67 @@ private fun TransferableItemContent( maxLines = 1, overflow = TextOverflow.Ellipsis, ) - Column( - horizontalAlignment = Alignment.End + if (transferable.hasEditableGuarantees) { + GuaranteedQuantitySection(transferable) + } + } +} + +@Composable +private fun GuaranteedQuantitySection(transferable: Transferable, modifier: Modifier = Modifier) { + Column( + modifier = modifier, + horizontalAlignment = Alignment.End + ) { + val guaranteedQuantity = transferable.guaranteeAssertion as? GuaranteeAssertion.ForAmount + Row( + modifier = Modifier, + verticalAlignment = CenterVertically ) { - val guaranteedQuantity = transferable.guaranteeAssertion as? GuaranteeAssertion.ForAmount - Row( - modifier = Modifier, - verticalAlignment = CenterVertically - ) { - if (guaranteedQuantity != null) { - Text( - modifier = Modifier.padding(end = RadixTheme.dimensions.paddingSmall), - text = stringResource(id = R.string.transactionReview_estimated), - style = RadixTheme.typography.body2Link, - color = RadixTheme.colors.gray1, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - textAlign = TextAlign.End - ) - } + if (guaranteedQuantity != null) { + Text( + modifier = Modifier.padding(end = RadixTheme.dimensions.paddingSmall), + text = stringResource(id = R.string.transactionReview_estimated), + style = RadixTheme.typography.body2Link, + color = RadixTheme.colors.gray1, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + textAlign = TextAlign.End + ) + } - (transferable.transferable as? TransferableResource.Amount)?.let { - Text( - modifier = Modifier, - text = it.amount.displayableQuantity(), - style = RadixTheme.typography.secondaryHeader, - color = RadixTheme.colors.gray1, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - textAlign = TextAlign.End - ) - } + (transferable.transferable as? TransferableWithGuarantees)?.let { + Text( + modifier = Modifier, + text = it.amount.displayableQuantity(), + style = RadixTheme.typography.secondaryHeader, + color = RadixTheme.colors.gray1, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + textAlign = TextAlign.End + ) } - guaranteedQuantity?.let { quantity -> - Row { - Text( - modifier = Modifier.padding(end = RadixTheme.dimensions.paddingSmall), - text = stringResource(id = R.string.transactionReview_guaranteed), - style = RadixTheme.typography.body2Regular, - color = RadixTheme.colors.gray2, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - textAlign = TextAlign.End - ) - Text( - modifier = Modifier, - text = quantity.amount.displayableQuantity(), - style = RadixTheme.typography.body2HighImportance, - color = RadixTheme.colors.gray2, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - textAlign = TextAlign.End - ) - } + } + guaranteedQuantity?.let { quantity -> + Row { + Text( + modifier = Modifier.padding(end = RadixTheme.dimensions.paddingSmall), + text = stringResource(id = R.string.transactionReview_guaranteed), + style = RadixTheme.typography.body2Regular, + color = RadixTheme.colors.gray2, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + textAlign = TextAlign.End + ) + Text( + modifier = Modifier, + text = quantity.amount.displayableQuantity(), + style = RadixTheme.typography.body2HighImportance, + color = RadixTheme.colors.gray2, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + textAlign = TextAlign.End + ) } } } @@ -342,11 +350,12 @@ private fun TransferableItemContent( @Composable private fun TransferableLsuItemContent( modifier: Modifier = Modifier, - transferable: TransferableResource.LsuAmount, + transferable: Transferable, shape: Shape ) { - val lsu = remember(transferable) { - transferable.resource.asLsu() + val transferableLsu = transferable.transferable as TransferableResource.LsuAmount + val lsu = remember(transferableLsu) { + transferableLsu.resource.asLsu() } Column( modifier = modifier @@ -379,7 +388,7 @@ private fun TransferableLsuItemContent( overflow = TextOverflow.Ellipsis, ) Text( - text = transferable.validatorDetail.name, + text = transferableLsu.validatorDetail.name, style = RadixTheme.typography.body2Regular, color = RadixTheme.colors.gray2, maxLines = 1, @@ -421,13 +430,21 @@ private fun TransferableLsuItemContent( ) Text( modifier = Modifier.weight(1f), - text = transferable.xrdWorth.displayableQuantity(), + text = transferableLsu.xrdWorth.displayableQuantity(), style = RadixTheme.typography.secondaryHeader, color = RadixTheme.colors.gray1, textAlign = TextAlign.End, maxLines = 2 ) } + if (transferable.hasEditableGuarantees) { + GuaranteedQuantitySection( + transferable, + modifier = Modifier + .fillMaxWidth() + .padding(vertical = RadixTheme.dimensions.paddingMedium) + ) + } } } @@ -538,10 +555,11 @@ private fun TransferableStakeClaimNftItemContent( @Composable private fun TransferablePoolUnitItemContent( modifier: Modifier = Modifier, - transferable: TransferableResource.PoolUnitAmount, + transferable: Transferable, shape: Shape, onFungibleResourceClick: (fungibleResource: Resource.FungibleResource, Boolean) -> Unit ) { + val transferablePoolUnit = transferable.transferable as TransferableResource.PoolUnitAmount Column( modifier = modifier .height(IntrinsicSize.Min) @@ -561,19 +579,23 @@ private fun TransferablePoolUnitItemContent( ) { Thumbnail.PoolUnit( modifier = Modifier.size(44.dp), - poolUnit = transferable.pool + poolUnit = transferablePoolUnit.poolUnit ) Column(modifier = Modifier.weight(1f)) { Text( modifier = Modifier.fillMaxWidth(), - text = transferable.pool.stake.displayTitle.ifEmpty { stringResource(id = R.string.transactionReview_unknown) }, + text = transferablePoolUnit.poolUnit.stake.displayTitle.ifEmpty { + stringResource( + id = R.string.transactionReview_unknown + ) + }, style = RadixTheme.typography.body2HighImportance, color = RadixTheme.colors.gray1, maxLines = 1, overflow = TextOverflow.Ellipsis, ) Text( - text = transferable.pool.pool?.metadata?.name().orEmpty().ifEmpty { "Unknown pool" }, // TODO crowdin + text = transferablePoolUnit.poolUnit.pool?.metadata?.name().orEmpty().ifEmpty { "Unknown pool" }, // TODO crowdin style = RadixTheme.typography.body2Regular, color = RadixTheme.colors.gray2, maxLines = 1, @@ -591,7 +613,7 @@ private fun TransferablePoolUnitItemContent( color = RadixTheme.colors.gray2, maxLines = 1 ) - val poolResources = transferable.pool.pool?.resources.orEmpty() + val poolResources = transferablePoolUnit.poolUnit.pool?.resources.orEmpty() Column(modifier = Modifier.border(1.dp, RadixTheme.colors.gray3, shape = RadixTheme.shapes.roundedRectSmall)) { poolResources.forEachIndexed { index, item -> val addDivider = index != poolResources.lastIndex @@ -601,7 +623,7 @@ private fun TransferablePoolUnitItemContent( .clickable { onFungibleResourceClick( item, - transferable.isNewlyCreated + transferablePoolUnit.isNewlyCreated ) } .fillMaxWidth() @@ -621,7 +643,7 @@ private fun TransferablePoolUnitItemContent( ) Text( modifier = Modifier.weight(1f), - text = transferable.contributionPerResource[item.resourceAddress]?.displayableQuantity().orEmpty(), + text = transferablePoolUnit.contributionPerResource[item.resourceAddress]?.displayableQuantity().orEmpty(), style = RadixTheme.typography.secondaryHeader, color = RadixTheme.colors.gray1, textAlign = TextAlign.End, @@ -633,6 +655,14 @@ private fun TransferablePoolUnitItemContent( } } } + if (transferable.hasEditableGuarantees) { + GuaranteedQuantitySection( + transferable, + modifier = Modifier + .fillMaxWidth() + .padding(vertical = RadixTheme.dimensions.paddingMedium) + ) + } } } @@ -694,7 +724,7 @@ fun TransactionAccountCardPreview() { account = SampleDataProvider().sampleAccount(), resources = SampleDataProvider().sampleFungibleResources().map { Transferable.Withdrawing( - transferable = TransferableResource.Amount( + transferable = TransferableResource.FungibleAmount( amount = "689.203".toBigDecimal(), resource = it, isNewlyCreated = false diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/TransactionAccountWithGuaranteesCard.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/TransactionAccountWithGuaranteesCard.kt index a0b174dcaf..3a30f4d5cb 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/TransactionAccountWithGuaranteesCard.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/composables/TransactionAccountWithGuaranteesCard.kt @@ -109,14 +109,14 @@ fun TransactionAccountWithGuaranteesCard( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(RadixTheme.dimensions.paddingMedium) ) { - val transferrable = accountWithGuarantee.transferableAmount + val transferable = accountWithGuarantee.transferable Thumbnail.Fungible( modifier = Modifier.size(44.dp), - token = transferrable.resource + token = transferable.fungibleResource ) Text( modifier = Modifier.weight(1f), - text = transferrable.resource.displayTitle, + text = transferable.fungibleResource.displayTitle, style = RadixTheme.typography.body2HighImportance, color = RadixTheme.colors.gray1, maxLines = 1, @@ -140,7 +140,7 @@ fun TransactionAccountWithGuaranteesCard( ) Text( modifier = Modifier, - text = accountWithGuarantee.transferableAmount.amount.displayableQuantity(), + text = accountWithGuarantee.transferable.amount.displayableQuantity(), style = RadixTheme.typography.secondaryHeader, color = RadixTheme.colors.gray1, maxLines = 1, @@ -245,7 +245,7 @@ fun TransactionAccountWithGuaranteesCardPreview() { mutableStateOf( Owned( account = SampleDataProvider().sampleAccount(), - transferableAmount = TransferableResource.Amount( + transferable = TransferableResource.FungibleAmount( amount = BigDecimal.TEN, resource = SampleDataProvider().sampleFungibleResources()[0], isNewlyCreated = false diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/guarantees/TransactionGuaranteesDelegate.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/guarantees/TransactionGuaranteesDelegate.kt index 2bdff23aba..180d5e1d45 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/guarantees/TransactionGuaranteesDelegate.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/guarantees/TransactionGuaranteesDelegate.kt @@ -2,7 +2,7 @@ package com.babylon.wallet.android.presentation.transaction.guarantees import com.babylon.wallet.android.domain.model.GuaranteeType import com.babylon.wallet.android.domain.model.Transferable -import com.babylon.wallet.android.domain.model.TransferableResource +import com.babylon.wallet.android.domain.model.TransferableWithGuarantees import com.babylon.wallet.android.presentation.common.ViewModelDelegate import com.babylon.wallet.android.presentation.transaction.AccountWithPredictedGuarantee import com.babylon.wallet.android.presentation.transaction.AccountWithTransferableResources @@ -21,11 +21,11 @@ class TransactionGuaranteesDelegate @Inject constructor() : ViewModelDelegate() transaction.to.forEach { depositing -> val resourcesWithGuarantees = depositing.resources.filterIsInstance().filter { - it.guaranteeType is GuaranteeType.Predicted && it.transferable is TransferableResource.Amount + it.guaranteeType is GuaranteeType.Predicted && it.transferable is TransferableWithGuarantees } val predictedAmounts = resourcesWithGuarantees.associate { - it.transferable as TransferableResource.Amount to it.guaranteeType as GuaranteeType.Predicted + it.transferable as TransferableWithGuarantees to it.guaranteeType as GuaranteeType.Predicted } when (depositing) { is AccountWithTransferableResources.Other -> { @@ -33,7 +33,7 @@ class TransactionGuaranteesDelegate @Inject constructor() : ViewModelDelegate { + _state.update { + it.copy( + previewType = preview.copy( + to = preview.to.mapWhen( + predicate = { depositing -> + sheet.accountsWithPredictedGuarantees.any { it.address == depositing.address } + }, + mutation = { depositing -> + depositing.updateFromGuarantees(sheet.accountsWithPredictedGuarantees) + } + ) + ), + sheetState = Sheet.None + ) + } + } - _state.update { - it.copy( - previewType = preview.copy( - to = preview.to.mapWhen( - predicate = { depositing -> - sheet.accountsWithPredictedGuarantees.any { it.address == depositing.address } - }, - mutation = { depositing -> - depositing.updateFromGuarantees(sheet.accountsWithPredictedGuarantees) - } + is PreviewType.Transfer.Pool -> { + _state.update { + it.copy( + previewType = preview.copy( + to = preview.to.mapWhen( + predicate = { depositing -> + sheet.accountsWithPredictedGuarantees.any { it.address == depositing.address } + }, + mutation = { depositing -> + depositing.updateFromGuarantees(sheet.accountsWithPredictedGuarantees) + } + ) + ), + sheetState = Sheet.None ) - ), - sheetState = Sheet.None - ) + } + } + + is PreviewType.Transfer.Staking -> { + _state.update { + it.copy( + previewType = preview.copy( + to = preview.to.mapWhen( + predicate = { depositing -> + sheet.accountsWithPredictedGuarantees.any { it.address == depositing.address } + }, + mutation = { depositing -> + depositing.updateFromGuarantees(sheet.accountsWithPredictedGuarantees) + } + ) + ), + sheetState = Sheet.None + ) + } + } } } } From 87aedc32a492d6f46f17d7376b26a45736700345 Mon Sep 17 00:00:00 2001 From: Jakub Porzuczek Date: Tue, 16 Jan 2024 12:40:30 +0100 Subject: [PATCH 4/5] pr changes --- .../gateway/extensions/StateEntityDetailsApiHelper.kt | 8 ++++---- .../android/data/repository/cache/database/PoolEntity.kt | 4 ++-- .../babylon/wallet/android/domain/model/Transferable.kt | 5 ++++- .../domain/usecases/assets/GetPoolUnitDetailsUseCase.kt | 2 +- .../transaction/analysis/PoolContributionAnalysis.kt | 2 +- .../transaction/analysis/PoolRedemptionAnalysis.kt | 2 +- .../presentation/transaction/analysis/StakeAnalysis.kt | 2 +- .../transaction/analysis/StakeClaimAnalysis.kt | 2 +- .../presentation/transaction/analysis/UnstakeAnalysis.kt | 2 +- 9 files changed, 16 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/StateEntityDetailsApiHelper.kt b/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/StateEntityDetailsApiHelper.kt index a4892b1c56..232a35cd0c 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/StateEntityDetailsApiHelper.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/StateEntityDetailsApiHelper.kt @@ -86,7 +86,7 @@ suspend fun StateApi.fetchAccountGatewayDetails( suspend fun StateApi.fetchPools( poolAddresses: Set, stateVersion: Long -): List { +): List { if (poolAddresses.isEmpty()) return emptyList() val poolDetails = mutableMapOf() @@ -107,7 +107,7 @@ suspend fun StateApi.fetchPools( } } - val result = mutableListOf() + val result = mutableListOf() paginateDetails( addresses = resourceToPoolComponentAssociation.keys, // Request details for resources metadataKeys = ExplicitMetadataKey.forAssets, @@ -116,7 +116,7 @@ suspend fun StateApi.fetchPools( resourcesDetails.items.forEach { resourceDetails -> val poolAddress = resourceToPoolComponentAssociation[resourceDetails.address] poolDetails[poolAddress]?.let { poolDetails -> - result.add(FetchPoolsResult(poolDetails, resourceDetails, poolWithResources[poolAddress].orEmpty())) + result.add(PoolsResponse(poolDetails, resourceDetails, poolWithResources[poolAddress].orEmpty())) } } } @@ -124,7 +124,7 @@ suspend fun StateApi.fetchPools( return result } -data class FetchPoolsResult( +data class PoolsResponse( val poolDetails: StateEntityDetailsResponseItem, val poolUnitDetails: StateEntityDetailsResponseItem, val poolResourcesDetails: List diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/PoolEntity.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/PoolEntity.kt index dfe84ef6a1..14c6d87de5 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/PoolEntity.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/PoolEntity.kt @@ -5,7 +5,7 @@ import androidx.room.Entity import androidx.room.ForeignKey import androidx.room.Index import androidx.room.PrimaryKey -import com.babylon.wallet.android.data.gateway.extensions.FetchPoolsResult +import com.babylon.wallet.android.data.gateway.extensions.PoolsResponse import com.babylon.wallet.android.data.gateway.extensions.toMetadata import com.babylon.wallet.android.data.gateway.generated.models.StateEntityDetailsResponseItem import com.babylon.wallet.android.data.repository.cache.database.PoolResourceJoin.Companion.asPoolResourceJoin @@ -34,7 +34,7 @@ data class PoolEntity( companion object { @Suppress("UnsafeCallOnNullableType") - fun List.asPoolsResourcesJoin( + fun List.asPoolsResourcesJoin( syncInfo: SyncInfo ): List = mapNotNull { fetchedPoolDetails -> diff --git a/app/src/main/java/com/babylon/wallet/android/domain/model/Transferable.kt b/app/src/main/java/com/babylon/wallet/android/domain/model/Transferable.kt index bdb5088cd7..3b88bec20b 100644 --- a/app/src/main/java/com/babylon/wallet/android/domain/model/Transferable.kt +++ b/app/src/main/java/com/babylon/wallet/android/domain/model/Transferable.kt @@ -37,7 +37,10 @@ sealed interface Transferable { instructionIndex = predicted.instructionIndex ) - is TransferableResource.StakeClaimNft -> null + is TransferableResource.StakeClaimNft -> GuaranteeAssertion.ForNFT( + instructionIndex = predicted.instructionIndex + ) + is TransferableResource.PoolUnitAmount -> GuaranteeAssertion.ForAmount( amount = transferable.amount * predicted.guaranteeOffset.toBigDecimal(), instructionIndex = predicted.instructionIndex diff --git a/app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/GetPoolUnitDetailsUseCase.kt b/app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/GetPoolUnitDetailsUseCase.kt index b2c535338f..60021a72f0 100644 --- a/app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/GetPoolUnitDetailsUseCase.kt +++ b/app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/GetPoolUnitDetailsUseCase.kt @@ -23,7 +23,7 @@ class GetPoolUnitDetailsUseCase @Inject constructor( val poolAddress = poolResource.poolAddress ?: return@then runCatching { error("Resource $resourceAddress is not associated with a pool") } - stateRepository.getPools(setOf(poolAddress)).map { + stateRepository.getPools(setOf(poolAddress)).mapCatching { PoolUnit( stake = poolResource, pool = it.first() diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/PoolContributionAnalysis.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/PoolContributionAnalysis.kt index a528f09511..0837b7775a 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/PoolContributionAnalysis.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/PoolContributionAnalysis.kt @@ -23,7 +23,7 @@ suspend fun DetailedManifestClass.PoolContribution.resolve( getProfileUseCase: GetProfileUseCase, resources: List, involvedPools: List -): PreviewType { +): PreviewType.Transfer.Pool { val defaultDepositGuarantees = getProfileUseCase.invoke().first().appPreferences.transaction.defaultDepositGuarantee val accountsWithdrawnFrom = executionSummary.accountWithdraws.keys val ownedAccountsWithdrawnFrom = getProfileUseCase.accountsOnCurrentNetwork().filter { diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/PoolRedemptionAnalysis.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/PoolRedemptionAnalysis.kt index e2e7a02211..dab485aea6 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/PoolRedemptionAnalysis.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/PoolRedemptionAnalysis.kt @@ -20,7 +20,7 @@ suspend fun DetailedManifestClass.PoolRedemption.resolve( getProfileUseCase: GetProfileUseCase, resources: List, involvedPools: List -): PreviewType { +): PreviewType.Transfer.Pool { val accountsWithdrawnFrom = executionSummary.accountDeposits.keys val ownedAccountsWithdrawnFrom = getProfileUseCase.accountsOnCurrentNetwork().filter { accountsWithdrawnFrom.contains(it.address) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/StakeAnalysis.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/StakeAnalysis.kt index f4a90cecb1..c4d3dee1f7 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/StakeAnalysis.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/StakeAnalysis.kt @@ -18,7 +18,7 @@ suspend fun DetailedManifestClass.ValidatorStake.resolve( getProfileUseCase: GetProfileUseCase, resources: List, involvedValidators: List -): PreviewType { +): PreviewType.Transfer.Staking { val fromAccounts = extractWithdrawals(executionSummary, getProfileUseCase, resources) val toAccounts = extractDeposits( executionSummary = executionSummary, diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/StakeClaimAnalysis.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/StakeClaimAnalysis.kt index 7162af1dba..9c7a3312f8 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/StakeClaimAnalysis.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/StakeClaimAnalysis.kt @@ -20,7 +20,7 @@ suspend fun DetailedManifestClass.ValidatorClaim.resolve( resources: List, involvedValidators: List, stakeClaimsNfts: List -): PreviewType { +): PreviewType.Transfer.Staking { val toAccounts = extractDeposits(executionSummary, getProfileUseCase, resources) val fromAccounts = extractWithdrawals( executionSummary = executionSummary, diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/UnstakeAnalysis.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/UnstakeAnalysis.kt index 5741fb7f23..429dbaba8e 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/UnstakeAnalysis.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/UnstakeAnalysis.kt @@ -16,7 +16,7 @@ suspend fun DetailedManifestClass.ValidatorUnstake.resolve( getProfileUseCase: GetProfileUseCase, resources: List, involvedValidators: List -): PreviewType { +): PreviewType.Transfer.Staking { val fromAccounts = extractWithdrawals(executionSummary, getProfileUseCase, resources, involvedValidators) val toAccounts = extractDeposits(executionSummary, getProfileUseCase, resources, involvedValidators) val validatorAddressesSet = validatorAddresses.map { it.addressString() }.toSet() From 9a8bf7d92dab000bc64623ca5f5dbc6d71aa6175 Mon Sep 17 00:00:00 2001 From: Jakub Porzuczek Date: Wed, 17 Jan 2024 15:28:18 +0100 Subject: [PATCH 5/5] rebase fixes --- .../transaction/analysis/TransactionAnalysisDelegate.kt | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/TransactionAnalysisDelegate.kt b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/TransactionAnalysisDelegate.kt index 4e65e0dc39..f3dcec85dd 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/TransactionAnalysisDelegate.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/transaction/analysis/TransactionAnalysisDelegate.kt @@ -1,6 +1,5 @@ package com.babylon.wallet.android.presentation.transaction.analysis -import com.babylon.wallet.android.data.manifest.toPrettyString import com.babylon.wallet.android.data.transaction.NotaryAndSigners import com.babylon.wallet.android.data.transaction.TransactionClient import com.babylon.wallet.android.domain.RadixWalletException @@ -23,11 +22,9 @@ import com.babylon.wallet.android.presentation.transaction.guaranteesCount import com.radixdlt.ret.DetailedManifestClass import com.radixdlt.ret.ExecutionSummary import com.radixdlt.ret.TransactionManifest -import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.update import rdx.works.core.decodeHex import rdx.works.core.then -import rdx.works.profile.data.model.currentNetwork import rdx.works.profile.domain.GetProfileUseCase import rdx.works.profile.domain.currentNetwork import timber.log.Timber @@ -43,8 +40,7 @@ class TransactionAnalysisDelegate @Inject constructor( private val getTransactionBadgesUseCase: GetTransactionBadgesUseCase, private val getNFTDetailsUseCase: GetNFTDetailsUseCase, private val resolveDAppInTransactionUseCase: ResolveDAppInTransactionUseCase, - private val searchFeePayersUseCase: SearchFeePayersUseCase, - private val getPoolDetailsUseCase: GetPoolDetailsUseCase + private val getPoolDetailsUseCase: GetPoolDetailsUseCase, private val resolveNotaryAndSignersUseCase: ResolveNotaryAndSignersUseCase, private val searchFeePayersUseCase: SearchFeePayersUseCase ) : ViewModelDelegate() {