Skip to content

Commit

Permalink
sc-29 mwr-612 xnetworking
Browse files Browse the repository at this point in the history
  • Loading branch information
AmadeyKuspakov authored and arvifox committed Jul 11, 2024
1 parent f3e529c commit 5b13793
Show file tree
Hide file tree
Showing 119 changed files with 1,184 additions and 737 deletions.
12 changes: 10 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,11 @@ android {
configurations {
all {
exclude(module = "bcprov-jdk15on")
// resolutionStrategy {
// dependencySubstitution {
// substitute(module("")).using(module(""))
// }
// }
}
}
}
Expand Down Expand Up @@ -234,8 +239,11 @@ dependencies {

implementation(libs.webSocketLibDep)

// Tests
testImplementation(project(":test_shared"))
testImplementation(libs.coroutineTestDep)
testImplementation(libs.junitDep)
testImplementation(libs.mockkDep)
testImplementation(libs.mockitoKotlinDep)
testImplementation(libs.archCoreTestDep)

kover(project(":common"))
kover(project(":common_wallet"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package jp.co.soramitsu.sora.splash.domain

import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import jp.co.soramitsu.androidfoundation.testing.MainCoroutineRule
import jp.co.soramitsu.feature_account_api.domain.interfaces.UserRepository
import jp.co.soramitsu.feature_account_api.domain.model.OnboardingState
import jp.co.soramitsu.test_shared.MainCoroutineRule
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ package jp.co.soramitsu.sora.splash.presentation
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import io.mockk.every
import io.mockk.mockkObject
import jp.co.soramitsu.androidfoundation.testing.MainCoroutineRule
import jp.co.soramitsu.androidfoundation.testing.getOrAwaitValue
import jp.co.soramitsu.common.logger.FirebaseWrapper
import jp.co.soramitsu.feature_account_api.domain.model.OnboardingState
import jp.co.soramitsu.sora.splash.domain.SplashInteractor
import jp.co.soramitsu.test_shared.MainCoroutineRule
import jp.co.soramitsu.test_shared.getOrAwaitValue
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.advanceUntilIdle
Expand Down
14 changes: 13 additions & 1 deletion common/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,16 @@ android {
buildConfigField("String", "GOOGLE_API_TOKEN", maybeWrapQuotes(secret("SORA_GOOGLE_TOKEN_PROD")))
}
}

packaging {
resources {
excludes += listOf(
"META-INF/DEPENDENCIES",
"META-INF/LICENSE.md",
"META-INF/LICENSE-notice.md",
)
}
}
}

dependencies {
Expand Down Expand Up @@ -218,7 +228,9 @@ dependencies {
implementation(libs.navigationComposeDep)
debugImplementation(libs.composeToolingDep)

testImplementation(project(":test_shared"))
testImplementation(libs.mockitoDep)
testImplementation(libs.archCoreTestDep)
testImplementation(libs.coroutineTestDep)
}

kapt {
Expand Down
111 changes: 54 additions & 57 deletions common/src/main/java/jp/co/soramitsu/common/di/modules/CommonModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,17 @@ import jp.co.soramitsu.common.util.json_decoder.JsonAccountsEncoder
import jp.co.soramitsu.common.vibration.DeviceVibrator
import jp.co.soramitsu.crypto.ed25519.Ed25519Sha3
import jp.co.soramitsu.xbackup.BackupService
import jp.co.soramitsu.xnetworking.basic.networkclient.SoramitsuHttpClientProvider
import jp.co.soramitsu.xnetworking.basic.networkclient.SoramitsuHttpClientProviderImpl
import jp.co.soramitsu.xnetworking.basic.networkclient.SoramitsuNetworkClient
import jp.co.soramitsu.xnetworking.sorawallet.blockexplorerinfo.SoraWalletBlockExplorerInfo
import jp.co.soramitsu.xnetworking.sorawallet.mainconfig.SoraRemoteConfigBuilder
import jp.co.soramitsu.xnetworking.sorawallet.mainconfig.SoraRemoteConfigProvider
import jp.co.soramitsu.xnetworking.sorawallet.tokenwhitelist.SoraTokensWhitelistManager
import jp.co.soramitsu.xnetworking.sorawallet.txhistory.client.SubQueryClientForSoraWalletFactory
import jp.co.soramitsu.xnetworking.lib.datasources.blockexplorer.api.BlockExplorerRepository
import jp.co.soramitsu.xnetworking.lib.datasources.blockexplorer.impl.BlockExplorerRepositoryImpl
import jp.co.soramitsu.xnetworking.lib.datasources.chainsconfig.api.ConfigDAO
import jp.co.soramitsu.xnetworking.lib.datasources.chainsconfig.api.data.ConfigParser
import jp.co.soramitsu.xnetworking.lib.datasources.chainsconfig.impl.SuperWalletConfigDAOImpl
import jp.co.soramitsu.xnetworking.lib.datasources.chainsconfig.impl.data.RemoteConfigParserImpl
import jp.co.soramitsu.xnetworking.lib.engines.rest.api.RestClient
import jp.co.soramitsu.xnetworking.lib.engines.rest.api.models.AbstractRestClientConfig
import jp.co.soramitsu.xnetworking.lib.engines.rest.impl.RestClientImpl
import jp.co.soramitsu.xsubstrate.encrypt.json.JsonSeedEncoder
import kotlinx.serialization.json.Json

@InstallIn(SingletonComponent::class)
@Module
Expand Down Expand Up @@ -133,91 +135,86 @@ class CommonModule {

@Singleton
@Provides
fun provideSvgDecoder(): SvgDecoder.Factory {
return SvgDecoder.Factory()
fun provideJson(): Json = Json {
prettyPrint = true
isLenient = true
ignoreUnknownKeys = true
}

@Singleton
@Provides
fun provideInAppUpdateManager(
@ApplicationContext c: Context,
sp: SoraPreferences
): InAppUpdateManager = InAppUpdateManager(c, sp)
fun provideConfigParser(
restClient: RestClient
): ConfigParser = RemoteConfigParserImpl(
restClient = restClient,
chainsRequestUrl = OptionsProvider.configXn,
)

@Singleton
@Provides
fun provideAppStateManager(): AppStateProvider = AppStateProviderImpl()
fun provideConfigDAO(configParser: ConfigParser): ConfigDAO =
SuperWalletConfigDAOImpl(configParser = configParser)

@Singleton
@Provides
fun provideCoroutineManager(): CoroutineManager =
CoroutineManager()

@Provides
fun provideWithProgress(): WithProgress = WithProgressImpl()
fun provideBlockExplorerRepository(
configDAO: ConfigDAO,
restClient: RestClient
): BlockExplorerRepository = BlockExplorerRepositoryImpl(
configDAO = configDAO,
restClient = restClient
)

@Singleton
@Provides
fun providesPushHandler(): PushHandler = PushHandler()
fun provideRestClient(json: Json): RestClient = RestClientImpl(
restClientConfig = object : AbstractRestClientConfig() {
override fun getConnectTimeoutMillis(): Long = 30_000L
override fun getOrCreateJsonConfig(): Json = json
override fun getRequestTimeoutMillis(): Long = 30_000L
override fun getSocketTimeoutMillis(): Long = 30_000L
override fun isLoggingEnabled(): Boolean = BuildConfig.DEBUG
}
)

@Singleton
@Provides
fun provideNetworkStateListener(): NetworkStateListener = NetworkStateListener()
fun provideSvgDecoder(): SvgDecoder.Factory {
return SvgDecoder.Factory()
}

@Singleton
@Provides
fun provideQrCodeGenerator(): QrCodeGenerator {
return QrCodeGenerator(Color.BLACK)
}
fun provideInAppUpdateManager(
@ApplicationContext c: Context,
sp: SoraPreferences
): InAppUpdateManager = InAppUpdateManager(c, sp)

@Singleton
@Provides
fun provideSoramitsuNetworkClient(): SoramitsuNetworkClient =
SoramitsuNetworkClient(logging = BuildConfig.DEBUG, timeout = 20000)
fun provideAppStateManager(): AppStateProvider = AppStateProviderImpl()

@Singleton
@Provides
fun provideSoraWalletBlockExplorerInfo(
client: SoramitsuNetworkClient,
soraRemoteConfigBuilder: SoraRemoteConfigBuilder,
): SoraWalletBlockExplorerInfo {
return SoraWalletBlockExplorerInfo(
networkClient = client,
soraRemoteConfigBuilder = soraRemoteConfigBuilder,
)
}
fun provideCoroutineManager(): CoroutineManager =
CoroutineManager()

@Singleton
@Provides
fun provideSoraRemoteConfigBuilder(
client: SoramitsuNetworkClient,
@ApplicationContext context: Context,
): SoraRemoteConfigBuilder {
return SoraRemoteConfigProvider(
context = context,
client = client,
commonUrl = OptionsProvider.configCommon,
mobileUrl = OptionsProvider.configMobile,
).provide()
}
fun provideWithProgress(): WithProgress = WithProgressImpl()

@Singleton
@Provides
fun provideSoramitsuHttpClientProvider(): SoramitsuHttpClientProvider =
SoramitsuHttpClientProviderImpl()
fun providesPushHandler(): PushHandler = PushHandler()

@Singleton
@Provides
fun provideSubQueryClientForSoraWalletFactory(
@ApplicationContext context: Context
): SubQueryClientForSoraWalletFactory = SubQueryClientForSoraWalletFactory(context)
fun provideNetworkStateListener(): NetworkStateListener = NetworkStateListener()

@Singleton
@Provides
fun provideSoraTokensWhitelistFetcher(
client: SoramitsuNetworkClient,
): SoraTokensWhitelistManager =
SoraTokensWhitelistManager(networkClient = client)
fun provideQrCodeGenerator(): QrCodeGenerator {
return QrCodeGenerator(Color.BLACK)
}

@Singleton
@Provides
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ object OptionsProvider {
var APPLICATION_ID: String = ""
const val configCommon = "https://config.polkaswap2.io/${FlavorOptionsProvider.typesFilePath}/common.json"
const val configMobile = "https://config.polkaswap2.io/${FlavorOptionsProvider.typesFilePath}/mobile.json"
const val configXn = "https://config.polkaswap2.io/${FlavorOptionsProvider.typesFilePath}/xn.json"
val fileProviderAuthority: String get() = "$APPLICATION_ID.soraFileProvider"
val header: String by lazy {
"$APPLICATION_ID/$CURRENT_VERSION_NAME/$CURRENT_VERSION_CODE/${BuildConfig.BUILD_TYPE}/${BuildConfig.FLAVOR}"
Expand All @@ -49,7 +50,7 @@ object OptionsProvider {
const val defaultScale = 18
const val nameByteLimit = 32
const val fiatSymbol = "$"
const val nbspace = ' '
const val nbspace = Typography.nbsp
const val euroSign = ''
const val soracard = "2.2.4"
const val soracardFiatPackageTest = "com.soracard.iban.wallet.test"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,21 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package jp.co.soramitsu.common.domain

import io.ktor.http.decodeURLPart
import io.ktor.util.decodeBase64Bytes
import javax.inject.Inject
import javax.inject.Singleton
import jp.co.soramitsu.common.io.FileManager
import jp.co.soramitsu.common.logger.FirebaseWrapper
import jp.co.soramitsu.xnetworking.sorawallet.tokenwhitelist.SoraTokensWhitelistManager
import jp.co.soramitsu.xnetworking.lib.engines.rest.api.RestClient
import jp.co.soramitsu.xnetworking.lib.engines.utils.JsonGetRequest
import jp.co.soramitsu.xnetworking.lib.engines.utils.fieldOrNull
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonArray

@Serializable
private data class TokenDto(
Expand All @@ -51,12 +56,12 @@ private data class TokenDto(

@Singleton
class WhitelistTokensManager @Inject constructor(
private val manager: SoraTokensWhitelistManager,
private val restClient: RestClient,
private val fileManager: FileManager,
) {

companion object {
private const val whitelistFileName = "whitelist_tokens.json"
private const val WHITELIST_FILE_NAME = "whitelist_tokens.json"
}

var whitelistIds: List<String> = emptyList()
Expand All @@ -71,7 +76,7 @@ class WhitelistTokensManager @Inject constructor(
}

init {
fileManager.readInternalFile(whitelistFileName)?.let {
fileManager.readInternalFile(WHITELIST_FILE_NAME)?.let {
val ids = Json.decodeFromString(ListSerializer(TokenDto.serializer()), it)
updateWhitelist(ids)
}
Expand All @@ -88,36 +93,64 @@ class WhitelistTokensManager @Inject constructor(
}

suspend fun updateWhitelistStorage() {
runCatching { manager.getTokens() }.onSuccess { dtoList ->
val ids = dtoList.map { TokenDto(it.address, it.type) }
runCatching {
restClient.get(
JsonGetRequest(
url = "https://whitelist.polkaswap2.io/whitelist.json",
responseDeserializer = JsonArray.serializer()
)
)
}.onSuccess { dtoList ->
val ids = dtoList.mapNotNull {
TokenDto(
id = it.fieldOrNull("address")
?: return@mapNotNull null,
type = it.fieldOrNull("icon")
?: return@mapNotNull null
)
}
updateWhitelist(ids)
fileManager.writeInternalFile(whitelistFileName, Json.encodeToString(ids))
fileManager.writeInternalFile(
WHITELIST_FILE_NAME,
Json.encodeToString(ids)
)

dtoList.forEach { dto ->
when (dto.rawIcon) {
is String -> {
fileManager.writeInternalCacheFile(
"${dto.address}.${dto.type}",
dto.rawIcon as String,
)
}
is ByteArray -> {
fileManager.writeInternalCacheFile(
"${dto.address}.${dto.type}",
dto.rawIcon as ByteArray,
)
}
else -> {}
val address = dto.fieldOrNull("address") ?: return@forEach
val iconField = dto.fieldOrNull("icon") ?: return@forEach

val iconRaw = iconField.substringAfter(
delimiter = ",",
missingDelimiterValue = ""
)
val iconExtension = iconField.removeSurrounding(
prefix = "data:image/",
suffix = iconRaw
)

when (iconExtension) {
"svg" -> fileManager.writeInternalCacheFile(
fileName = "$address.$iconExtension",
content = iconRaw.decodeURLPart()
)
"png" -> fileManager.writeInternalCacheFile(
fileName = "$address.$iconExtension",
content = iconRaw.decodeBase64Bytes()
)
else -> return@forEach
}
}
}.onFailure {
FirebaseWrapper.recordException(it)
if (fileManager.existsInternalFile(whitelistFileName).not()) {
updateWhitelist(
AssetHolder.getIds().map { id ->
TokenDto(id, "")
}
)
}

if (fileManager.existsInternalFile(WHITELIST_FILE_NAME))
return@onFailure

updateWhitelist(
AssetHolder.getIds().map { id ->
TokenDto(id, "")
}
)
}
}
}
Loading

0 comments on commit 5b13793

Please sign in to comment.