diff --git a/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/EntityMetadataCollectionExtensions.kt b/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/EntityMetadataCollectionExtensions.kt index ace2fbc168..c5fe1aa473 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/EntityMetadataCollectionExtensions.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/EntityMetadataCollectionExtensions.kt @@ -38,11 +38,6 @@ import com.babylon.wallet.android.data.gateway.generated.models.PublicKeyEcdsaSe import com.babylon.wallet.android.data.gateway.generated.models.PublicKeyEddsaEd25519 import com.babylon.wallet.android.data.gateway.generated.models.PublicKeyHashEcdsaSecp256k1 import com.babylon.wallet.android.data.gateway.generated.models.PublicKeyHashEddsaEd25519 -import com.radixdlt.sargon.NonFungibleGlobalId -import com.radixdlt.sargon.NonFungibleLocalId -import com.radixdlt.sargon.ResourceAddress -import com.radixdlt.sargon.extensions.init -import com.radixdlt.sargon.extensions.string import rdx.works.core.domain.resources.metadata.Metadata import rdx.works.core.domain.resources.metadata.MetadataType import rdx.works.core.domain.resources.metadata.MetadataType.Integer.Size @@ -56,8 +51,7 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) is MetadataBoolValue -> Metadata.Primitive( key = key, value = typed.value.toString(), - valueType = MetadataType.Bool, - isLocked = isLocked + valueType = MetadataType.Bool ) is MetadataBoolArrayValue -> Metadata.Collection( @@ -66,18 +60,15 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) Metadata.Primitive( key = key, value = it.toString(), - valueType = MetadataType.Bool, - isLocked = isLocked + valueType = MetadataType.Bool ) - }, - isLocked = isLocked + } ) is MetadataDecimalValue -> Metadata.Primitive( key = key, value = typed.value, - valueType = MetadataType.Decimal, - isLocked = isLocked + valueType = MetadataType.Decimal ) is MetadataDecimalArrayValue -> Metadata.Collection( @@ -88,15 +79,13 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) value = it, valueType = MetadataType.Decimal ) - }, - isLocked = isLocked + } ) is MetadataGlobalAddressValue -> Metadata.Primitive( key = key, value = typed.value, - valueType = MetadataType.Address, - isLocked = isLocked + valueType = MetadataType.Address ) is MetadataGlobalAddressArrayValue -> Metadata.Collection( @@ -105,18 +94,15 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) Metadata.Primitive( key = key, value = it, - valueType = MetadataType.Address, - isLocked = isLocked + valueType = MetadataType.Address ) }, - isLocked = isLocked ) is MetadataI32Value -> Metadata.Primitive( key = key, value = typed.value, - valueType = MetadataType.Integer(signed = true, size = Size.INT), - isLocked = isLocked + valueType = MetadataType.Integer(signed = true, size = Size.INT) ) is MetadataI32ArrayValue -> Metadata.Collection( @@ -125,18 +111,15 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) Metadata.Primitive( key = key, value = it, - valueType = MetadataType.Integer(signed = true, size = Size.INT), - isLocked = isLocked + valueType = MetadataType.Integer(signed = true, size = Size.INT) ) - }, - isLocked = isLocked + } ) is MetadataI64Value -> Metadata.Primitive( key = key, value = typed.value, - valueType = MetadataType.Integer(signed = true, size = Size.LONG), - isLocked = isLocked + valueType = MetadataType.Integer(signed = true, size = Size.LONG) ) is MetadataI64ArrayValue -> Metadata.Collection( @@ -145,32 +128,27 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) Metadata.Primitive( key = key, value = it, - valueType = MetadataType.Integer(signed = true, size = Size.LONG), - isLocked = isLocked + valueType = MetadataType.Integer(signed = true, size = Size.LONG) ) - }, - isLocked = isLocked + } ) is MetadataU8Value -> Metadata.Primitive( key = key, value = typed.value, - valueType = MetadataType.Integer(signed = false, size = Size.INT), - isLocked = isLocked + valueType = MetadataType.Integer(signed = false, size = Size.INT) ) is MetadataU8ArrayValue -> Metadata.Primitive( key = key, value = typed.valueHex, - valueType = MetadataType.Bytes, - isLocked = isLocked + valueType = MetadataType.Bytes ) is MetadataU32Value -> Metadata.Primitive( key = key, value = typed.value, - valueType = MetadataType.Integer(signed = false, size = Size.INT), - isLocked = isLocked + valueType = MetadataType.Integer(signed = false, size = Size.INT) ) is MetadataU32ArrayValue -> Metadata.Collection( @@ -179,18 +157,15 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) Metadata.Primitive( key = key, value = it, - valueType = MetadataType.Integer(signed = false, size = Size.INT), - isLocked = isLocked + valueType = MetadataType.Integer(signed = false, size = Size.INT) ) - }, - isLocked = isLocked + } ) is MetadataU64Value -> Metadata.Primitive( key = key, value = typed.value, - valueType = MetadataType.Integer(signed = false, size = Size.LONG), - isLocked = isLocked + valueType = MetadataType.Integer(signed = false, size = Size.LONG) ) is MetadataU64ArrayValue -> Metadata.Collection( @@ -199,18 +174,15 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) Metadata.Primitive( key = key, value = it, - valueType = MetadataType.Integer(signed = false, size = Size.LONG), - isLocked = isLocked + valueType = MetadataType.Integer(signed = false, size = Size.LONG) ) }, - isLocked = isLocked ) is MetadataInstantValue -> Metadata.Primitive( key = key, - value = typed.unixTimestampSeconds, - valueType = MetadataType.Instant, - isLocked = isLocked + value = typed.value, + valueType = MetadataType.Instant ) is MetadataInstantArrayValue -> Metadata.Collection( @@ -219,21 +191,15 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) Metadata.Primitive( key = key, value = it, - valueType = MetadataType.Instant, - isLocked = isLocked + valueType = MetadataType.Instant ) - }, - isLocked = isLocked + } ) is MetadataNonFungibleGlobalIdValue -> Metadata.Primitive( key = key, - value = NonFungibleGlobalId( - resourceAddress = ResourceAddress.init(typed.resourceAddress), - nonFungibleLocalId = NonFungibleLocalId.init(typed.nonFungibleId) - ).string, - valueType = MetadataType.NonFungibleGlobalId, - isLocked = isLocked + value = "${typed.resourceAddress}:${typed.nonFungibleId}", + valueType = MetadataType.NonFungibleGlobalId ) is MetadataNonFungibleGlobalIdArrayValue -> Metadata.Collection( @@ -241,23 +207,17 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) values = typed.propertyValues.map { Metadata.Primitive( key = key, - value = NonFungibleGlobalId( - resourceAddress = ResourceAddress.init(it.resourceAddress), - nonFungibleLocalId = NonFungibleLocalId.init(it.nonFungibleId) - ).string, - valueType = MetadataType.NonFungibleGlobalId, - isLocked = isLocked + value = "${it.resourceAddress}:${it.nonFungibleId}", + valueType = MetadataType.NonFungibleGlobalId ) - }, - isLocked = isLocked + } ) is MetadataNonFungibleLocalIdValue -> Metadata.Primitive( key = key, lastUpdatedAtStateVersion = lastUpdatedAtStateVersion, value = typed.value, - valueType = MetadataType.NonFungibleLocalId, - isLocked = isLocked + valueType = MetadataType.NonFungibleLocalId ) is MetadataNonFungibleLocalIdArrayValue -> Metadata.Collection( @@ -266,18 +226,15 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) Metadata.Primitive( key = key, value = it, - valueType = MetadataType.NonFungibleLocalId, - isLocked = isLocked + valueType = MetadataType.NonFungibleLocalId ) - }, - isLocked = isLocked + } ) is MetadataOriginValue -> Metadata.Primitive( key = key, value = typed.value, - valueType = MetadataType.Url, - isLocked = isLocked + valueType = MetadataType.Url ) is MetadataOriginArrayValue -> Metadata.Collection( @@ -286,18 +243,15 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) Metadata.Primitive( key = key, value = it, - valueType = MetadataType.Url, - isLocked = isLocked + valueType = MetadataType.Url ) - }, - isLocked = isLocked + } ) is MetadataStringValue -> Metadata.Primitive( key = key, value = typed.value, - valueType = MetadataType.String, - isLocked = isLocked + valueType = MetadataType.String ) is MetadataStringArrayValue -> Metadata.Collection( @@ -306,18 +260,15 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) Metadata.Primitive( key = key, value = it, - valueType = MetadataType.String, - isLocked = isLocked + valueType = MetadataType.String ) - }, - isLocked = isLocked + } ) is MetadataUrlValue -> Metadata.Primitive( key = key, value = typed.value, - valueType = MetadataType.Url, - isLocked = isLocked + valueType = MetadataType.Url ) is MetadataUrlArrayValue -> Metadata.Collection( @@ -326,11 +277,9 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) Metadata.Primitive( key = key, value = it, - valueType = MetadataType.Url, - isLocked = isLocked + valueType = MetadataType.Url ) - }, - isLocked = isLocked + } ) is MetadataPublicKeyValue -> when (typed.value) { @@ -338,16 +287,14 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) key = key, lastUpdatedAtStateVersion = lastUpdatedAtStateVersion, value = typed.value.keyHex, - valueType = MetadataType.PublicKeyEcdsaSecp256k1, - isLocked = isLocked + valueType = MetadataType.PublicKeyEcdsaSecp256k1 ) is PublicKeyEddsaEd25519 -> Metadata.Primitive( key = key, lastUpdatedAtStateVersion = lastUpdatedAtStateVersion, value = typed.value.keyHex, - valueType = MetadataType.PublicKeyEddsaEd25519, - isLocked = isLocked + valueType = MetadataType.PublicKeyEddsaEd25519 ) else -> error("Not supported MetadataPublicKeyValue type for $value") @@ -361,21 +308,18 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) is PublicKeyEcdsaSecp256k1 -> Metadata.Primitive( key = key, value = value.keyHex, - valueType = MetadataType.PublicKeyEcdsaSecp256k1, - isLocked = isLocked + valueType = MetadataType.PublicKeyEcdsaSecp256k1 ) is PublicKeyEddsaEd25519 -> Metadata.Primitive( key = key, value = value.keyHex, - valueType = MetadataType.PublicKeyEddsaEd25519, - isLocked = isLocked + valueType = MetadataType.PublicKeyEddsaEd25519 ) else -> error("Not supported MetadataPublicKeyValue type for $value") } - }, - isLocked = isLocked + } ) is MetadataPublicKeyHashValue -> when (typed.value) { @@ -383,16 +327,14 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) key = key, lastUpdatedAtStateVersion = lastUpdatedAtStateVersion, value = typed.value.hashHex, - valueType = MetadataType.PublicKeyHashEcdsaSecp256k1, - isLocked = isLocked + valueType = MetadataType.PublicKeyHashEcdsaSecp256k1 ) is PublicKeyHashEddsaEd25519 -> Metadata.Primitive( key = key, lastUpdatedAtStateVersion = lastUpdatedAtStateVersion, value = typed.value.hashHex, - valueType = MetadataType.PublicKeyHashEddsaEd25519, - isLocked = isLocked + valueType = MetadataType.PublicKeyHashEddsaEd25519 ) } @@ -405,20 +347,17 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) key = key, lastUpdatedAtStateVersion = lastUpdatedAtStateVersion, value = value.hashHex, - valueType = MetadataType.PublicKeyHashEcdsaSecp256k1, - isLocked = isLocked + valueType = MetadataType.PublicKeyHashEcdsaSecp256k1 ) is PublicKeyHashEddsaEd25519 -> Metadata.Primitive( key = key, lastUpdatedAtStateVersion = lastUpdatedAtStateVersion, value = value.hashHex, - valueType = MetadataType.PublicKeyHashEddsaEd25519, - isLocked = isLocked + valueType = MetadataType.PublicKeyHashEddsaEd25519 ) } - }, - isLocked = isLocked + } ) else -> null 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 9aeb9cb261..fe138a4042 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 @@ -1,7 +1,6 @@ package com.babylon.wallet.android.data.gateway.extensions import com.babylon.wallet.android.data.gateway.apis.StateApi -import com.babylon.wallet.android.data.gateway.generated.models.EntityMetadataItem import com.babylon.wallet.android.data.gateway.generated.models.FungibleResourcesCollection import com.babylon.wallet.android.data.gateway.generated.models.FungibleResourcesCollectionItem import com.babylon.wallet.android.data.gateway.generated.models.LedgerState @@ -16,7 +15,6 @@ import com.babylon.wallet.android.data.gateway.generated.models.StateEntityDetai import com.babylon.wallet.android.data.gateway.generated.models.StateEntityDetailsResponseItem import com.babylon.wallet.android.data.gateway.generated.models.StateEntityFungiblesPageRequest import com.babylon.wallet.android.data.gateway.generated.models.StateEntityFungiblesPageRequestOptIns -import com.babylon.wallet.android.data.gateway.generated.models.StateEntityMetadataPageRequest import com.babylon.wallet.android.data.gateway.generated.models.StateEntityNonFungibleIdsPageRequest import com.babylon.wallet.android.data.gateway.generated.models.StateEntityNonFungiblesPageRequest import com.babylon.wallet.android.data.gateway.generated.models.StateEntityNonFungiblesPageRequestOptIns @@ -388,28 +386,3 @@ suspend fun StateApi.paginateNonFungibles( onPage(response) } } - -suspend fun StateApi.getAllMetadata( - resourceAddress: ResourceAddress, - stateVersion: Long, - initialCursor: String -): List { - val items = mutableListOf() - - var cursor: String? = initialCursor - while (cursor != null) { - val page = entityMetadataPage( - stateEntityMetadataPageRequest = StateEntityMetadataPageRequest( - address = resourceAddress.string, - cursor = initialCursor, - atLedgerState = LedgerStateSelector( - stateVersion = stateVersion - ) - ) - ).toResult().getOrThrow() - cursor = page.nextCursor - items.addAll(page.items) - } - - return items -} diff --git a/app/src/main/java/com/babylon/wallet/android/data/gateway/serialisers/MetadataTypedValueSerializer.kt b/app/src/main/java/com/babylon/wallet/android/data/gateway/serialisers/MetadataTypedValueSerializer.kt index ec339650af..366ef32224 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/gateway/serialisers/MetadataTypedValueSerializer.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/gateway/serialisers/MetadataTypedValueSerializer.kt @@ -25,7 +25,6 @@ import com.babylon.wallet.android.data.gateway.generated.models.MetadataPublicKe import com.babylon.wallet.android.data.gateway.generated.models.MetadataStringArrayValue import com.babylon.wallet.android.data.gateway.generated.models.MetadataStringValue import com.babylon.wallet.android.data.gateway.generated.models.MetadataTypedValue -import com.babylon.wallet.android.data.gateway.generated.models.MetadataU32ArrayValue import com.babylon.wallet.android.data.gateway.generated.models.MetadataU32Value import com.babylon.wallet.android.data.gateway.generated.models.MetadataU64ArrayValue import com.babylon.wallet.android.data.gateway.generated.models.MetadataU64Value @@ -63,7 +62,7 @@ object MetadataTypedValueSerializer : JsonContentPolymorphicSerializer MetadataStringArrayValue.serializer() MetadataValueType.BoolArray -> MetadataBoolArrayValue.serializer() MetadataValueType.U8Array -> MetadataU8ArrayValue.serializer() - MetadataValueType.U32Array -> MetadataU32ArrayValue.serializer() + MetadataValueType.U32Array -> MetadataU32Value.serializer() MetadataValueType.U64Array -> MetadataU64ArrayValue.serializer() MetadataValueType.I32Array -> MetadataI32ArrayValue.serializer() MetadataValueType.I64Array -> MetadataI64ArrayValue.serializer() diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/DAppEntity.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/DAppEntity.kt index b6ded0778b..b7b18fa74e 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/DAppEntity.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/DAppEntity.kt @@ -3,6 +3,7 @@ package com.babylon.wallet.android.data.repository.cache.database import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.PrimaryKey +import com.babylon.wallet.android.data.gateway.extensions.toMetadata import com.babylon.wallet.android.data.gateway.generated.models.StateEntityDetailsResponseItem import com.radixdlt.sargon.AccountAddress import com.radixdlt.sargon.extensions.init @@ -26,10 +27,7 @@ data class DAppEntity( companion object { fun from(item: StateEntityDetailsResponseItem, syncedAt: Instant) = DAppEntity( definitionAddress = AccountAddress.init(item.address), - metadata = MetadataColumn.from( - explicitMetadata = item.explicitMetadata, - implicitMetadata = item.metadata - ), + metadata = item.explicitMetadata?.toMetadata()?.let { MetadataColumn(it) }, synced = syncedAt ) } diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/NFTEntity.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/NFTEntity.kt index e1692d3cab..ac89cc3324 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/NFTEntity.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/NFTEntity.kt @@ -37,7 +37,7 @@ data class NFTEntity( metadata = toMetadata().takeIf { it.isNotEmpty() }?.let { - MetadataColumn(metadata = it, implicitState = MetadataColumn.ImplicitMetadataState.Complete) + MetadataColumn(it) }, synced = synced ) @@ -49,7 +49,7 @@ data class NFTEntity( metadata = metadata.takeIf { it.isNotEmpty() }?.let { - MetadataColumn(metadata = it, implicitState = MetadataColumn.ImplicitMetadataState.Complete) + MetadataColumn(it) }, synced = synced ) 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 972e4de6f1..e69bdde5ce 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 @@ -6,6 +6,7 @@ import androidx.room.ForeignKey import androidx.room.Index import androidx.room.PrimaryKey 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 import com.babylon.wallet.android.data.repository.cache.database.ResourceEntity.Companion.asEntity @@ -59,14 +60,11 @@ data class PoolEntity( } fun StateEntityDetailsResponseItem.asPoolEntity(): PoolEntity? { - val metadataColumn = MetadataColumn.from( - explicitMetadata = explicitMetadata, - implicitMetadata = metadata - ) - val poolUnitResourceAddress = metadataColumn.metadata.poolUnit() ?: return null + val metadata = this.metadata.toMetadata() + val poolUnitResourceAddress = metadata.poolUnit() ?: return null return PoolEntity( address = PoolAddress.init(address), - metadata = metadataColumn, + metadata = MetadataColumn(metadata), resourceAddress = poolUnitResourceAddress ) } diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ProvidedConverters.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ProvidedConverters.kt index bffd706390..9981253788 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ProvidedConverters.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ProvidedConverters.kt @@ -2,9 +2,6 @@ package com.babylon.wallet.android.data.repository.cache.database import androidx.room.ProvidedTypeConverter import androidx.room.TypeConverter -import com.babylon.wallet.android.data.gateway.extensions.toMetadata -import com.babylon.wallet.android.data.gateway.generated.models.EntityMetadataCollection -import com.babylon.wallet.android.data.repository.cache.database.MetadataColumn.ImplicitMetadataState import com.radixdlt.sargon.AccountAddress import com.radixdlt.sargon.Decimal192 import com.radixdlt.sargon.NonFungibleLocalId @@ -15,7 +12,6 @@ import com.radixdlt.sargon.VaultAddress import com.radixdlt.sargon.extensions.init import com.radixdlt.sargon.extensions.string import com.radixdlt.sargon.extensions.toDecimal192OrNull -import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json @@ -28,75 +24,7 @@ import java.time.Instant data class BehavioursColumn(val behaviours: Set) @Serializable -data class MetadataColumn( - /** - * A union of explicit and **currently known** implicit metadata - * As a client we don't need to expose the difference between explicit - * and implicit metadata. - */ - val metadata: List, - - /** - * The state of the next page of the implicit metadata. See [ImplicitMetadataState] - */ - @SerialName("implicit_state") - val implicitState: ImplicitMetadataState -) { - - val nextCursor: String? - get() = (implicitState as? ImplicitMetadataState.Incomplete)?.nextCursor - - @Serializable - sealed interface ImplicitMetadataState { - /** - * When we have no information yet regarding the existence of implicit metadata - * An example is when we query account information. In this request we receive - * resource data but with no information about implicit metadata. In order to make - * sure we received all metadata available we need to fetch details of this specific - * resource - */ - @Serializable - @SerialName("unknown") - data object Unknown : ImplicitMetadataState - - /** - * We have received an answer from a details request and we know that the [MetadataColumn.metadata] - * are complete. - */ - @Serializable - @SerialName("complete") - data object Complete : ImplicitMetadataState - - /** - * We have received an answer from a details request and we know that the [MetadataColumn.metadata] - * are incomplete. We need to query [nextCursor] to receive more. - */ - @Serializable - @SerialName("incomplete") - data class Incomplete( - @SerialName("next_cursor") - val nextCursor: String - ) : ImplicitMetadataState - } - - companion object { - fun from( - explicitMetadata: EntityMetadataCollection?, - implicitMetadata: EntityMetadataCollection - ): MetadataColumn { - val explicit = explicitMetadata?.toMetadata().orEmpty().toSet() - val implicit = implicitMetadata.toMetadata().toSet() - - val all = explicit union implicit - return MetadataColumn( - metadata = all.toList(), - implicitState = implicitMetadata.nextCursor?.let { - ImplicitMetadataState.Incomplete(nextCursor = it) - } ?: ImplicitMetadataState.Complete - ) - } - } -} +data class MetadataColumn(val metadata: List) @Suppress("TooManyFunctions") @ProvidedTypeConverter @@ -109,23 +37,23 @@ class StateDatabaseConverters { // Behaviours @TypeConverter fun stringToBehaviours(string: String?): BehavioursColumn? { - return string?.let { json.decodeFromString(string) } + return string?.let { BehavioursColumn(behaviours = json.decodeFromString(string)) } } @TypeConverter fun behavioursToString(column: BehavioursColumn?): String? { - return column?.let { json.encodeToString(it) } + return column?.let { json.encodeToString(it.behaviours) } } // Metadata @TypeConverter fun stringToMetadata(string: String?): MetadataColumn? { - return string?.let { json.decodeFromString(string) } + return string?.let { MetadataColumn(metadata = json.decodeFromString(string)) } } @TypeConverter fun metadataToString(column: MetadataColumn?): String? { - return column?.let { json.encodeToString(it) } + return column?.let { json.encodeToString(it.metadata) } } // Decimal192 diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ResourceEntity.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ResourceEntity.kt index 214ce47aae..cf7f2625a8 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ResourceEntity.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ResourceEntity.kt @@ -22,7 +22,10 @@ import com.radixdlt.sargon.extensions.init import com.radixdlt.sargon.extensions.string import com.radixdlt.sargon.extensions.toDecimal192 import rdx.works.core.domain.resources.Divisibility +import rdx.works.core.domain.resources.ExplicitMetadataKey import rdx.works.core.domain.resources.Resource +import rdx.works.core.domain.resources.metadata.Metadata +import rdx.works.core.domain.resources.metadata.MetadataType import rdx.works.core.domain.resources.metadata.poolAddress import rdx.works.core.domain.resources.metadata.validatorAddress import java.time.Instant @@ -47,14 +50,17 @@ data class ResourceEntity( val synced: Instant ) { - val isDetailsAvailable: Boolean - get() = when (type) { - ResourceEntityType.FUNGIBLE -> supply != null && divisibility != null && behaviours != null - ResourceEntityType.NON_FUNGIBLE -> supply != null && behaviours != null - } - @Suppress("CyclomaticComplexMethod") fun toResource(amount: Decimal192?): Resource { + val validatorAndPoolMetadata = listOf( + validatorAddress?.let { + Metadata.Primitive(ExplicitMetadataKey.VALIDATOR.key, it.string, MetadataType.Address) + }, + poolAddress?.let { + Metadata.Primitive(ExplicitMetadataKey.POOL.key, it.string, MetadataType.Address) + } + ).mapNotNull { it } + return when (type) { ResourceEntityType.FUNGIBLE -> { Resource.FungibleResource( @@ -63,7 +69,7 @@ data class ResourceEntity( assetBehaviours = behaviours?.behaviours?.toSet(), currentSupply = supply, divisibility = divisibility, - metadata = metadata?.metadata.orEmpty() + metadata = metadata?.metadata.orEmpty() + validatorAndPoolMetadata ) } @@ -74,7 +80,7 @@ data class ResourceEntity( assetBehaviours = behaviours?.behaviours?.toSet(), items = emptyList(), currentSupply = supply?.string?.toIntOrNull(), - metadata = metadata?.metadata.orEmpty() + metadata = metadata?.metadata.orEmpty() + validatorAndPoolMetadata ) } } @@ -91,8 +97,9 @@ data class ResourceEntity( validatorAddress = metadata.validatorAddress(), poolAddress = metadata.poolAddress(), metadata = metadata + .filterNot { it.key in setOf(ExplicitMetadataKey.POOL.key, ExplicitMetadataKey.VALIDATOR.key) } .takeIf { it.isNotEmpty() } - ?.let { MetadataColumn(it, MetadataColumn.ImplicitMetadataState.Unknown) }, + ?.let { MetadataColumn(it) }, synced = synced ) @@ -105,8 +112,9 @@ data class ResourceEntity( validatorAddress = metadata.validatorAddress(), poolAddress = metadata.poolAddress(), metadata = metadata + .filterNot { it.key in setOf(ExplicitMetadataKey.POOL.key, ExplicitMetadataKey.VALIDATOR.key) } .takeIf { it.isNotEmpty() } - ?.let { MetadataColumn(it, MetadataColumn.ImplicitMetadataState.Unknown) }, + ?.let { MetadataColumn(it) }, synced = synced ) } @@ -118,8 +126,7 @@ data class ResourceEntity( details: StateEntityDetailsResponseItemDetails? = null ): ResourceEntity = from( address = ResourceAddress.init(resourceAddress), - explicitMetadata = explicitMetadata, - implicitMetadata = null, + metadataCollection = explicitMetadata, details = details, type = ResourceEntityType.FUNGIBLE, synced = synced @@ -132,8 +139,7 @@ data class ResourceEntity( details: StateEntityDetailsResponseItemDetails? = null ): ResourceEntity = from( address = ResourceAddress.init(resourceAddress), - explicitMetadata = explicitMetadata, - implicitMetadata = null, + metadataCollection = explicitMetadata, details = details, type = ResourceEntityType.NON_FUNGIBLE, synced = synced @@ -150,44 +156,33 @@ data class ResourceEntity( } return from( address = ResourceAddress.init(address), - explicitMetadata = explicitMetadata, - implicitMetadata = metadata, + metadataCollection = metadata, details = details, type = type, synced = synced ) } - @Suppress("LongParameterList") private fun from( address: ResourceAddress, - explicitMetadata: EntityMetadataCollection?, - implicitMetadata: EntityMetadataCollection?, + metadataCollection: EntityMetadataCollection?, details: StateEntityDetailsResponseItemDetails?, type: ResourceEntityType, synced: Instant ): ResourceEntity { - val metadataColumn = if (implicitMetadata != null) { - MetadataColumn.from( - explicitMetadata = explicitMetadata, - implicitMetadata = implicitMetadata - ) - } else { - MetadataColumn( - metadata = explicitMetadata?.toMetadata().orEmpty(), - implicitState = MetadataColumn.ImplicitMetadataState.Unknown - ) - }.takeIf { it.metadata.isNotEmpty() } - + val metadata = metadataCollection?.toMetadata().orEmpty() return ResourceEntity( address = address, type = type, divisibility = details?.divisibility(), behaviours = details?.let { BehavioursColumn(it.extractBehaviours()) }, supply = details?.totalSupply(), - validatorAddress = metadataColumn?.metadata?.validatorAddress(), - poolAddress = metadataColumn?.metadata?.poolAddress(), - metadata = metadataColumn, + validatorAddress = metadata.validatorAddress(), + poolAddress = metadata.poolAddress(), + metadata = metadata + .filterNot { it.key in setOf(ExplicitMetadataKey.VALIDATOR.key, ExplicitMetadataKey.POOL.key) } + .takeIf { it.isNotEmpty() } + ?.let { MetadataColumn(it) }, synced = synced ) } 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 04f596388d..2156845bdc 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 @@ -324,15 +324,6 @@ interface StateDao { @Insert(onConflict = OnConflictStrategy.REPLACE) fun insertDApps(dApps: List) - @Query( - """ - UPDATE ResourceEntity SET - metadata = :metadataColumn - WHERE address = :resourceAddress - """ - ) - fun updateMetadata(resourceAddress: ResourceAddress, metadataColumn: MetadataColumn) - companion object { val deleteDuration = 1.toDuration(DurationUnit.SECONDS) private val accountsCacheDuration = 2.toDuration(DurationUnit.HOURS) 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 98acbfa299..90ef12b87d 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 @@ -20,7 +20,7 @@ import androidx.room.TypeConverters PoolDAppJoin::class, TokenPriceEntity::class ], - version = StateDatabase.VERSION_9 + version = StateDatabase.VERSION_8 ) @TypeConverters(StateDatabaseConverters::class) abstract class StateDatabase : RoomDatabase() { @@ -51,12 +51,9 @@ abstract class StateDatabase : RoomDatabase() { @Deprecated("Add TokenPriceEntity to schema") const val VERSION_7 = 7 - @Deprecated("Replace BigDecimal with Decimal192") + // Replace BigDecimal with Decimal192 const val VERSION_8 = 8 - // Added next cursor to metadata column and locked flag - const val VERSION_9 = 9 - 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/ValidatorEntity.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ValidatorEntity.kt index 8c67d5d5c5..d48548e363 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ValidatorEntity.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ValidatorEntity.kt @@ -5,6 +5,7 @@ import androidx.room.Entity import androidx.room.PrimaryKey import com.babylon.wallet.android.data.gateway.extensions.claimTokenResourceAddress import com.babylon.wallet.android.data.gateway.extensions.stakeUnitResourceAddress +import com.babylon.wallet.android.data.gateway.extensions.toMetadata import com.babylon.wallet.android.data.gateway.extensions.totalXRDStake import com.babylon.wallet.android.data.gateway.generated.models.StateEntityDetailsResponseItem import com.radixdlt.sargon.Decimal192 @@ -37,16 +38,28 @@ data class ValidatorEntity( ) companion object { - fun StateEntityDetailsResponseItem.asValidatorEntity(syncInfo: SyncInfo) = ValidatorEntity( - address = ValidatorAddress.init(address), - stakeUnitResourceAddress = details?.stakeUnitResourceAddress?.let { ResourceAddress.init(it) }, - claimTokenResourceAddress = details?.claimTokenResourceAddress?.let { ResourceAddress.init(it) }, - totalStake = totalXRDStake, - metadata = MetadataColumn.from( - explicitMetadata = explicitMetadata, - implicitMetadata = metadata - ), + fun Validator.asValidatorEntity(syncInfo: SyncInfo) = ValidatorEntity( + address = address, + stakeUnitResourceAddress = stakeUnitResourceAddress, + claimTokenResourceAddress = claimTokenResourceAddress, + totalStake = totalXrdStake, + metadata = metadata.takeIf { it.isNotEmpty() }?.let { MetadataColumn(it) }, stateVersion = syncInfo.accountStateVersion ) + + fun List.asValidators() = map { item -> + val metadata = item.explicitMetadata?.toMetadata().orEmpty() + Validator( + address = ValidatorAddress.init(item.address), + totalXrdStake = item.totalXRDStake, + stakeUnitResourceAddress = item.details?.stakeUnitResourceAddress?.let { ResourceAddress.init(it) }, + claimTokenResourceAddress = item.details?.claimTokenResourceAddress?.let { ResourceAddress.init(it) }, + metadata = metadata + ) + } + + fun List.asValidatorEntities(syncInfo: SyncInfo) = map { item -> + item.asValidatorEntity(syncInfo) + } } } 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 ff628ce264..f07d9ac0ce 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 @@ -11,7 +11,8 @@ import com.babylon.wallet.android.data.repository.cache.database.StateDao import com.babylon.wallet.android.data.repository.cache.database.StateDao.Companion.accountCacheValidity import com.babylon.wallet.android.data.repository.cache.database.StateDatabase import com.babylon.wallet.android.data.repository.cache.database.SyncInfo -import com.babylon.wallet.android.data.repository.cache.database.ValidatorEntity.Companion.asValidatorEntity +import com.babylon.wallet.android.data.repository.cache.database.ValidatorEntity.Companion.asValidatorEntities +import com.babylon.wallet.android.data.repository.cache.database.ValidatorEntity.Companion.asValidators import com.babylon.wallet.android.data.repository.cache.database.getCachedPools import com.babylon.wallet.android.data.repository.cache.database.getCachedValidators import com.babylon.wallet.android.di.coroutines.ApplicationScope @@ -233,47 +234,57 @@ class AccountsStateCache @Inject constructor( result } - private fun Flow>.compileAccountAddressAssets() = transform { cached -> - val stateVersion = cached.values.mapNotNull { it.stateVersion }.maxOrNull() ?: run { - emit(emptyList()) - return@transform - } - - val allValidatorAddresses = cached.map { it.value.validatorAddresses() }.flatten().toSet() - val cachedValidators = dao.getCachedValidators(allValidatorAddresses, stateVersion).toMutableMap() - val newValidators = runCatching { - val validatorItems = api.fetchValidators( - allValidatorAddresses - cachedValidators.keys, - stateVersion - ).validators - - val syncInfo = SyncInfo(InstantGenerator(), stateVersion) - validatorItems.map { - it.asValidatorEntity(syncInfo) - }.onEach { entity -> - cachedValidators[entity.address] = entity.asValidatorDetail() + private fun Flow>.compileAccountAddressAssets(): Flow> = + transform { cached -> + val stateVersion = cached.values.mapNotNull { it.stateVersion }.maxOrNull() ?: run { + emit(emptyList()) + return@transform } - }.onFailure { cacheErrors.value = it }.getOrNull() ?: return@transform - - if (newValidators.isNotEmpty()) { - logger.d("\uD83D\uDCBD Inserting validators") - dao.insertValidators(newValidators) - } - val allPoolAddresses = cached.map { it.value.poolAddresses() }.flatten().toSet() - val cachedPools = dao.getCachedPools(allPoolAddresses, stateVersion).toMutableMap() - val unknownPools = allPoolAddresses - cachedPools.keys - if (unknownPools.isNotEmpty()) { - logger.d("\uD83D\uDCBD Inserting pools") - val newPools = runCatching { - api.fetchPools(unknownPools.toSet(), stateVersion) + val allValidatorAddresses = cached.map { it.value.validatorAddresses() }.flatten().toSet() + val cachedValidators = dao.getCachedValidators(allValidatorAddresses, stateVersion).toMutableMap() + val newValidators = runCatching { + api.fetchValidators( + allValidatorAddresses - cachedValidators.keys, + stateVersion + ).validators.asValidators().onEach { + cachedValidators[it.address] = it + } }.onFailure { error -> cacheErrors.value = error }.getOrNull() ?: return@transform - if (newPools.poolItems.isNotEmpty()) { - val join = newPools.poolItems.asPoolsResourcesJoin(SyncInfo(InstantGenerator(), stateVersion)) - dao.updatePools(pools = join) + if (newValidators.isNotEmpty()) { + logger.d("\uD83D\uDCBD Inserting validators") + dao.insertValidators(newValidators.asValidatorEntities(SyncInfo(InstantGenerator(), stateVersion))) + } + + val allPoolAddresses = cached.map { it.value.poolAddresses() }.flatten().toSet() + val cachedPools = dao.getCachedPools(allPoolAddresses, stateVersion).toMutableMap() + val unknownPools = allPoolAddresses - cachedPools.keys + if (unknownPools.isNotEmpty()) { + logger.d("\uD83D\uDCBD Inserting pools") + + val newPools = runCatching { + api.fetchPools(unknownPools.toSet(), stateVersion) + }.onFailure { error -> + cacheErrors.value = error + }.getOrNull() ?: return@transform + + if (newPools.poolItems.isNotEmpty()) { + val join = newPools.poolItems.asPoolsResourcesJoin(SyncInfo(InstantGenerator(), stateVersion)) + dao.updatePools(pools = join) + } else { + emit( + cached.mapNotNull { + it.value.toAccountAddressWithAssets( + accountAddress = it.key, + pools = cachedPools, + validators = cachedValidators + ) + } + ) + } } else { emit( cached.mapNotNull { @@ -285,18 +296,7 @@ class AccountsStateCache @Inject constructor( } ) } - } else { - emit( - cached.mapNotNull { - it.value.toAccountAddressWithAssets( - accountAddress = it.key, - pools = cachedPools, - validators = cachedValidators - ) - } - ) } - } private data class AccountCachedData( val stateVersion: Long?, 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 2a3d5989b4..4b0c225141 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 @@ -3,13 +3,11 @@ 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.getAllMetadata import com.babylon.wallet.android.data.gateway.extensions.getNextNftItems import com.babylon.wallet.android.data.gateway.extensions.paginateDetails import com.babylon.wallet.android.data.gateway.extensions.paginateNonFungibles import com.babylon.wallet.android.data.gateway.extensions.toMetadata 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 @@ -19,6 +17,7 @@ import com.babylon.wallet.android.data.repository.cache.database.StateDao.Compan import com.babylon.wallet.android.data.repository.cache.database.StateDao.Companion.resourcesCacheValidity import com.babylon.wallet.android.data.repository.cache.database.SyncInfo import com.babylon.wallet.android.data.repository.cache.database.ValidatorEntity.Companion.asValidatorEntity +import com.babylon.wallet.android.data.repository.cache.database.ValidatorEntity.Companion.asValidators import com.babylon.wallet.android.data.repository.cache.database.getCachedPools import com.babylon.wallet.android.data.repository.cache.database.storeAccountNFTsPortfolio import com.babylon.wallet.android.data.repository.cache.database.updateResourceDetails @@ -71,8 +70,7 @@ interface StateRepository { suspend fun getResources( addresses: Set, underAccountAddress: AccountAddress?, - withDetails: Boolean, - withAllMetadata: Boolean + withDetails: Boolean ): Result> suspend fun getPools(poolAddresses: Set): Result> @@ -320,18 +318,23 @@ class StateRepositoryImpl @Inject constructor( override suspend fun getResources( addresses: Set, underAccountAddress: AccountAddress?, - withDetails: Boolean, - withAllMetadata: Boolean + withDetails: Boolean ): Result> = withContext(dispatcher) { runCatching { - val addressesWithResourceEntities = addresses.associateWith { address -> - stateDao.getResourceDetails( + val addressesWithResources = addresses.associateWith { address -> + val cachedEntity = stateDao.getResourceDetails( resourceAddress = address, minValidity = resourcesCacheValidity() ) + + val amount = underAccountAddress?.let { accountAddress -> + stateDao.getAccountResourceJoin(resourceAddress = address, accountAddress = accountAddress)?.amount + } + + cachedEntity?.toResource(amount) }.toMutableMap() - val resourcesToFetch = addressesWithResourceEntities.mapNotNull { entry -> + val resourcesToFetch = addressesWithResources.mapNotNull { entry -> val cachedResource = entry.value if (cachedResource == null || !cachedResource.isDetailsAvailable && withDetails) entry.key else null } @@ -341,48 +344,22 @@ class StateRepositoryImpl @Inject constructor( metadataKeys = ExplicitMetadataKey.forAssets, onPage = { page -> page.items.forEach { item -> + val amount = underAccountAddress?.let { accountAddress -> + stateDao.getAccountResourceJoin( + resourceAddress = ResourceAddress.init(item.address), + accountAddress = accountAddress + )?.amount + } val updatedEntity = stateDao.updateResourceDetails(item) + val resource = updatedEntity.toResource(amount) - addressesWithResourceEntities[updatedEntity.address] = updatedEntity + addressesWithResources[resource.address] = resource } } ) } - addressesWithResourceEntities.values.filterNotNull().map { resourceEntity -> - val amount = underAccountAddress?.let { accountAddress -> - stateDao.getAccountResourceJoin(resourceAddress = resourceEntity.address, accountAddress = accountAddress)?.amount - } - - val nextMetadataCursor = resourceEntity.metadata?.nextCursor - if (withAllMetadata && nextMetadataCursor != null) { - val remainingMetadata = runCatching { - val stateVersion = requireNotNull(getLatestCachedStateVersionInNetwork()) - - stateApi.getAllMetadata( - resourceAddress = resourceEntity.address, - stateVersion = stateVersion, - initialCursor = nextMetadataCursor - ) - }.getOrNull()?.mapNotNull { it.toMetadata() }?.takeIf { it.isNotEmpty() }?.toSet() - - if (remainingMetadata != null) { - resourceEntity.copy( - metadata = resourceEntity.metadata.metadata.toMutableSet().apply { - this union remainingMetadata - }.let { - MetadataColumn(metadata = it.toList(), implicitState = MetadataColumn.ImplicitMetadataState.Complete) - }.also { - stateDao.updateMetadata(resourceAddress = resourceEntity.address, metadataColumn = it) - } - ) - } else { - resourceEntity - } - } else { - resourceEntity - }.toResource(amount) - } + addressesWithResources.values.filterNotNull() } } @@ -418,7 +395,9 @@ class StateRepositoryImpl @Inject constructor( runCatching { val stateVersion = getLatestCachedStateVersionInNetwork() val cachedValidators = if (stateVersion != null) { - stateDao.getValidators(addresses = validatorAddresses.toSet(), atStateVersion = stateVersion) + stateDao.getValidators(addresses = validatorAddresses.toSet(), atStateVersion = stateVersion).map { + it.asValidatorDetail() + } } else { emptyList() } @@ -429,17 +408,15 @@ class StateRepositoryImpl @Inject constructor( validatorsAddresses = unknownAddresses, stateVersion = stateVersion ) - - val syncInfo = SyncInfo(InstantGenerator(), requireNotNull(response.stateVersion)) - val newValidatorEntities = response.validators.map { it.asValidatorEntity(syncInfo) }.also { entities -> - stateDao.insertValidators(entities) + val details = response.validators.asValidators() + if (details.isNotEmpty()) { + val syncInfo = SyncInfo(InstantGenerator(), requireNotNull(response.stateVersion)) + stateDao.insertValidators(details.map { it.asValidatorEntity(syncInfo) }) } - newValidatorEntities + cachedValidators + details + cachedValidators } else { cachedValidators } - }.mapCatching { entities -> - entities.map { it.asValidatorDetail() } } } diff --git a/app/src/main/java/com/babylon/wallet/android/domain/usecases/GetDAppWithResourcesUseCase.kt b/app/src/main/java/com/babylon/wallet/android/domain/usecases/GetDAppWithResourcesUseCase.kt index e0cd36d334..de6170a35f 100644 --- a/app/src/main/java/com/babylon/wallet/android/domain/usecases/GetDAppWithResourcesUseCase.kt +++ b/app/src/main/java/com/babylon/wallet/android/domain/usecases/GetDAppWithResourcesUseCase.kt @@ -26,8 +26,7 @@ class GetDAppWithResourcesUseCase @Inject constructor( val resources = stateRepository.getResources( addresses = claimedResources.toSet(), underAccountAddress = null, - withDetails = false, - withAllMetadata = false + withDetails = false ).getOrNull().orEmpty() DAppWithResources( diff --git a/app/src/main/java/com/babylon/wallet/android/domain/usecases/GetResourcesUseCase.kt b/app/src/main/java/com/babylon/wallet/android/domain/usecases/GetResourcesUseCase.kt index 21d4231adf..748614c112 100644 --- a/app/src/main/java/com/babylon/wallet/android/domain/usecases/GetResourcesUseCase.kt +++ b/app/src/main/java/com/babylon/wallet/android/domain/usecases/GetResourcesUseCase.kt @@ -8,13 +8,6 @@ class GetResourcesUseCase @Inject constructor( private val stateRepository: StateRepository ) { - suspend operator fun invoke( - addresses: Set, - withDetails: Boolean = false - ) = stateRepository.getResources( - addresses = addresses, - underAccountAddress = null, - withDetails = withDetails, - withAllMetadata = false - ) + suspend operator fun invoke(addresses: Set, withDetails: Boolean = false) = + stateRepository.getResources(addresses = addresses, underAccountAddress = null, withDetails = withDetails) } diff --git a/app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/GetLSUDetailsUseCase.kt b/app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/GetLSUDetailsUseCase.kt new file mode 100644 index 0000000000..47d8be8193 --- /dev/null +++ b/app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/GetLSUDetailsUseCase.kt @@ -0,0 +1,38 @@ +package com.babylon.wallet.android.domain.usecases.assets + +import com.babylon.wallet.android.data.repository.state.StateRepository +import com.radixdlt.sargon.AccountAddress +import com.radixdlt.sargon.ResourceAddress +import rdx.works.core.domain.assets.LiquidStakeUnit +import rdx.works.core.domain.assets.ValidatorWithStakes +import rdx.works.core.domain.resources.Resource +import rdx.works.core.then +import java.lang.RuntimeException +import javax.inject.Inject + +/** + * Returns the LSU with validator details. Currently this use case does not return the associated claims. + */ +class GetLSUDetailsUseCase @Inject constructor( + private val stateRepository: StateRepository +) { + + suspend operator fun invoke(resourceAddress: ResourceAddress, accountAddress: AccountAddress): Result = + stateRepository.getResources( + addresses = setOf(resourceAddress), + underAccountAddress = accountAddress, + withDetails = true + ).mapCatching { + it.first() as Resource.FungibleResource + }.then { stake -> + val validatorAddress = stake.validatorAddress + ?: return@then Result.failure(RuntimeException("Resource $resourceAddress has no associated validator")) + stateRepository.getValidators(validatorAddresses = setOf(validatorAddress)).mapCatching { validators -> + val validator = validators.first() + ValidatorWithStakes( + validator = validator, + liquidStakeUnit = LiquidStakeUnit(stake, validator) + ) + } + } +} diff --git a/app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/ObserveResourceUseCase.kt b/app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/ObserveResourceUseCase.kt new file mode 100644 index 0000000000..a2bcdc9b7f --- /dev/null +++ b/app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/ObserveResourceUseCase.kt @@ -0,0 +1,42 @@ +package com.babylon.wallet.android.domain.usecases.assets + +import com.babylon.wallet.android.data.repository.state.StateRepository +import com.radixdlt.sargon.AccountAddress +import com.radixdlt.sargon.ResourceAddress +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import rdx.works.core.domain.resources.Resource +import javax.inject.Inject + +/** + * Fetches details regarding this fungible/non-fungible by looking it up through its address. + * If an account address is provided, the repository will try to also fetch amount information. + */ +class ObserveResourceUseCase @Inject constructor( + private val stateRepository: StateRepository +) { + + operator fun invoke( + resourceAddress: ResourceAddress, + accountAddress: AccountAddress? = null, + withDetails: Boolean = true + ): Flow = flow { + val resource = stateRepository.getResources( + addresses = setOf(resourceAddress), + underAccountAddress = accountAddress, + withDetails = false + ).getOrThrow().first() + + emit(resource) + + if (!resource.isDetailsAvailable && withDetails) { + val resourceWithDetails = stateRepository.getResources( + addresses = setOf(resourceAddress), + underAccountAddress = accountAddress, + withDetails = true + ).getOrThrow().first() + + emit(resourceWithDetails) + } + } +} diff --git a/app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/ResolveAssetsFromAddressUseCase.kt b/app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/ResolveAssetsFromAddressUseCase.kt index fe61486e2e..75ecff1798 100644 --- a/app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/ResolveAssetsFromAddressUseCase.kt +++ b/app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/ResolveAssetsFromAddressUseCase.kt @@ -21,14 +21,12 @@ class ResolveAssetsFromAddressUseCase @Inject constructor( ) { suspend operator fun invoke( fungibleAddresses: Set, - nonFungibleIds: Map>, - withAllMetadata: Boolean = false + nonFungibleIds: Map> ): Result> = stateRepository .getResources( addresses = fungibleAddresses + nonFungibleIds.keys, underAccountAddress = null, - withDetails = true, - withAllMetadata = withAllMetadata + withDetails = true ).mapCatching { resources -> val nfts = nonFungibleIds.mapValues { entry -> stateRepository.getNFTDetails(entry.key, entry.value.toSet()).getOrThrow() diff --git a/app/src/main/java/com/babylon/wallet/android/domain/usecases/transaction/GetTransactionBadgesUseCase.kt b/app/src/main/java/com/babylon/wallet/android/domain/usecases/transaction/GetTransactionBadgesUseCase.kt index 70de3905cb..020f794add 100644 --- a/app/src/main/java/com/babylon/wallet/android/domain/usecases/transaction/GetTransactionBadgesUseCase.kt +++ b/app/src/main/java/com/babylon/wallet/android/domain/usecases/transaction/GetTransactionBadgesUseCase.kt @@ -14,8 +14,7 @@ class GetTransactionBadgesUseCase @Inject constructor( ): Result> = stateRepository.getResources( addresses = addresses, underAccountAddress = null, - withDetails = false, - withAllMetadata = false + withDetails = false ).mapCatching { resources -> resources.map { Badge( diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/AssetMetadataRow.kt b/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/AssetMetadataRow.kt new file mode 100644 index 0000000000..bb64f10e4e --- /dev/null +++ b/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/AssetMetadataRow.kt @@ -0,0 +1,224 @@ +package com.babylon.wallet.android.presentation.account.composable + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import com.babylon.wallet.android.R +import com.babylon.wallet.android.designsystem.theme.RadixTheme +import com.babylon.wallet.android.presentation.ui.composables.ExpandableText +import com.babylon.wallet.android.presentation.ui.composables.actionableaddress.ActionableAddressView +import com.babylon.wallet.android.utils.openUrl +import com.radixdlt.sargon.Address +import com.radixdlt.sargon.NonFungibleGlobalId +import com.radixdlt.sargon.NonFungibleLocalId +import com.radixdlt.sargon.extensions.formatted +import com.radixdlt.sargon.extensions.init +import com.radixdlt.sargon.extensions.toDecimal192OrNull +import rdx.works.core.domain.resources.metadata.Metadata +import rdx.works.core.domain.resources.metadata.MetadataType +import java.time.Instant +import java.time.ZoneId +import java.time.format.DateTimeFormatter +import java.time.format.FormatStyle +import java.util.Locale + +@Composable +fun AssetMetadataRow( + modifier: Modifier, + key: String, + valueView: @Composable RowScope.() -> Unit +) { + Row( + modifier = modifier, + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + modifier = Modifier.padding(end = RadixTheme.dimensions.paddingMedium), + text = key.replaceFirstChar { + if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() + }, + style = RadixTheme.typography.body1Regular, + color = RadixTheme.colors.gray2 + ) + + valueView() + } +} + +@Composable +fun Metadata.View(modifier: Modifier) { + if (isRenderedInNewLine) { + Column( + modifier = modifier, + verticalArrangement = Arrangement.spacedBy(RadixTheme.dimensions.paddingSmall) + ) { + KeyView() + ValueView(isRenderedInNewLine = true) + } + } else { + Row( + modifier = modifier, + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + KeyView() + Spacer(modifier = Modifier.width(RadixTheme.dimensions.paddingMedium)) + ValueView(isRenderedInNewLine = false) + } + } +} + +@Composable +fun Metadata.KeyView( + modifier: Modifier = Modifier +) { + Text( + modifier = modifier.padding(end = RadixTheme.dimensions.paddingMedium), + text = key, + style = RadixTheme.typography.body1Regular, + color = RadixTheme.colors.gray2, + textAlign = TextAlign.Start + ) +} + +@Suppress("CyclomaticComplexMethod") +@Composable +fun Metadata.ValueView( + modifier: Modifier = Modifier, + isRenderedInNewLine: Boolean +) { + val context = LocalContext.current + when (this) { + is Metadata.Collection, is Metadata.Map -> Text( + modifier = modifier, + text = stringResource(id = R.string.assetDetails_NFTDetails_complexData), + style = RadixTheme.typography.body1HighImportance, + color = RadixTheme.colors.gray1, + textAlign = if (isRenderedInNewLine) TextAlign.Start else TextAlign.End, + maxLines = 2 + ) + + is Metadata.Primitive -> when (valueType) { + MetadataType.Bool, + is MetadataType.Integer, + MetadataType.Bytes, + MetadataType.Enum, + MetadataType.PublicKeyEcdsaSecp256k1, + MetadataType.PublicKeyEddsaEd25519, + MetadataType.PublicKeyHashEcdsaSecp256k1, + MetadataType.PublicKeyHashEddsaEd25519 -> Text( + modifier = modifier, + text = value, + style = RadixTheme.typography.body1HighImportance, + color = RadixTheme.colors.gray1, + textAlign = if (isRenderedInNewLine) TextAlign.Start else TextAlign.End, + maxLines = 2 + ) + + MetadataType.String -> ExpandableText( + modifier = modifier, + text = value, + style = RadixTheme.typography.body1HighImportance.copy( + color = RadixTheme.colors.gray1, + textAlign = if (isRenderedInNewLine) TextAlign.Start else TextAlign.End, + ), + toggleStyle = RadixTheme.typography.body1HighImportance.copy( + color = RadixTheme.colors.gray2 + ), + ) + + MetadataType.Instant -> { + val displayable = remember(value) { + val epochSeconds = value.toLongOrNull() ?: return@remember value + val dateTime = Instant.ofEpochSecond(epochSeconds) + .atZone(ZoneId.systemDefault()) + .toLocalDateTime() + + dateTime.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)) + } + Text( + modifier = modifier, + text = displayable, + style = RadixTheme.typography.body1HighImportance, + color = RadixTheme.colors.gray1, + textAlign = if (isRenderedInNewLine) TextAlign.Start else TextAlign.End, + maxLines = 2 + ) + } + + MetadataType.Address -> ActionableAddressView( + modifier = modifier, + address = remember(value) { + Address.init(value) + } + ) + + MetadataType.NonFungibleGlobalId -> ActionableAddressView( + modifier = modifier, + globalId = remember(value) { + NonFungibleGlobalId.init(value) + } + ) + + MetadataType.NonFungibleLocalId -> ActionableAddressView( + modifier = modifier, + localId = remember(value) { + NonFungibleLocalId.init(value) + } + ) + + MetadataType.Decimal -> Text( + modifier = modifier, + // If value is unable to transform to big decimal we just display raw value + text = value.toDecimal192OrNull()?.formatted() ?: value, + style = RadixTheme.typography.body1HighImportance, + color = RadixTheme.colors.gray1, + textAlign = if (isRenderedInNewLine) TextAlign.Start else TextAlign.End, + maxLines = 2 + ) + + MetadataType.Url -> Row( + modifier = modifier + .fillMaxWidth() + .clickable { context.openUrl(value) }, + horizontalArrangement = Arrangement.spacedBy(RadixTheme.dimensions.paddingDefault), + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = value, + style = RadixTheme.typography.body1StandaloneLink, + color = RadixTheme.colors.blue1 + ) + Icon( + painter = painterResource(id = R.drawable.ic_external_link), + contentDescription = null, + tint = RadixTheme.colors.gray3 + ) + } + } + } +} + +private const val ASSET_METADATA_SHORT_STRING_THRESHOLD = 40 +private val Metadata.isRenderedInNewLine: Boolean + get() = this is Metadata.Primitive && ( + valueType is MetadataType.Url || + (valueType is MetadataType.String && value.length > ASSET_METADATA_SHORT_STRING_THRESHOLD) + ) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/MetadataView.kt b/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/MetadataView.kt deleted file mode 100644 index 693803322b..0000000000 --- a/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/MetadataView.kt +++ /dev/null @@ -1,308 +0,0 @@ -package com.babylon.wallet.android.presentation.account.composable - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.wrapContentSize -import androidx.compose.foundation.text.InlineTextContent -import androidx.compose.foundation.text.appendInlineContent -import androidx.compose.material3.Icon -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.Placeholder -import androidx.compose.ui.text.PlaceholderVerticalAlign -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.buildAnnotatedString -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.dp -import androidx.constraintlayout.compose.ConstraintLayout -import androidx.constraintlayout.compose.Dimension -import com.babylon.wallet.android.R -import com.babylon.wallet.android.designsystem.theme.RadixTheme -import com.babylon.wallet.android.presentation.ui.composables.ExpandableText -import com.babylon.wallet.android.presentation.ui.composables.LinkText -import com.babylon.wallet.android.presentation.ui.composables.actionableaddress.ActionableAddressView -import com.babylon.wallet.android.presentation.ui.modifier.throttleClickable -import com.babylon.wallet.android.utils.copyToClipboard -import com.radixdlt.sargon.Address -import com.radixdlt.sargon.NonFungibleGlobalId -import com.radixdlt.sargon.NonFungibleLocalId -import com.radixdlt.sargon.extensions.formatted -import com.radixdlt.sargon.extensions.init -import com.radixdlt.sargon.extensions.toDecimal192OrNull -import rdx.works.core.domain.resources.metadata.Metadata -import rdx.works.core.domain.resources.metadata.MetadataType -import java.time.Instant -import java.time.ZoneId -import java.time.format.DateTimeFormatter -import java.time.format.FormatStyle - -@Composable -fun MetadataView( - modifier: Modifier = Modifier, - key: String, - isLocked: Boolean = false, - isRenderedInNewLine: Boolean = false, - valueContent: @Composable () -> Unit -) { - if (isRenderedInNewLine) { - Column( - modifier = modifier, - verticalArrangement = Arrangement.spacedBy(RadixTheme.dimensions.paddingSmall) - ) { - MetadataKeyView(key = key, isLocked = isLocked) - valueContent() - } - } else { - ConstraintLayout(modifier = modifier) { - val (keyView, valueView) = createRefs() - - MetadataKeyView( - modifier = Modifier.constrainAs(keyView) { - start.linkTo(parent.start) - top.linkTo(parent.top) - end.linkTo(valueView.start, margin = 12.dp) - width = if (key.length > SHORT_KEY_THRESHOLD) { - Dimension.fillToConstraints - } else { - Dimension.preferredWrapContent - } - height = Dimension.wrapContent - }, - key = key, - isLocked = isLocked - ) - Box( - modifier = Modifier.constrainAs(valueView) { - start.linkTo(keyView.end) - end.linkTo(parent.end) - top.linkTo(parent.top) - width = Dimension.fillToConstraints - height = Dimension.wrapContent - }, - contentAlignment = Alignment.TopEnd - ) { - valueContent() - } - } - } -} - -@Composable -fun MetadataView( - modifier: Modifier = Modifier, - metadata: Metadata -) { - MetadataView( - modifier = modifier, - key = metadata.key, - isLocked = metadata.isLocked, - isRenderedInNewLine = metadata.isRenderedInNewLine, - ) { - MetadataValueView( - modifier = Modifier.wrapContentSize( - align = if (metadata.isRenderedInNewLine) Alignment.TopStart else Alignment.TopEnd - ), - metadata = metadata, - isRenderedInNewLine = metadata.isRenderedInNewLine - ) - } -} - -@Composable -fun MetadataKeyView( - modifier: Modifier = Modifier, - metadata: Metadata, - style: TextStyle = RadixTheme.typography.body1Regular, - color: Color = RadixTheme.colors.gray2, -) { - MetadataKeyView( - modifier = modifier, - key = metadata.key, - isLocked = metadata.isLocked, - style = style, - color = color - ) -} - -@Composable -fun MetadataKeyView( - modifier: Modifier = Modifier, - key: String, - isLocked: Boolean, - style: TextStyle = RadixTheme.typography.body1Regular, - color: Color = RadixTheme.colors.gray2, -) { - Text( - modifier = modifier, - text = buildAnnotatedString { - append(key) - append(" ") - if (isLocked) { - appendInlineContent(id = "lock_icon") - } - }, - style = style, - color = color, - textAlign = TextAlign.Start, - inlineContent = mapOf( - "lock_icon" to InlineTextContent( - Placeholder(style.fontSize, style.fontSize, PlaceholderVerticalAlign.TextCenter) - ) { - Icon( - painter = painterResource(id = com.babylon.wallet.android.designsystem.R.drawable.ic_lock), - contentDescription = null, - tint = color - ) - } - ) - ) -} - -@Suppress("CyclomaticComplexMethod") -@Composable -fun MetadataValueView( - modifier: Modifier = Modifier, - metadata: Metadata, - isRenderedInNewLine: Boolean, - style: TextStyle = RadixTheme.typography.body1HighImportance, - color: Color = RadixTheme.colors.gray1 -) { - val context = LocalContext.current - when (metadata) { - is Metadata.Collection, is Metadata.Map -> Text( - modifier = modifier, - text = stringResource(id = R.string.assetDetails_NFTDetails_complexData), - style = style, - color = color, - textAlign = if (isRenderedInNewLine) TextAlign.Start else TextAlign.End, - maxLines = 2 - ) - - is Metadata.Primitive -> when (metadata.valueType) { - MetadataType.Bool, - is MetadataType.Integer, - MetadataType.Bytes, - MetadataType.Enum -> Text( - modifier = modifier, - text = metadata.value, - style = style, - color = color, - textAlign = if (isRenderedInNewLine) TextAlign.Start else TextAlign.End, - maxLines = 2 - ) - - MetadataType.PublicKeyEcdsaSecp256k1, - MetadataType.PublicKeyEddsaEd25519, - MetadataType.PublicKeyHashEcdsaSecp256k1, - MetadataType.PublicKeyHashEddsaEd25519 -> Text( - modifier = modifier.throttleClickable { - context.copyToClipboard( - label = metadata.key, - value = metadata.value, - successMessage = context.getString(R.string.addressAction_copiedToClipboard) - ) - }, - text = metadata.value, - style = style, - color = color, - textAlign = TextAlign.End, - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) - - MetadataType.String -> ExpandableText( - modifier = modifier, - text = metadata.value, - style = style.copy( - color = color, - textAlign = if (isRenderedInNewLine) TextAlign.Start else TextAlign.End, - ), - toggleStyle = style.copy( - color = RadixTheme.colors.gray2 - ) - ) - - MetadataType.Instant -> { - val displayable = remember(metadata.value) { - val epochSeconds = metadata.value.toLongOrNull() ?: return@remember metadata.value - val dateTime = Instant.ofEpochSecond(epochSeconds) - .atZone(ZoneId.systemDefault()) - .toLocalDateTime() - - dateTime.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)) - } - Text( - modifier = modifier, - text = displayable, - style = style, - color = color, - textAlign = if (isRenderedInNewLine) TextAlign.Start else TextAlign.End, - maxLines = 2 - ) - } - - MetadataType.Address -> ActionableAddressView( - modifier = modifier, - address = remember(metadata.value) { - Address.init(metadata.value) - }, - textStyle = style, - textColor = color, - iconColor = color - ) - - MetadataType.NonFungibleGlobalId -> ActionableAddressView( - modifier = modifier, - globalId = remember(metadata.value) { - NonFungibleGlobalId.init(metadata.value) - }.copy(), - textStyle = style, - textColor = color, - iconColor = color - ) - - MetadataType.NonFungibleLocalId -> ActionableAddressView( - modifier = modifier, - localId = remember(metadata.value) { - NonFungibleLocalId.init(metadata.value) - }, - textStyle = style, - textColor = color, - iconColor = color - ) - - MetadataType.Decimal -> Text( - modifier = modifier, - // If value is unable to transform to big decimal we just display raw value - text = metadata.value.toDecimal192OrNull()?.formatted() ?: metadata.value, - style = style, - color = color, - textAlign = if (isRenderedInNewLine) TextAlign.Start else TextAlign.End, - maxLines = 2 - ) - - MetadataType.Url -> LinkText( - modifier = modifier.fillMaxWidth(), - url = metadata.value - ) - } - } -} - -private const val SHORT_KEY_THRESHOLD = 30 -private const val SHORT_VALUE_THRESHOLD = 40 -private val Metadata.isRenderedInNewLine: Boolean - get() = this is Metadata.Primitive && ( - valueType is MetadataType.Url || - (valueType is MetadataType.String && value.length > SHORT_VALUE_THRESHOLD) - ) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/settings/approveddapps/dappdetail/DappDetailScreen.kt b/app/src/main/java/com/babylon/wallet/android/presentation/settings/approveddapps/dappdetail/DappDetailScreen.kt index 6262d4098c..9449202a75 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/settings/approveddapps/dappdetail/DappDetailScreen.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/settings/approveddapps/dappdetail/DappDetailScreen.kt @@ -4,6 +4,7 @@ package com.babylon.wallet.android.presentation.settings.approveddapps.dappdetai import androidx.activity.compose.BackHandler 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 @@ -25,6 +26,7 @@ import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Icon import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.rememberModalBottomSheetState @@ -40,6 +42,8 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview @@ -60,7 +64,6 @@ import com.babylon.wallet.android.presentation.ui.RadixWalletPreviewTheme import com.babylon.wallet.android.presentation.ui.composables.BasicPromptAlertDialog import com.babylon.wallet.android.presentation.ui.composables.DefaultModalSheetLayout import com.babylon.wallet.android.presentation.ui.composables.GrayBackgroundWrapper -import com.babylon.wallet.android.presentation.ui.composables.LinkText import com.babylon.wallet.android.presentation.ui.composables.PersonaDataFieldRow import com.babylon.wallet.android.presentation.ui.composables.PersonaDataStringField import com.babylon.wallet.android.presentation.ui.composables.RadixCenteredTopAppBar @@ -72,6 +75,7 @@ import com.babylon.wallet.android.presentation.ui.composables.card.NonFungibleCa import com.babylon.wallet.android.presentation.ui.composables.card.PersonaCard import com.babylon.wallet.android.presentation.ui.modifier.radixPlaceholder import com.babylon.wallet.android.presentation.ui.modifier.throttleClickable +import com.babylon.wallet.android.utils.openUrl import com.radixdlt.sargon.AccountAddress import com.radixdlt.sargon.Address import com.radixdlt.sargon.AppearanceId @@ -483,6 +487,7 @@ fun DAppWebsiteAddressRow( modifier: Modifier = Modifier, website: String?, ) { + val context = LocalContext.current Column( modifier = modifier, verticalArrangement = Arrangement.spacedBy(dimensions.paddingSmall) @@ -494,14 +499,31 @@ fun DAppWebsiteAddressRow( style = RadixTheme.typography.body1Regular, color = RadixTheme.colors.gray2 ) - - LinkText( + Row( modifier = Modifier .fillMaxWidth() - .radixPlaceholder(visible = website == null), - clickable = website != null, - url = website.orEmpty() - ) + .clickable(enabled = website != null) { + if (website != null) { + context.openUrl(website) + } + }, + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(dimensions.paddingSmall) + ) { + Text( + modifier = Modifier + .weight(1f) + .radixPlaceholder(visible = website == null), + text = website.orEmpty(), + style = RadixTheme.typography.body1HighImportance, + color = RadixTheme.colors.blue1 + ) + Icon( + painter = painterResource(id = com.babylon.wallet.android.designsystem.R.drawable.ic_link_out), + tint = RadixTheme.colors.gray3, + contentDescription = null + ) + } } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/settings/debug/profile/InspectProfileScreen.kt b/app/src/main/java/com/babylon/wallet/android/presentation/settings/debug/profile/InspectProfileScreen.kt index 330b6dee45..48d348b791 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/settings/debug/profile/InspectProfileScreen.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/settings/debug/profile/InspectProfileScreen.kt @@ -1,5 +1,6 @@ package com.babylon.wallet.android.presentation.settings.debug.profile +import android.content.ClipData import androidx.compose.foundation.background import androidx.compose.foundation.horizontalScroll import androidx.compose.foundation.layout.WindowInsets @@ -30,11 +31,11 @@ import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.Typeface import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.sp +import androidx.core.content.getSystemService import com.babylon.wallet.android.R import com.babylon.wallet.android.designsystem.theme.RadixTheme import com.babylon.wallet.android.presentation.common.FullscreenCircularProgressContent import com.babylon.wallet.android.presentation.ui.composables.RadixCenteredTopAppBar -import com.babylon.wallet.android.utils.copyToClipboard @Composable fun InspectProfileScreen( @@ -81,10 +82,13 @@ fun InspectProfileScreen( containerColor = RadixTheme.colors.gray4, contentColor = RadixTheme.colors.gray1, onClick = { - context.copyToClipboard( - label = "Radix Profile", - value = state.rawSnapshot.orEmpty() - ) + context.getSystemService()?.let { clipboardManager -> + val clipData = ClipData.newPlainText( + "Radix Address", + state.rawSnapshot + ) + clipboardManager.setPrimaryClip(clipData) + } } ) { Icon(painter = painterResource(id = R.drawable.ic_copy), contentDescription = null) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt index 6c10d99f52..cd556a9e92 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt @@ -1,6 +1,5 @@ package com.babylon.wallet.android.presentation.status.assets -import android.net.Uri import androidx.compose.foundation.border import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -11,27 +10,21 @@ import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue -import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import com.babylon.wallet.android.R import com.babylon.wallet.android.designsystem.theme.RadixTheme -import com.babylon.wallet.android.presentation.account.composable.MetadataKeyView -import com.babylon.wallet.android.presentation.account.composable.MetadataView import com.babylon.wallet.android.presentation.status.assets.fungible.FungibleDialogContent import com.babylon.wallet.android.presentation.status.assets.lsu.LSUDialogContent import com.babylon.wallet.android.presentation.status.assets.nonfungible.NonFungibleAssetDialogContent import com.babylon.wallet.android.presentation.status.assets.pool.PoolUnitDialogContent import com.babylon.wallet.android.presentation.ui.composables.BottomSheetDialogWrapper -import com.babylon.wallet.android.presentation.ui.composables.LinkText import com.babylon.wallet.android.presentation.ui.composables.SnackbarUiMessageHandler import com.babylon.wallet.android.presentation.ui.composables.assets.Behaviour import com.babylon.wallet.android.presentation.ui.composables.assets.Tag @@ -45,7 +38,6 @@ import rdx.works.core.domain.assets.AssetPrice import rdx.works.core.domain.assets.LiquidStakeUnit import rdx.works.core.domain.assets.PoolUnit import rdx.works.core.domain.assets.Token -import rdx.works.core.domain.resources.Resource import rdx.works.core.domain.resources.Tag @Composable @@ -147,83 +139,6 @@ fun Asset.displayTitle() = when (this) { } } -@Composable -fun DescriptionSection( - modifier: Modifier = Modifier, - description: String?, - infoUrl: Uri? -) { - Column( - modifier = modifier.fillMaxWidth() - ) { - if (!description.isNullOrBlank()) { - Text( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = RadixTheme.dimensions.paddingSmall) - .padding(bottom = if (infoUrl != null) RadixTheme.dimensions.paddingSemiLarge else 0.dp), - text = description, - style = RadixTheme.typography.body1Regular, - color = RadixTheme.colors.gray1, - textAlign = TextAlign.Start - ) - } - - if (infoUrl != null) { - Text( - modifier = Modifier - .padding(horizontal = RadixTheme.dimensions.paddingSmall), - text = stringResource(id = R.string.assetDetails_moreInfo), - style = RadixTheme.typography.body1Regular, - color = RadixTheme.colors.gray2 - ) - - LinkText( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = RadixTheme.dimensions.paddingSmall) - .padding(top = RadixTheme.dimensions.paddingXSmall), - url = infoUrl - ) - } - - if (!description.isNullOrBlank() || infoUrl != null) { - Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) - HorizontalDivider(Modifier.fillMaxWidth(), color = RadixTheme.colors.gray4) - Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) - } - } -} - -@Composable -fun NonStandardMetadataSection( - modifier: Modifier = Modifier, - resource: Resource -) { - val metadata = remember(resource.metadata) { - resource.nonStandardMetadata - } - - if (metadata.isNotEmpty()) { - Column( - modifier = modifier - ) { - Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) - HorizontalDivider(Modifier.fillMaxWidth(), color = RadixTheme.colors.gray4) - - metadata.forEach { metadata -> - Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) - MetadataView( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = RadixTheme.dimensions.paddingSmall), - metadata = metadata - ) - } - } - } -} - @Composable fun BehavioursSection( modifier: Modifier = Modifier, @@ -279,10 +194,11 @@ fun TagsSection( if (!tags.isNullOrEmpty()) { Column(modifier = modifier) { Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) - MetadataKeyView( + Text( modifier = Modifier.fillMaxWidth(), - key = stringResource(id = R.string.assetDetails_tags), - isLocked = false + text = stringResource(id = R.string.assetDetails_tags), + style = RadixTheme.typography.body1Regular, + color = RadixTheme.colors.gray2 ) Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) FlowRow( @@ -304,6 +220,7 @@ fun TagsSection( } } ) + Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingXXLarge)) } } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialogViewModel.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialogViewModel.kt index 0cc0ab10c8..a16bf9ffde 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialogViewModel.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialogViewModel.kt @@ -52,8 +52,7 @@ class AssetDialogViewModel @Inject constructor( is AssetDialogArgs.NFT -> mapOf( args.resourceAddress to args.localId?.let { setOf(it) }.orEmpty() ) - }, - withAllMetadata = true + } ).mapCatching { assets -> when (val asset = assets.first()) { // In case we receive a fungible asset, let's copy the custom amount diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt index c1926988dc..732ac8c51b 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt @@ -23,11 +23,9 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import com.babylon.wallet.android.R import com.babylon.wallet.android.designsystem.theme.RadixTheme -import com.babylon.wallet.android.presentation.account.composable.MetadataView +import com.babylon.wallet.android.presentation.account.composable.AssetMetadataRow import com.babylon.wallet.android.presentation.status.assets.AssetDialogArgs import com.babylon.wallet.android.presentation.status.assets.BehavioursSection -import com.babylon.wallet.android.presentation.status.assets.DescriptionSection -import com.babylon.wallet.android.presentation.status.assets.NonStandardMetadataSection import com.babylon.wallet.android.presentation.status.assets.TagsSection import com.babylon.wallet.android.presentation.ui.composables.ShimmeringView import com.babylon.wallet.android.presentation.ui.composables.Thumbnail @@ -63,9 +61,22 @@ fun FungibleDialogContent( ), horizontalAlignment = Alignment.CenterHorizontally ) { - FungibleIconSection(token = token) + if (token?.resource != null) { + Thumbnail.Fungible( + modifier = Modifier.size(104.dp), + token = token.resource + ) + } else { + Box( + modifier = Modifier + .size(104.dp) + .radixPlaceholder( + visible = true, + shape = CircleShape + ) + ) + } Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) - if (amount != null) { TokenBalance( modifier = Modifier @@ -97,12 +108,17 @@ fun FungibleDialogContent( HorizontalDivider(Modifier.fillMaxWidth(), color = RadixTheme.colors.gray4) Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) - DescriptionSection( - modifier = Modifier.fillMaxWidth(), - description = token?.resource?.description, - infoUrl = token?.resource?.infoUrl - ) - + if (!token?.resource?.description.isNullOrBlank()) { + Text( + modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingSmall), + text = token?.resource?.description.orEmpty(), + style = RadixTheme.typography.body2Regular, + color = RadixTheme.colors.gray1 + ) + Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) + HorizontalDivider(Modifier.fillMaxWidth(), color = RadixTheme.colors.gray4) + Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) + } AddressRow( modifier = Modifier .fillMaxWidth() @@ -113,7 +129,7 @@ fun FungibleDialogContent( Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) if (!isNewlyCreated) { - MetadataView( + AssetMetadataRow( modifier = Modifier .fillMaxWidth() .padding(horizontal = RadixTheme.dimensions.paddingSmall), @@ -143,34 +159,8 @@ fun FungibleDialogContent( TagsSection( modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingSmall), - tags = token?.resource?.tags + tags = token?.resource?.tags, ) - - token?.resource?.let { resource -> - NonStandardMetadataSection(resource = resource) - } } } } - -@Composable -private fun FungibleIconSection( - modifier: Modifier = Modifier, - token: Token? -) { - if (token?.resource != null) { - Thumbnail.Fungible( - modifier = modifier.size(104.dp), - token = token.resource - ) - } else { - Box( - modifier = modifier - .size(104.dp) - .radixPlaceholder( - visible = true, - shape = CircleShape - ) - ) - } -} diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt index 6c3af190d8..bfc6f2acea 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt @@ -26,11 +26,9 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import com.babylon.wallet.android.R import com.babylon.wallet.android.designsystem.theme.RadixTheme -import com.babylon.wallet.android.presentation.account.composable.MetadataView +import com.babylon.wallet.android.presentation.account.composable.AssetMetadataRow import com.babylon.wallet.android.presentation.status.assets.AssetDialogArgs import com.babylon.wallet.android.presentation.status.assets.BehavioursSection -import com.babylon.wallet.android.presentation.status.assets.DescriptionSection -import com.babylon.wallet.android.presentation.status.assets.NonStandardMetadataSection import com.babylon.wallet.android.presentation.status.assets.TagsSection import com.babylon.wallet.android.presentation.ui.composables.ShimmeringView import com.babylon.wallet.android.presentation.ui.composables.Thumbnail @@ -73,9 +71,22 @@ fun LSUDialogContent( ), horizontalAlignment = Alignment.CenterHorizontally ) { - LSUIconSection(lsu = lsu) + if (lsu != null) { + Thumbnail.LSU( + modifier = Modifier.size(104.dp), + liquidStakeUnit = lsu + ) + } else { + Box( + modifier = Modifier + .size(104.dp) + .radixPlaceholder( + visible = true, + shape = CircleShape + ) + ) + } Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) - TokenBalance( modifier = Modifier .fillMaxWidth(fraction = if (lsu == null) 0.5f else 1f) @@ -135,11 +146,17 @@ fun LSUDialogContent( ) Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) - DescriptionSection( - modifier = Modifier.fillMaxWidth(), - description = lsu?.fungibleResource?.description, - infoUrl = lsu?.fungibleResource?.infoUrl - ) + if (!lsu?.fungibleResource?.description.isNullOrBlank()) { + Text( + modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingSmall), + text = lsu?.fungibleResource?.description.orEmpty(), + style = RadixTheme.typography.body2Regular, + color = RadixTheme.colors.gray1 + ) + Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) + HorizontalDivider(Modifier.fillMaxWidth(), color = RadixTheme.colors.gray4) + Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) + } AddressRow( modifier = Modifier @@ -161,7 +178,7 @@ fun LSUDialogContent( } Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) - MetadataView( + AssetMetadataRow( modifier = Modifier .fillMaxWidth() .padding(horizontal = RadixTheme.dimensions.paddingSmall), @@ -169,6 +186,7 @@ fun LSUDialogContent( ) { Text( modifier = Modifier + .padding(start = RadixTheme.dimensions.paddingDefault) .widthIn(min = RadixTheme.dimensions.paddingXXXXLarge * 2) .radixPlaceholder(visible = lsu == null), text = lsu?.name().orEmpty(), @@ -178,7 +196,7 @@ fun LSUDialogContent( ) } Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) - MetadataView( + AssetMetadataRow( modifier = Modifier .fillMaxWidth() .padding(horizontal = RadixTheme.dimensions.paddingSmall), @@ -186,6 +204,7 @@ fun LSUDialogContent( ) { Text( modifier = Modifier + .padding(start = RadixTheme.dimensions.paddingDefault) .widthIn(min = RadixTheme.dimensions.paddingXXXXLarge * 2) .radixPlaceholder( visible = lsu?.fungibleResource?.currentSupply == null @@ -200,6 +219,7 @@ fun LSUDialogContent( textAlign = TextAlign.End ) } + Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) BehavioursSection( modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingSmall), @@ -210,32 +230,6 @@ fun LSUDialogContent( modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingSmall), tags = lsu?.fungibleResource?.tags ) - - lsu?.resource?.let { resource -> - NonStandardMetadataSection(resource = resource) - } - } -} - -@Composable -private fun LSUIconSection( - modifier: Modifier = Modifier, - lsu: LiquidStakeUnit? -) { - if (lsu != null) { - Thumbnail.LSU( - modifier = modifier.size(104.dp), - liquidStakeUnit = lsu - ) - } else { - Box( - modifier = modifier - .size(104.dp) - .radixPlaceholder( - visible = true, - shape = CircleShape - ) - ) } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt index 039fb21c23..fb2ce098be 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt @@ -27,13 +27,12 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import com.babylon.wallet.android.R -import com.babylon.wallet.android.designsystem.composable.RadixPrimaryButton +import com.babylon.wallet.android.designsystem.composable.RadixTextButton import com.babylon.wallet.android.designsystem.theme.RadixTheme -import com.babylon.wallet.android.presentation.account.composable.MetadataView +import com.babylon.wallet.android.presentation.account.composable.AssetMetadataRow +import com.babylon.wallet.android.presentation.account.composable.View import com.babylon.wallet.android.presentation.status.assets.AssetDialogViewModel import com.babylon.wallet.android.presentation.status.assets.BehavioursSection -import com.babylon.wallet.android.presentation.status.assets.DescriptionSection -import com.babylon.wallet.android.presentation.status.assets.NonStandardMetadataSection import com.babylon.wallet.android.presentation.status.assets.TagsSection import com.babylon.wallet.android.presentation.ui.composables.GrayBackgroundWrapper import com.babylon.wallet.android.presentation.ui.composables.Thumbnail @@ -115,13 +114,14 @@ fun NonFungibleAssetDialogContent( } if (item != null) { - MetadataView( + AssetMetadataRow( modifier = Modifier .fillMaxWidth() .padding(horizontal = RadixTheme.dimensions.paddingXXLarge), key = stringResource(id = R.string.assetDetails_NFTDetails_id) ) { ActionableAddressView( + modifier = Modifier.padding(start = RadixTheme.dimensions.paddingDefault), globalId = item.globalId, visitableInDashboard = !isNewlyCreated, textStyle = RadixTheme.typography.body1HighImportance, @@ -154,11 +154,10 @@ fun NonFungibleAssetDialogContent( item?.nonStandardMetadata?.forEach { metadata -> Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) - MetadataView( + metadata.View( modifier = Modifier .fillMaxWidth() - .padding(horizontal = RadixTheme.dimensions.paddingXXLarge), - metadata = metadata + .padding(horizontal = RadixTheme.dimensions.paddingXXLarge) ) } @@ -201,14 +200,22 @@ fun NonFungibleAssetDialogContent( ) Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) - DescriptionSection( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = RadixTheme.dimensions.paddingLarge), - description = asset?.resource?.description, - infoUrl = asset?.resource?.infoUrl - ) - + if (!asset?.resource?.description.isNullOrBlank()) { + Text( + modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingXXLarge), + text = asset?.resource?.description.orEmpty(), + style = RadixTheme.typography.body2Regular, + color = RadixTheme.colors.gray1 + ) + Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) + HorizontalDivider( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = RadixTheme.dimensions.paddingLarge), + color = RadixTheme.colors.gray4 + ) + Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) + } AddressRow( modifier = Modifier .fillMaxWidth() @@ -218,7 +225,7 @@ fun NonFungibleAssetDialogContent( ) if (!asset?.resource?.name.isNullOrBlank() && localId != null) { Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) - MetadataView( + AssetMetadataRow( modifier = Modifier .fillMaxWidth() .padding(horizontal = RadixTheme.dimensions.paddingXXLarge), @@ -234,7 +241,7 @@ fun NonFungibleAssetDialogContent( Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) if (!isNewlyCreated) { - MetadataView( + AssetMetadataRow( modifier = Modifier .fillMaxWidth() .padding(horizontal = RadixTheme.dimensions.paddingXXLarge), @@ -242,6 +249,7 @@ fun NonFungibleAssetDialogContent( ) { Text( modifier = Modifier + .padding(start = RadixTheme.dimensions.paddingDefault) .widthIn(min = RadixTheme.dimensions.paddingXXXXLarge * 2) .radixPlaceholder(visible = asset?.resource?.currentSupply == null), text = when { @@ -267,13 +275,6 @@ fun NonFungibleAssetDialogContent( modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingXXLarge), tags = asset?.resource?.tags ) - - asset?.resource?.let { resource -> - NonStandardMetadataSection( - modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingLarge), - resource = resource - ) - } } } } @@ -292,77 +293,57 @@ private fun ClaimNFTInfo( val showClaimButton = claimState is AssetDialogViewModel.State.ClaimState.ReadyToClaim && !accountContextMissing Column( modifier = modifier - .padding(horizontal = RadixTheme.dimensions.paddingLarge) + .padding(horizontal = RadixTheme.dimensions.paddingXXLarge) .fillMaxWidth() ) { - HorizontalDivider( - modifier = Modifier - .fillMaxWidth() - .padding(bottom = RadixTheme.dimensions.paddingDefault), - color = RadixTheme.colors.gray4 - ) + Row( + modifier = Modifier.padding(bottom = if (showClaimButton) 0.dp else RadixTheme.dimensions.paddingSmall), + horizontalArrangement = Arrangement.spacedBy(RadixTheme.dimensions.paddingSmall), + verticalAlignment = Alignment.CenterVertically + ) { + Text( + modifier = Modifier.weight(1f), + text = when (claimState) { + is AssetDialogViewModel.State.ClaimState.ReadyToClaim -> stringResource( + id = if (accountContextMissing) { + R.string.transactionReview_toBeClaimed + } else { + R.string.account_staking_readyToBeClaimed + } + ) + is AssetDialogViewModel.State.ClaimState.Unstaking -> + stringResource(id = R.string.account_staking_unstaking) + null -> "" + }.uppercase(), + style = RadixTheme.typography.body2HighImportance, + color = RadixTheme.colors.gray2 + ) - Text( - modifier = Modifier - .fillMaxWidth() - .padding( - vertical = RadixTheme.dimensions.paddingDefault, - horizontal = RadixTheme.dimensions.paddingMedium - ), - text = stringResource(id = R.string.assetDetails_staking_currentRedeemableValue), - style = RadixTheme.typography.secondaryHeader, - color = RadixTheme.colors.gray1, - textAlign = TextAlign.Center - ) + if (showClaimButton) { + RadixTextButton( + text = stringResource(id = R.string.account_staking_claim), + onClick = onClaimClick, + textStyle = RadixTheme.typography.body2Link + ) + } + } val fiatPrice = remember(price, item) { price?.xrdPrice(item) } WorthXRD( - modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingMedium), amount = claimState?.amount, fiatPrice = fiatPrice, - isLoadingBalance = isLoadingBalance, - iconSize = 44.dp, - symbolStyle = RadixTheme.typography.body2HighImportance + isLoadingBalance = isLoadingBalance ) - when (claimState) { - is AssetDialogViewModel.State.ClaimState.Unstaking -> { - Row( - modifier = Modifier - .padding(top = RadixTheme.dimensions.paddingDefault) - .padding(horizontal = RadixTheme.dimensions.paddingMedium) - .fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.Top - ) { - Text( - text = stringResource(id = R.string.assetDetails_staking_readyToClaimIn), - style = RadixTheme.typography.body1Regular, - color = RadixTheme.colors.gray2 - ) - - Text( - text = stringResource(id = R.string.assetDetails_staking_readyToClaimInMinutes, claimState.approximateClaimMinutes), - style = RadixTheme.typography.body1HighImportance, - color = RadixTheme.colors.gray1 - ) - } - } - is AssetDialogViewModel.State.ClaimState.ReadyToClaim -> { - if (showClaimButton) { - RadixPrimaryButton( - modifier = Modifier - .padding(top = RadixTheme.dimensions.paddingDefault) - .padding(horizontal = RadixTheme.dimensions.paddingMedium) - .fillMaxWidth(), - text = stringResource(id = R.string.assetDetails_staking_readyToClaim), - onClick = onClaimClick - ) - } - } - null -> {} + if (claimState is AssetDialogViewModel.State.ClaimState.Unstaking) { + Text( + modifier = Modifier.padding(top = RadixTheme.dimensions.paddingSmall), + text = stringResource(id = R.string.assetDetails_staking_unstaking, claimState.approximateClaimMinutes), + style = RadixTheme.typography.body2HighImportance, + color = RadixTheme.colors.gray2 + ) } } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt index 649689cfaf..90ff3ffbf0 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt @@ -25,11 +25,9 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import com.babylon.wallet.android.R import com.babylon.wallet.android.designsystem.theme.RadixTheme -import com.babylon.wallet.android.presentation.account.composable.MetadataView +import com.babylon.wallet.android.presentation.account.composable.AssetMetadataRow import com.babylon.wallet.android.presentation.status.assets.AssetDialogArgs import com.babylon.wallet.android.presentation.status.assets.BehavioursSection -import com.babylon.wallet.android.presentation.status.assets.DescriptionSection -import com.babylon.wallet.android.presentation.status.assets.NonStandardMetadataSection import com.babylon.wallet.android.presentation.status.assets.TagsSection import com.babylon.wallet.android.presentation.ui.composables.Thumbnail import com.babylon.wallet.android.presentation.ui.composables.assets.PoolResourcesValues @@ -152,12 +150,20 @@ fun PoolUnitDialogContent( ) Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) - DescriptionSection( - modifier = Modifier.fillMaxWidth(), - description = poolUnit?.stake?.description, - infoUrl = poolUnit?.stake?.infoUrl - ) - + if (!poolUnit?.stake?.description.isNullOrBlank()) { + Text( + modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingDefault), + text = poolUnit?.stake?.description.orEmpty(), + style = RadixTheme.typography.body2Regular, + color = RadixTheme.colors.gray1 + ) + Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) + HorizontalDivider( + modifier = Modifier.fillMaxWidth(), + color = RadixTheme.colors.gray4 + ) + Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) + } AddressRow( modifier = Modifier .fillMaxWidth() @@ -166,7 +172,7 @@ fun PoolUnitDialogContent( ) Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) - MetadataView( + AssetMetadataRow( modifier = Modifier .fillMaxWidth() .padding(horizontal = RadixTheme.dimensions.paddingSmall), @@ -174,6 +180,7 @@ fun PoolUnitDialogContent( ) { Text( modifier = Modifier + .padding(start = RadixTheme.dimensions.paddingDefault) .widthIn(min = RadixTheme.dimensions.paddingXXXXLarge * 2) .radixPlaceholder(visible = poolUnit?.stake?.currentSupply == null), text = when (val supply = poolUnit?.stake?.currentSupply) { @@ -194,11 +201,7 @@ fun PoolUnitDialogContent( TagsSection( modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingSmall), - tags = poolUnit?.resource?.tags + tags = poolUnit?.resource?.tags, ) - - poolUnit?.resource?.let { resource -> - NonStandardMetadataSection(resource = resource) - } } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/LinkText.kt b/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/LinkText.kt deleted file mode 100644 index 557aebcb76..0000000000 --- a/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/LinkText.kt +++ /dev/null @@ -1,80 +0,0 @@ -package com.babylon.wallet.android.presentation.ui.composables - -import android.net.Uri -import androidx.compose.foundation.text.InlineTextContent -import androidx.compose.foundation.text.appendInlineContent -import androidx.compose.material3.Icon -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.Placeholder -import androidx.compose.ui.text.PlaceholderVerticalAlign -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.buildAnnotatedString -import androidx.compose.ui.text.style.TextAlign -import com.babylon.wallet.android.R -import com.babylon.wallet.android.designsystem.theme.RadixTheme -import com.babylon.wallet.android.presentation.ui.modifier.throttleClickable -import com.babylon.wallet.android.utils.openUrl - -@Composable -fun LinkText( - modifier: Modifier = Modifier, - url: Uri, - clickable: Boolean = true, - linkStyle: TextStyle = RadixTheme.typography.body1StandaloneLink, - linkColor: Color = RadixTheme.colors.blue1, - linkIconColor: Color = RadixTheme.colors.gray2 -) { - LinkText( - modifier = modifier, - url = url.toString(), - clickable = clickable, - linkStyle = linkStyle, - linkColor = linkColor, - linkIconColor = linkIconColor - ) -} - -@Composable -fun LinkText( - modifier: Modifier = Modifier, - url: String, - clickable: Boolean = true, - linkStyle: TextStyle = RadixTheme.typography.body1StandaloneLink, - linkColor: Color = RadixTheme.colors.blue1, - linkIconColor: Color = RadixTheme.colors.gray2 -) { - val context = LocalContext.current - Text( - modifier = modifier.throttleClickable(enabled = clickable) { - context.openUrl(url) - }, - text = buildAnnotatedString { - append(url) - append(" ") - appendInlineContent(id = "link_icon") - }, - style = linkStyle, - color = linkColor, - inlineContent = mapOf( - "link_icon" to InlineTextContent( - Placeholder( - linkStyle.fontSize, - linkStyle.fontSize, - PlaceholderVerticalAlign.TextCenter - ) - ) { - Icon( - painter = painterResource(id = R.drawable.ic_external_link), - contentDescription = null, - tint = linkIconColor - ) - } - ), - textAlign = TextAlign.Start, - ) -} diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/actionableaddress/ActionableAddressView.kt b/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/actionableaddress/ActionableAddressView.kt index 35b396ea2a..7ce9189383 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/actionableaddress/ActionableAddressView.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/actionableaddress/ActionableAddressView.kt @@ -2,8 +2,10 @@ package com.babylon.wallet.android.presentation.ui.composables.actionableaddress +import android.content.ClipData import android.content.Context import android.net.Uri +import android.os.Build import android.widget.Toast import androidx.annotation.DrawableRes import androidx.annotation.VisibleForTesting @@ -43,6 +45,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.constraintlayout.compose.ConstraintLayout import androidx.constraintlayout.compose.Dimension +import androidx.core.content.getSystemService import androidx.core.net.toUri import com.babylon.wallet.android.R import com.babylon.wallet.android.designsystem.theme.RadixTheme @@ -50,7 +53,6 @@ import com.babylon.wallet.android.domain.usecases.VerifyAddressOnLedgerUseCase import com.babylon.wallet.android.presentation.ui.RadixWalletPreviewTheme import com.babylon.wallet.android.presentation.ui.composables.AccountQRCodeView import com.babylon.wallet.android.presentation.ui.composables.BottomSheetWrapper -import com.babylon.wallet.android.utils.copyToClipboard import com.babylon.wallet.android.utils.encodeUtf8 import com.babylon.wallet.android.utils.openUrl import com.radixdlt.sargon.AccountAddress @@ -467,11 +469,20 @@ private sealed interface OnAction { ) : CallbackBasedAction { override fun onAction(context: Context) { - context.copyToClipboard( - label = "Radix Address", - value = actionableAddress.copyable.orEmpty(), - successMessage = context.getString(R.string.addressAction_copiedToClipboard) - ) + context.getSystemService()?.let { clipboardManager -> + + val clipData = ClipData.newPlainText( + "Radix Address", + actionableAddress.copyable + ) + + clipboardManager.setPrimaryClip(clipData) + + // From Android 13, the system handles the copy confirmation + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) { + Toast.makeText(context, R.string.addressAction_copiedToClipboard, Toast.LENGTH_SHORT).show() + } + } } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/assets/StakingTab.kt b/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/assets/StakingTab.kt index 7154fded5e..1abad4e9bc 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/assets/StakingTab.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/assets/StakingTab.kt @@ -26,7 +26,6 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.babylon.wallet.android.R import com.babylon.wallet.android.designsystem.composable.RadixTextButton @@ -715,8 +714,6 @@ fun WorthXRD( amount: Decimal192?, fiatPrice: FiatPrice?, isLoadingBalance: Boolean, - iconSize: Dp = 24.dp, - symbolStyle: TextStyle = RadixTheme.typography.body2HighImportance, trailingContent: @Composable (() -> Unit)? = null ) { Row( @@ -736,17 +733,15 @@ fun WorthXRD( painter = painterResource(id = com.babylon.wallet.android.designsystem.R.drawable.ic_xrd_token), contentDescription = null, modifier = Modifier - .size(iconSize) + .size(24.dp) .clip(RadixTheme.shapes.circle), tint = Color.Unspecified ) Text( - modifier = Modifier.padding( - horizontal = RadixTheme.dimensions.paddingSmall - ), + modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingSmall), text = XrdResource.SYMBOL, - style = symbolStyle, + style = RadixTheme.typography.body2HighImportance, color = RadixTheme.colors.gray1, maxLines = 1 ) diff --git a/app/src/main/java/com/babylon/wallet/android/utils/ContextExtensions.kt b/app/src/main/java/com/babylon/wallet/android/utils/ContextExtensions.kt index b5888f71a3..92676dbc0d 100644 --- a/app/src/main/java/com/babylon/wallet/android/utils/ContextExtensions.kt +++ b/app/src/main/java/com/babylon/wallet/android/utils/ContextExtensions.kt @@ -1,16 +1,13 @@ package com.babylon.wallet.android.utils import android.content.ActivityNotFoundException -import android.content.ClipData import android.content.ComponentName import android.content.Context import android.content.ContextWrapper import android.content.Intent import android.content.pm.PackageManager import android.net.Uri -import android.os.Build import android.widget.Toast -import androidx.core.content.getSystemService import androidx.core.net.toUri import androidx.fragment.app.FragmentActivity import androidx.navigation.NavController @@ -47,28 +44,6 @@ suspend fun Context.biometricAuthenticateSuspend(allowIfDeviceIsNotSecure: Boole fun Context.openUrl(url: HttpUrl, browser: Browser? = null) = openUrl(url.toString(), browser) fun Context.openUrl(url: String, browser: Browser? = null) = openUrl(url.toUri(), browser) -fun Context.copyToClipboard( - label: String, - value: String, - // Used only for Android versions < Android 13 - successMessage: String? = null -) { - getSystemService()?.let { clipboardManager -> - - val clipData = ClipData.newPlainText( - label, - value - ) - - clipboardManager.setPrimaryClip(clipData) - - // From Android 13, the system handles the copy confirmation - if (successMessage != null && Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) { - Toast.makeText(this, successMessage, Toast.LENGTH_SHORT).show() - } - } -} - @Suppress("SwallowedException") fun Context.openUrl(uri: Uri, browser: Browser? = null) { val intent = Intent(Intent.ACTION_VIEW).apply { diff --git a/app/src/test/java/com/babylon/wallet/android/data/cache/ProvidedConvertersTest.kt b/app/src/test/java/com/babylon/wallet/android/data/cache/ProvidedConvertersTest.kt index 46a5a3e520..a5f10bb2ae 100644 --- a/app/src/test/java/com/babylon/wallet/android/data/cache/ProvidedConvertersTest.kt +++ b/app/src/test/java/com/babylon/wallet/android/data/cache/ProvidedConvertersTest.kt @@ -3,12 +3,12 @@ package com.babylon.wallet.android.data.cache import com.babylon.wallet.android.data.repository.cache.database.BehavioursColumn import com.babylon.wallet.android.data.repository.cache.database.MetadataColumn import com.babylon.wallet.android.data.repository.cache.database.StateDatabaseConverters -import org.junit.Assert.assertEquals -import org.junit.Assert.assertNull -import org.junit.Test import rdx.works.core.domain.assets.AssetBehaviour import rdx.works.core.domain.resources.metadata.Metadata import rdx.works.core.domain.resources.metadata.MetadataType +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull +import org.junit.Test class ProvidedConvertersTest { @@ -100,8 +100,7 @@ class ProvidedConvertersTest { ) to Metadata.Primitive("value", "Value", MetadataType.String) ) ) - ), - implicitState = MetadataColumn.ImplicitMetadataState.Unknown + ) ) val converter = StateDatabaseConverters() diff --git a/app/src/test/java/com/babylon/wallet/android/domain/usecases/SearchFeePayersUseCaseTest.kt b/app/src/test/java/com/babylon/wallet/android/domain/usecases/SearchFeePayersUseCaseTest.kt index 12c32db309..36c95090ec 100644 --- a/app/src/test/java/com/babylon/wallet/android/domain/usecases/SearchFeePayersUseCaseTest.kt +++ b/app/src/test/java/com/babylon/wallet/android/domain/usecases/SearchFeePayersUseCaseTest.kt @@ -148,8 +148,7 @@ class SearchFeePayersUseCaseTest { override suspend fun getResources( addresses: Set, underAccountAddress: AccountAddress?, - withDetails: Boolean, - withAllMetadata: Boolean + withDetails: Boolean ): Result> { TODO("Not yet implemented") } diff --git a/app/src/test/java/com/babylon/wallet/android/fakes/StateRepositoryFake.kt b/app/src/test/java/com/babylon/wallet/android/fakes/StateRepositoryFake.kt index 353085772f..589e7a67f9 100644 --- a/app/src/test/java/com/babylon/wallet/android/fakes/StateRepositoryFake.kt +++ b/app/src/test/java/com/babylon/wallet/android/fakes/StateRepositoryFake.kt @@ -37,12 +37,7 @@ open class StateRepositoryFake : StateRepository { override suspend fun updateStakeClaims(account: Account, claims: List): Result> = Result.success(claims) - override suspend fun getResources( - addresses: Set, - underAccountAddress: AccountAddress?, - withDetails: Boolean, - withAllMetadata: Boolean - ): Result> = + override suspend fun getResources(addresses: Set, underAccountAddress: AccountAddress?, withDetails: Boolean): Result> = Result.failure(RuntimeException("Not implemented")) override suspend fun getPools(poolAddresses: Set): Result> = Result.failure(RuntimeException("Not implemented")) @@ -50,10 +45,7 @@ open class StateRepositoryFake : StateRepository { override suspend fun getValidators(validatorAddresses: Set): Result> = Result.failure(RuntimeException("Not implemented")) - override suspend fun getNFTDetails( - resourceAddress: ResourceAddress, - localIds: Set - ): Result> = + override suspend fun getNFTDetails(resourceAddress: ResourceAddress, localIds: Set): Result> = Result.failure(RuntimeException("Not implemented")) override suspend fun getOwnedXRD(accounts: List): Result> = 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 7915fdee49..c53a311008 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 @@ -305,8 +305,7 @@ class DAppAuthorizedLoginViewModelTest : StateViewModelTest, underAccountAddress: AccountAddress?, - withDetails: Boolean, - withAllMetadata: Boolean + withDetails: Boolean ): Result> { TODO("Not yet implemented") } diff --git a/core/src/main/java/rdx/works/core/domain/resources/Resource.kt b/core/src/main/java/rdx/works/core/domain/resources/Resource.kt index 23a92e47fb..504ffbd1b5 100644 --- a/core/src/main/java/rdx/works/core/domain/resources/Resource.kt +++ b/core/src/main/java/rdx/works/core/domain/resources/Resource.kt @@ -26,7 +26,6 @@ import rdx.works.core.domain.resources.metadata.claimAmount import rdx.works.core.domain.resources.metadata.claimEpoch import rdx.works.core.domain.resources.metadata.description import rdx.works.core.domain.resources.metadata.iconUrl -import rdx.works.core.domain.resources.metadata.infoUrl import rdx.works.core.domain.resources.metadata.keyImageUrl import rdx.works.core.domain.resources.metadata.name import rdx.works.core.domain.resources.metadata.poolAddress @@ -48,12 +47,6 @@ sealed class Resource { is NonFungibleResource -> currentSupply != null && behaviours != null } - val nonStandardMetadata: List by lazy { - metadata.filterNot { item -> - item.key in ExplicitMetadataKey.entries.map { it.key }.toSet() - } - } - data class FungibleResource( override val address: ResourceAddress, val ownedAmount: Decimal192?, @@ -62,7 +55,6 @@ sealed class Resource { val divisibility: Divisibility? = null, override val metadata: List = emptyList() ) : Resource(), Comparable { - override val name: String by lazy { metadata.name().orEmpty().truncate(maxNumberOfCharacters = NAME_MAX_CHARS) } @@ -79,10 +71,6 @@ sealed class Resource { metadata.iconUrl() } - val infoUrl: Uri? by lazy { - metadata.infoUrl() - } - override val validatorAddress: ValidatorAddress? by lazy { metadata.validatorAddress() } @@ -181,10 +169,6 @@ sealed class Resource { metadata.iconUrl() } - val infoUrl: Uri? by lazy { - metadata.infoUrl() - } - val tags: ImmutableList by lazy { metadata.tags().orEmpty().map { Tag.Dynamic(name = it.truncate(maxNumberOfCharacters = TAG_MAX_CHARS)) diff --git a/core/src/main/java/rdx/works/core/domain/resources/metadata/Metadata.kt b/core/src/main/java/rdx/works/core/domain/resources/metadata/Metadata.kt index c700c9b7a9..b7f44b0131 100644 --- a/core/src/main/java/rdx/works/core/domain/resources/metadata/Metadata.kt +++ b/core/src/main/java/rdx/works/core/domain/resources/metadata/Metadata.kt @@ -7,7 +7,6 @@ import kotlinx.serialization.Serializable sealed interface Metadata { val key: String val lastUpdatedAtStateVersion: Long - val isLocked: Boolean @Serializable @SerialName("primitive") @@ -17,7 +16,6 @@ sealed interface Metadata { @SerialName("value_type") val valueType: MetadataType, override val lastUpdatedAtStateVersion: Long = 0, - override val isLocked: Boolean = false ) : Metadata @Serializable @@ -26,7 +24,6 @@ sealed interface Metadata { override val key: String, val values: List, override val lastUpdatedAtStateVersion: Long = 0, - override val isLocked: Boolean = false ) : Metadata @Serializable @@ -34,8 +31,7 @@ sealed interface Metadata { data class Map( override val key: String, val values: kotlin.collections.Map, - override val lastUpdatedAtStateVersion: Long = 0L, - override val isLocked: Boolean = false + override val lastUpdatedAtStateVersion: Long = 0L ) : Metadata } diff --git a/designsystem/src/main/res/drawable/ic_lock.xml b/designsystem/src/main/res/drawable/ic_lock.xml index 73f80fc366..9d29f7c790 100644 --- a/designsystem/src/main/res/drawable/ic_lock.xml +++ b/designsystem/src/main/res/drawable/ic_lock.xml @@ -1,13 +1,14 @@ + android:width="14dp" + android:height="14dp" + android:viewportWidth="14" + android:viewportHeight="14"> + android:pathData="M0,0h14v14H0z"/> + android:pathData="M10.499,4.667h-0.584L9.915,3.5a2.918,2.918 0,0 0,-5.833 0v1.167h-0.583a1.17,1.17 0,0 0,-1.167 1.166v5.834a1.17,1.17 0,0 0,1.167 1.166h7a1.17,1.17 0,0 0,1.166 -1.166L11.665,5.833A1.17,1.17 0,0 0,10.5 4.667zM6.999,9.917A1.17,1.17 0,0 1,5.832 8.75a1.17,1.17 0,0 1,1.167 -1.167A1.17,1.17 0,0 1,8.165 8.75,1.17 1.17,0 0,1 7,9.917zM8.807,4.667L5.19,4.667L5.19,3.5a1.81,1.81 0,0 1,3.617 0v1.167z" + android:fillColor="#fff"/> +