Skip to content

Commit

Permalink
PERA-1354 :: Asset cache implementation (#89)
Browse files Browse the repository at this point in the history
  • Loading branch information
mitsinsar authored Dec 23, 2024
1 parent 5af4407 commit 0e36369
Show file tree
Hide file tree
Showing 155 changed files with 6,143 additions and 11 deletions.
2 changes: 2 additions & 0 deletions composeTestApp/src/androidMain/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<uses-permission android:name="android.permission.INTERNET"/>

<application
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="false"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright 2022 Pera Wallet, LDA
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/

package com.algorand.common.foundation.network

import io.ktor.client.HttpClient
import io.ktor.client.engine.okhttp.OkHttp
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.client.plugins.logging.ANDROID
import io.ktor.client.plugins.logging.LogLevel
import io.ktor.client.plugins.logging.Logger
import io.ktor.client.plugins.logging.Logging
import io.ktor.serialization.kotlinx.json.json

internal actual fun getAlgodHttpClient(algodInterceptorPlugin: AlgodInterceptorPlugin): HttpClient {
return HttpClient(OkHttp) {
install(Logging) {
logger = Logger.ANDROID
level = LogLevel.BODY
}
install(ContentNegotiation) {
json(PeraJsonNegotiation)
}
install(algodInterceptorPlugin)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/*
* Copyright 2022 Pera Wallet, LDA
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/

package com.algorand.common.asset.data.mapper.entity

import com.algorand.common.asset.data.database.model.AssetDetailEntity
import com.algorand.common.asset.data.database.model.VerificationTierEntity
import com.algorand.common.asset.data.model.AssetCreatorResponse
import com.algorand.common.asset.data.model.AssetResponse
import com.algorand.common.testing.peraFixture
import io.mockk.every
import io.mockk.mockk
import java.math.BigDecimal
import java.math.BigInteger
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNull
import org.junit.Test

internal class AssetAssetInfoEntityMapperImplTest {

private val verificationTierEntityMapper: VerificationTierEntityMapper = mockk()

private val sut = AssetDetailEntityMapperImpl(verificationTierEntityMapper)

@Test
fun `EXPECT response to be mapped to entity successfully`() {
every { verificationTierEntityMapper(null) } returns VerificationTierEntity.UNKNOWN
val result = sut(ASSET_DETAIL_RESPONSE)

assertEquals(ASSET_DETAIL_ENTITY, result)
}

@Test
fun `EXPECT null WHEN assetId is null`() {
val assetDetailResponse = peraFixture<AssetResponse>().copy(assetId = null)

val result = sut(assetDetailResponse)

assertNull(result)
}

@Test
fun `EXPECT default values when optional fields are null`() {
every { verificationTierEntityMapper(null) } returns VerificationTierEntity.UNKNOWN
val assetDetailResponse = peraFixture<AssetResponse>().copy(
assetId = 1L,
isAvailableOnDiscoverMobile = null,
maxSupply = null,
totalSupply = null,
fractionDecimals = null,
verificationTier = null
)

val result = sut(assetDetailResponse)

assertEquals(0, result?.decimals)
assertEquals("0", result?.maxSupply)
assertEquals("0", result?.totalSupply)
assertFalse(result?.availableOnDiscoverMobile!!)
}

companion object {
private val ASSET_DETAIL_RESPONSE = AssetResponse(
assetId = 1L,
fullName = "fullName",
shortName = "shortName",
fractionDecimals = 2,
usdValue = "10",
maxSupply = "10",
explorerUrl = "explorerUrl",
projectUrl = "projectUrl",
projectName = "projectName",
logoSvgUri = "logoSvgUri",
logoUri = "logoUri",
description = "description",
totalSupply = "10",
url = "url",
telegramUrl = "telegramUrl",
twitterUsername = "twitterUsername",
discordUrl = "discordUrl",
isAvailableOnDiscoverMobile = true,
last24HoursAlgoPriceChangePercentage = "10",
verificationTier = null,
assetCreator = AssetCreatorResponse(
publicKey = "publicKey",
id = 1L,
isVerifiedAssetCreator = true
),
collectible = null
)

private val ASSET_DETAIL_ENTITY = AssetDetailEntity(
assetId = 1L,
name = "fullName",
unitName = "shortName",
decimals = 2,
usdValue = "10",
maxSupply = "10",
explorerUrl = "explorerUrl",
projectUrl = "projectUrl",
projectName = "projectName",
logoSvgUrl = "logoSvgUri",
logoUrl = "logoUri",
description = "description",
totalSupply = "10",
url = "url",
telegramUrl = "telegramUrl",
twitterUsername = "twitterUsername",
discordUrl = "discordUrl",
availableOnDiscoverMobile = true,
last24HoursAlgoPriceChangePercentage = "10",
verificationTier = VerificationTierEntity.UNKNOWN,
assetCreatorAddress = "publicKey",
assetCreatorId = 1L,
isVerifiedAssetCreator = true
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright 2022 Pera Wallet, LDA
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/

package com.algorand.common.asset.data.mapper.entity

import com.algorand.common.asset.data.database.model.CollectibleEntity
import com.algorand.common.asset.data.database.model.CollectibleMediaTypeEntity.MIXED
import com.algorand.common.asset.data.database.model.CollectibleStandardTypeEntity.ARC_3
import com.algorand.common.asset.data.model.AssetResponse
import com.algorand.common.asset.data.model.collectible.CollectibleResponse
import com.algorand.common.testing.peraFixture
import io.mockk.every
import io.mockk.mockk
import org.junit.Assert.assertEquals
import org.junit.Test

internal class CollectibleEntityMapperImplTest {

private val collectibleStandardEntityMapper: CollectibleStandardTypeEntityMapper = mockk()
private val collectibleMediaTypeEntityMapper: CollectibleMediaTypeEntityMapper = mockk()

private val sut = CollectibleEntityMapperImpl(
collectibleStandardEntityMapper,
collectibleMediaTypeEntityMapper
)

@Test
fun `EXPECT response to be mapped to entity successfully`() {
val collectibleResponse = peraFixture<CollectibleResponse>()
val assetDetailResponse = peraFixture<AssetResponse>().copy(
assetId = 1L,
collectible = collectibleResponse
)
every { collectibleStandardEntityMapper(collectibleResponse.standard) } returns ARC_3
every { collectibleMediaTypeEntityMapper(collectibleResponse.mediaType) } returns MIXED

val result = sut(assetDetailResponse)

val expected = CollectibleEntity(
collectibleAssetId = 1L,
standardType = ARC_3,
mediaType = MIXED,
primaryImageUrl = collectibleResponse.primaryImageUrl,
title = collectibleResponse.title,
description = collectibleResponse.description,
collectionId = collectibleResponse.collection?.collectionId,
collectionName = collectibleResponse.collection?.collectionName,
collectionDescription = collectibleResponse.collection?.collectionDescription
)
assertEquals(expected, result)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright 2022 Pera Wallet, LDA
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/

package com.algorand.common.asset.data.mapper.entity

import com.algorand.common.asset.data.database.model.CollectibleMediaEntity
import com.algorand.common.asset.data.database.model.CollectibleMediaTypeEntity.IMAGE
import com.algorand.common.asset.data.database.model.CollectibleMediaTypeExtensionEntity.GIF
import com.algorand.common.asset.data.model.AssetResponse
import com.algorand.common.asset.data.model.collectible.CollectibleMediaResponse
import com.algorand.common.asset.data.model.collectible.CollectibleMediaTypeExtensionResponse
import com.algorand.common.asset.data.model.collectible.CollectibleMediaTypeResponse
import com.algorand.common.asset.data.model.collectible.CollectibleResponse
import com.algorand.common.testing.peraFixture
import io.mockk.every
import io.mockk.mockk
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test

internal class CollectibleMediaEntityMapperImplTest {

private val collectibleMediaTypeEntityMapper: CollectibleMediaTypeEntityMapper = mockk()
private val collectibleMediaTypeExtensionEntityMapper: CollectibleMediaTypeExtensionEntityMapper = mockk()

private val sut = CollectibleMediaEntityMapperImpl(
collectibleMediaTypeEntityMapper,
collectibleMediaTypeExtensionEntityMapper,
)

@Test
fun `EXPECT null WHEN asset id is null`() {
val assetDetailResponse = peraFixture<AssetResponse>().copy(assetId = null)

val result = sut(assetDetailResponse)

assertTrue(result.isEmpty())
}

@Test
fun `EXPECT response to be mapped to entity successfully`() {
val mediaTypeResponse = peraFixture<CollectibleMediaTypeResponse>()
val mediaTypeExtensionResponse = peraFixture<CollectibleMediaTypeExtensionResponse>()
val collectibleMediaResponse = peraFixture<CollectibleMediaResponse>().copy(
mediaType = mediaTypeResponse,
mediaTypeExtension = mediaTypeExtensionResponse
)
val collectibleResponse = peraFixture<CollectibleResponse>().copy(
collectibleMedias = listOf(collectibleMediaResponse)
)
val assetDetailResponse = peraFixture<AssetResponse>().copy(
assetId = 1L,
collectible = collectibleResponse
)
every { collectibleMediaTypeEntityMapper(mediaTypeResponse) } returns IMAGE
every { collectibleMediaTypeExtensionEntityMapper(mediaTypeExtensionResponse) } returns GIF

val result = sut(assetDetailResponse)

val expected = listOf(
CollectibleMediaEntity(
collectibleAssetId = 1L,
mediaType = IMAGE,
downloadUrl = collectibleMediaResponse.downloadUrl,
previewUrl = collectibleMediaResponse.previewUrl,
mediaTypeExtension = GIF
)
)
assertEquals(expected, result)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright 2022 Pera Wallet, LDA
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/

package com.algorand.common.asset.data.mapper.entity

import com.algorand.common.asset.data.database.model.CollectibleMediaTypeEntity
import com.algorand.common.asset.data.model.collectible.CollectibleMediaTypeResponse
import org.junit.Assert.assertEquals
import org.junit.Test

internal class CollectibleMediaTypeEntityMapperImplTest {

private val sut = CollectibleMediaTypeEntityMapperImpl()

@Test
fun `EXPECT response to be mapped to entity successfully`() {
val responseList = listOf(
CollectibleMediaTypeResponse.IMAGE,
CollectibleMediaTypeResponse.VIDEO,
CollectibleMediaTypeResponse.MIXED,
CollectibleMediaTypeResponse.AUDIO,
CollectibleMediaTypeResponse.UNKNOWN,
null
)

val result = responseList.map { sut(it) }

val expected = listOf(
CollectibleMediaTypeEntity.IMAGE,
CollectibleMediaTypeEntity.VIDEO,
CollectibleMediaTypeEntity.MIXED,
CollectibleMediaTypeEntity.AUDIO,
CollectibleMediaTypeEntity.UNKNOWN,
CollectibleMediaTypeEntity.UNKNOWN
)
assertEquals(expected, result)
}
}
Loading

0 comments on commit 0e36369

Please sign in to comment.