fun chainRegistrySyncUp()
+
+ suspend fun getSingleAssetPriceCoingecko(priceId: String, currency: String): BigDecimal?
}
diff --git a/feature-wallet-api/src/main/java/jp/co/soramitsu/wallet/impl/domain/validation/EnoughToPayFeesValidation.kt b/feature-wallet-api/src/main/java/jp/co/soramitsu/wallet/impl/domain/validation/EnoughToPayFeesValidation.kt
index 52050bea96..ef82bd9d37 100644
--- a/feature-wallet-api/src/main/java/jp/co/soramitsu/wallet/impl/domain/validation/EnoughToPayFeesValidation.kt
+++ b/feature-wallet-api/src/main/java/jp/co/soramitsu/wallet/impl/domain/validation/EnoughToPayFeesValidation.kt
@@ -1,13 +1,14 @@
package jp.co.soramitsu.wallet.impl.domain.validation
-import java.math.BigDecimal
import jp.co.soramitsu.account.api.domain.interfaces.AccountRepository
+import jp.co.soramitsu.common.utils.orZero
import jp.co.soramitsu.common.validation.DefaultFailureLevel
import jp.co.soramitsu.common.validation.Validation
import jp.co.soramitsu.common.validation.ValidationStatus
import jp.co.soramitsu.runtime.ext.accountIdOf
import jp.co.soramitsu.runtime.multiNetwork.chain.model.Chain
import jp.co.soramitsu.wallet.impl.domain.interfaces.WalletRepository
+import java.math.BigDecimal
class EnoughToPayFeesValidation(
private val feeExtractor: AmountProducer
,
@@ -39,7 +40,7 @@ fun
EnoughToPayFeesValidation.Companion.assetBalanceProducer(
val accountId = chain.accountIdOf(originAddressExtractor(payload))
val meta = accountRepository.getSelectedMetaAccount()
- val asset = walletRepository.getAsset(meta.id, accountId, chainAssetExtractor(payload), chain.minSupportedVersion)!!
+ val asset = walletRepository.getAsset(meta.id, accountId, chainAssetExtractor(payload), chain.minSupportedVersion)
- asset.availableForStaking
+ asset?.availableForStaking.orZero()
}
diff --git a/feature-wallet-impl/build.gradle b/feature-wallet-impl/build.gradle
index 0b34a690d1..b4e0a18201 100644
--- a/feature-wallet-impl/build.gradle
+++ b/feature-wallet-impl/build.gradle
@@ -18,9 +18,12 @@ android {
buildConfigField "String", "RAMP_TOKEN", "\"4bk3yhfrg99fer764bo7egrqmxbfene7gbrpwmp3\""
buildConfigField "String", "RAMP_HOST", "\"ri-widget-staging.firebaseapp.com\""
- buildConfigField "String", "MOONPAY_PRIVATE_KEY", readSecret("MOONPAY_TEST_SECRET")
+ buildConfigField "String", "MOONPAY_PRIVATE_KEY", readSecretInQuotes("MOONPAY_TEST_SECRET")
buildConfigField "String", "MOONPAY_HOST", "\"buy-staging.moonpay.com\""
buildConfigField "String", "MOONPAY_PUBLIC_KEY", "\"pk_test_DMRuyL6Nf1qc9OzjPBmCFBeCGkFwiZs0\""
+
+ buildConfigField "String", "SORA_CONFIG_COMMON", "\"https://config.polkaswap2.io/stage/common.json\""
+ buildConfigField "String", "SORA_CONFIG_MOBILE", "\"https://config.polkaswap2.io/stage/mobile.json\""
}
buildTypes {
@@ -28,9 +31,12 @@ android {
buildConfigField "String", "RAMP_TOKEN", "\"3quzr4e6wdyccndec8jzjebzar5kxxzfy2f3us5k\""
buildConfigField "String", "RAMP_HOST", "\"buy.ramp.network\""
- buildConfigField "String", "MOONPAY_PRIVATE_KEY", readSecret("MOONPAY_PRODUCTION_SECRET")
+ buildConfigField "String", "MOONPAY_PRIVATE_KEY", readSecretInQuotes("MOONPAY_PRODUCTION_SECRET")
buildConfigField "String", "MOONPAY_PUBLIC_KEY", "\"pk_live_Boi6Rl107p7XuJWBL8GJRzGWlmUSoxbz\""
buildConfigField "String", "MOONPAY_HOST", "\"buy.moonpay.com\""
+
+ buildConfigField "String", "SORA_CONFIG_COMMON", "\"https://config.polkaswap2.io/prod/common.json\""
+ buildConfigField "String", "SORA_CONFIG_MOBILE", "\"https://config.polkaswap2.io/prod/mobile.json\""
}
}
@@ -63,6 +69,8 @@ dependencies {
implementation project(':feature-account-api')
implementation project(':feature-account-impl')
implementation project(':runtime')
+ implementation project(':feature-soracard-api')
+ implementation project(':feature-soracard-impl')
implementation kotlinDep
@@ -111,6 +119,8 @@ dependencies {
implementation jnaDep
implementation beaconDep, withoutJna
+ implementation soraCardDep, withoutBouncycastle
+
implementation shimmerDep
implementation compose
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/feature_wallet_impl/di/WalletFeatureComponent.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/feature_wallet_impl/di/WalletFeatureComponent.kt
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/feature_wallet_impl/di/WalletFeatureDependencies.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/feature_wallet_impl/di/WalletFeatureDependencies.kt
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/historySource/HistorySourceProvider.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/historySource/HistorySourceProvider.kt
index 603b8d21f0..1d6311abc6 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/historySource/HistorySourceProvider.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/historySource/HistorySourceProvider.kt
@@ -4,18 +4,20 @@ import jp.co.soramitsu.runtime.multiNetwork.ChainRegistry
import jp.co.soramitsu.runtime.multiNetwork.chain.model.Chain
import jp.co.soramitsu.wallet.impl.data.network.subquery.OperationsHistoryApi
import jp.co.soramitsu.xnetworking.networkclient.SoramitsuNetworkClient
+import jp.co.soramitsu.xnetworking.sorawallet.mainconfig.SoraRemoteConfigBuilder
import jp.co.soramitsu.xnetworking.txhistory.client.sorawallet.SubQueryClientForSoraWalletFactory
class HistorySourceProvider(
private val walletOperationsApi: OperationsHistoryApi,
private val chainRegistry: ChainRegistry,
private val soramitsuNetworkClient: SoramitsuNetworkClient,
- private val soraSubqueryFactory: SubQueryClientForSoraWalletFactory
+ private val soraSubqueryFactory: SubQueryClientForSoraWalletFactory,
+ private val soraRemoteConfigBuilder: SoraRemoteConfigBuilder
) {
operator fun invoke(historyUrl: String, historyType: Chain.ExternalApi.Section.Type): HistorySource? {
return when (historyType) {
Chain.ExternalApi.Section.Type.SUBQUERY -> SubqueryHistorySource(walletOperationsApi, chainRegistry, historyUrl)
- Chain.ExternalApi.Section.Type.SORA -> SoraHistorySource(soramitsuNetworkClient, soraSubqueryFactory, historyUrl)
+ Chain.ExternalApi.Section.Type.SORA -> SoraHistorySource(soramitsuNetworkClient, soraSubqueryFactory, soraRemoteConfigBuilder)
Chain.ExternalApi.Section.Type.SUBSQUID -> SubsquidHistorySource(walletOperationsApi, historyUrl)
Chain.ExternalApi.Section.Type.GIANTSQUID -> GiantsquidHistorySource(walletOperationsApi, historyUrl)
else -> null
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/historySource/SoraHistorySource.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/historySource/SoraHistorySource.kt
index 52077fc119..c1b5692258 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/historySource/SoraHistorySource.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/historySource/SoraHistorySource.kt
@@ -7,6 +7,7 @@ import jp.co.soramitsu.wallet.impl.data.mappers.toOperation
import jp.co.soramitsu.wallet.impl.domain.interfaces.TransactionFilter
import jp.co.soramitsu.wallet.impl.domain.model.Operation
import jp.co.soramitsu.xnetworking.networkclient.SoramitsuNetworkClient
+import jp.co.soramitsu.xnetworking.sorawallet.mainconfig.SoraRemoteConfigBuilder
import jp.co.soramitsu.xnetworking.txhistory.TxHistoryItem
import jp.co.soramitsu.xnetworking.txhistory.TxHistoryResult
import jp.co.soramitsu.xnetworking.txhistory.client.sorawallet.SubQueryClientForSoraWalletFactory
@@ -14,7 +15,7 @@ import jp.co.soramitsu.xnetworking.txhistory.client.sorawallet.SubQueryClientFor
class SoraHistorySource(
private val soramitsuNetworkClient: SoramitsuNetworkClient,
private val soraSubqueryFactory: SubQueryClientForSoraWalletFactory,
- private val url: String
+ private val soraRemoteConfigBuilder: SoraRemoteConfigBuilder
) : HistorySource {
override suspend fun getOperations(
pageSize: Int,
@@ -28,15 +29,14 @@ class SoraHistorySource(
val soraStartPage = 1L
val page = cursor?.toLongOrNull() ?: soraStartPage
- val subQueryClientForSora = soraSubqueryFactory.create(soramitsuNetworkClient, url, pageSize)
+ val subQueryClientForSora = soraSubqueryFactory.create(soramitsuNetworkClient, pageSize, soraRemoteConfigBuilder)
- val soraHistory: TxHistoryResult = subQueryClientForSora.getTransactionHistoryPaged(
+ val soraHistory: TxHistoryResult? = subQueryClientForSora.getTransactionHistoryPaged(
accountAddress,
- chain.name,
page
)
- val soraHistoryItems: List = soraHistory.items
+ val soraHistoryItems: List = soraHistory?.items.orEmpty()
val soraOperations = soraHistoryItems.mapNotNull { it.toOperation(chain, chainAsset, accountAddress, filters) }
return CursorPage(page.inc().toString(), soraOperations)
}
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/repository/WalletRepositoryImpl.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/repository/WalletRepositoryImpl.kt
index 18b3a3a8ff..e83bb90ac0 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/repository/WalletRepositoryImpl.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/repository/WalletRepositoryImpl.kt
@@ -1,8 +1,6 @@
package jp.co.soramitsu.wallet.impl.data.repository
import com.opencsv.CSVReaderHeaderAware
-import java.math.BigDecimal
-import java.math.BigInteger
import jp.co.soramitsu.account.api.domain.model.MetaAccount
import jp.co.soramitsu.account.api.domain.model.accountId
import jp.co.soramitsu.common.data.network.HttpExceptionHandler
@@ -48,6 +46,8 @@ import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.withContext
+import java.math.BigDecimal
+import java.math.BigInteger
class WalletRepositoryImpl(
private val substrateSource: SubstrateRemoteSource,
@@ -64,6 +64,12 @@ class WalletRepositoryImpl(
private val remoteConfigFetcher: RemoteConfigFetcher
) : WalletRepository, UpdatesProviderUi by updatesMixin {
+ companion object {
+ private const val COINGECKO_REQUEST_DELAY_MILLIS = 60 * 1000
+ }
+
+ private val coingeckoCache = mutableMapOf>>()
+
override fun assetsFlow(meta: MetaAccount): Flow> {
return combine(
chainRegistry.chainsById,
@@ -357,6 +363,25 @@ class WalletRepositoryImpl(
)
}
+ override suspend fun getSingleAssetPriceCoingecko(priceId: String, currency: String): BigDecimal? {
+ coingeckoCache[priceId]?.get(currency)?.let { (cacheUntilMillis, cachedValue) ->
+ if (System.currentTimeMillis() <= cacheUntilMillis) {
+ return cachedValue
+ }
+ }
+ val apiValue = apiCall {
+ coingeckoApi.getSingleAssetPrice(priceIds = priceId, currency = currency)
+ }.getOrDefault(priceId, null)?.getOrDefault(currency, null)?.toBigDecimal()
+
+ apiValue?.let {
+ val currencyMap = coingeckoCache[priceId] ?: mutableMapOf()
+ val cacheUntilMillis = System.currentTimeMillis() + COINGECKO_REQUEST_DELAY_MILLIS
+ currencyMap[currency] = cacheUntilMillis to apiValue
+ coingeckoCache[priceId] = currencyMap
+ }
+ return apiValue
+ }
+
private suspend fun getAssetPriceCoingecko(vararg priceId: String, currencyId: String): Map> {
return apiCall { coingeckoApi.getAssetPrice(priceId.joinToString(","), currencyId, true) }
}
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/di/WalletFeatureModule.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/di/WalletFeatureModule.kt
index 1945288a74..cae1623566 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/di/WalletFeatureModule.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/di/WalletFeatureModule.kt
@@ -76,6 +76,8 @@ import jp.co.soramitsu.wallet.impl.presentation.balance.assetActions.buy.BuyMixi
import jp.co.soramitsu.wallet.impl.presentation.send.SendSharedState
import jp.co.soramitsu.wallet.impl.presentation.transaction.filter.HistoryFiltersProvider
import jp.co.soramitsu.xnetworking.networkclient.SoramitsuNetworkClient
+import jp.co.soramitsu.xnetworking.sorawallet.mainconfig.SoraRemoteConfigBuilder
+import jp.co.soramitsu.xnetworking.sorawallet.mainconfig.SoraRemoteConfigProvider
import jp.co.soramitsu.xnetworking.txhistory.client.sorawallet.SubQueryClientForSoraWalletFactory
import javax.inject.Named
import javax.inject.Singleton
@@ -183,12 +185,14 @@ class WalletFeatureModule {
walletOperationsHistoryApi: OperationsHistoryApi,
chainRegistry: ChainRegistry,
soramitsuNetworkClient: SoramitsuNetworkClient,
- subQueryClientForSoraWalletFactory: SubQueryClientForSoraWalletFactory
+ subQueryClientForSoraWalletFactory: SubQueryClientForSoraWalletFactory,
+ soraRemoteConfigBuilder: SoraRemoteConfigBuilder
) = HistorySourceProvider(
walletOperationsHistoryApi,
chainRegistry,
soramitsuNetworkClient,
- subQueryClientForSoraWalletFactory
+ subQueryClientForSoraWalletFactory,
+ soraRemoteConfigBuilder
)
@Provides
@@ -196,12 +200,12 @@ class WalletFeatureModule {
walletRepository: WalletRepository,
addressBookRepository: AddressBookRepository,
accountRepository: AccountRepository,
+ historyRepository: HistoryRepository,
chainRegistry: ChainRegistry,
fileProvider: FileProvider,
preferences: Preferences,
selectedFiat: SelectedFiat,
- updatesMixin: UpdatesMixin,
- historyRepository: HistoryRepository
+ updatesMixin: UpdatesMixin
): WalletInteractor = WalletInteractorImpl(
walletRepository,
addressBookRepository,
@@ -359,4 +363,18 @@ class WalletFeatureModule {
fun provideSubQueryClientForSoraWalletFactory(
@ApplicationContext context: Context
): SubQueryClientForSoraWalletFactory = SubQueryClientForSoraWalletFactory(context)
+
+ @Singleton
+ @Provides
+ fun provideSoraRemoteConfigBuilder(
+ client: SoramitsuNetworkClient,
+ @ApplicationContext context: Context
+ ): SoraRemoteConfigBuilder {
+ return SoraRemoteConfigProvider(
+ context = context,
+ client = client,
+ commonUrl = BuildConfig.SORA_CONFIG_COMMON,
+ mobileUrl = BuildConfig.SORA_CONFIG_MOBILE
+ ).provide()
+ }
}
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/domain/WalletInteractorImpl.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/domain/WalletInteractorImpl.kt
index db740012d4..360b24a4ba 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/domain/WalletInteractorImpl.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/domain/WalletInteractorImpl.kt
@@ -1,7 +1,5 @@
package jp.co.soramitsu.wallet.impl.domain
-import java.math.BigDecimal
-import java.math.BigInteger
import jp.co.soramitsu.account.api.domain.interfaces.AccountRepository
import jp.co.soramitsu.account.api.domain.model.MetaAccount
import jp.co.soramitsu.account.api.domain.model.accountId
@@ -48,9 +46,13 @@ import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.withIndex
import kotlinx.coroutines.withContext
+import java.math.BigDecimal
+import java.math.BigInteger
private const val QR_PREFIX_SUBSTRATE = "substrate"
private const val PREFS_WALLET_SELECTED_CHAIN_ID = "wallet_selected_chain_id"
+private const val PREFS_SORA_CARD_HIDDEN_SESSIONS_COUNT = "prefs_sora_card_hidden_sessions_count"
+private const val SORA_CARD_HIDDEN_SESSIONS_LIMIT = 5
class WalletInteractorImpl(
private val walletRepository: WalletRepository,
@@ -119,7 +121,15 @@ class WalletInteractorImpl(
val metaAccount = accountRepository.getSelectedMetaAccount()
val (chain, chainAsset) = chainRegistry.chainWithAsset(chainId, chainAssetId)
- return walletRepository.getAsset(metaAccount.id, metaAccount.accountId(chain)!!, chainAsset, chain.minSupportedVersion)!!
+ val accountId = metaAccount.accountId(chain)!!
+ return walletRepository.getAsset(metaAccount.id, accountId, chainAsset, chain.minSupportedVersion)
+ ?: Asset.createEmpty(
+ chainAsset = chainAsset,
+ metaId = metaAccount.id,
+ accountId = accountId,
+ minSupportedVersion = chain.minSupportedVersion,
+ enabled = chain.nodes.isNotEmpty()
+ )
}
override fun operationsFirstPageFlow(chainId: ChainId, chainAssetId: String): Flow {
@@ -328,6 +338,25 @@ class WalletInteractorImpl(
return existingChain?.id
}
+ override fun isShowGetSoraCard(): Boolean =
+ preferences.getInt(PREFS_SORA_CARD_HIDDEN_SESSIONS_COUNT, 0) <= 0
+
+ override fun observeIsShowSoraCard(): Flow =
+ preferences.intFlow(PREFS_SORA_CARD_HIDDEN_SESSIONS_COUNT, 0).map { it <= 0 }
+
+ override fun hideSoraCard() {
+ preferences.putInt(PREFS_SORA_CARD_HIDDEN_SESSIONS_COUNT, SORA_CARD_HIDDEN_SESSIONS_LIMIT)
+ }
+
+ override fun decreaseSoraCardHiddenSessions() {
+ val newCount = preferences.getInt(PREFS_SORA_CARD_HIDDEN_SESSIONS_COUNT, 0) - 1
+ if (newCount <= 0) {
+ preferences.removeField(PREFS_SORA_CARD_HIDDEN_SESSIONS_COUNT)
+ } else {
+ preferences.putInt(PREFS_SORA_CARD_HIDDEN_SESSIONS_COUNT, newCount)
+ }
+ }
+
override suspend fun getEquilibriumAccountInfo(asset: Chain.Asset, accountId: AccountId): EqAccountInfo? =
walletRepository.getEquilibriumAccountInfo(asset, accountId)
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/WalletRouter.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/WalletRouter.kt
index 514c225a5d..72b6b64b9c 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/WalletRouter.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/WalletRouter.kt
@@ -30,7 +30,7 @@ interface WalletRouter : SecureRouter, WalletRouterApi {
fun openSend(assetPayload: AssetPayload?, initialSendToAddress: String? = null, currencyId: String? = null)
- fun openSwapTokensScreen(assetPayload: AssetPayload)
+ fun openSwapTokensScreen(assetId: String, chainId: String)
fun openSelectChain(assetId: String, chainId: ChainId? = null, chooserMode: Boolean = true)
@@ -105,6 +105,8 @@ interface WalletRouter : SecureRouter, WalletRouterApi {
fun openNetworkIssues()
+ fun openGetSoraCard()
+
fun openOptionsAddAccount(payload: AddAccountBottomSheet.Payload)
fun openAlert(payload: AlertViewState)
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/assetselector/AssetSelectContent.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/assetselector/AssetSelectContent.kt
index 581491c543..c111a0a33c 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/assetselector/AssetSelectContent.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/assetselector/AssetSelectContent.kt
@@ -34,7 +34,6 @@ import jp.co.soramitsu.common.compose.component.Image
import jp.co.soramitsu.common.compose.component.MarginHorizontal
import jp.co.soramitsu.common.compose.component.MarginVertical
import jp.co.soramitsu.common.compose.component.getImageRequest
-import jp.co.soramitsu.common.compose.theme.FearlessThemeBlackBg
import jp.co.soramitsu.common.compose.theme.black2
import jp.co.soramitsu.common.compose.theme.black4
import jp.co.soramitsu.common.compose.theme.gray2
@@ -208,17 +207,15 @@ private fun SelectAssetScreenPreview() {
assets = items,
searchQuery = null
)
- FearlessThemeBlackBg {
- Column(
- Modifier.background(black4)
- ) {
- AssetSelectContent(
- state = state,
- callback = object : AssetSelectContentInterface {
- override fun onAssetSelected(assetItemState: AssetItemState) {}
- override fun onSearchInput(input: String) {}
- }
- )
- }
+ Column(
+ Modifier.background(black4)
+ ) {
+ AssetSelectContent(
+ state = state,
+ callback = object : AssetSelectContentInterface {
+ override fun onAssetSelected(assetItemState: AssetItemState) {}
+ override fun onSearchInput(input: String) {}
+ }
+ )
}
}
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/chainselector/ChainSelectContent.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/chainselector/ChainSelectContent.kt
index 096b7399d2..f921058125 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/chainselector/ChainSelectContent.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/chainselector/ChainSelectContent.kt
@@ -32,7 +32,6 @@ import jp.co.soramitsu.common.compose.component.Image
import jp.co.soramitsu.common.compose.component.MarginHorizontal
import jp.co.soramitsu.common.compose.component.MarginVertical
import jp.co.soramitsu.common.compose.component.getImageRequest
-import jp.co.soramitsu.common.compose.theme.FearlessThemeBlackBg
import jp.co.soramitsu.common.compose.theme.black4
import jp.co.soramitsu.common.utils.clickableWithNoIndication
import jp.co.soramitsu.feature_wallet_impl.R
@@ -212,11 +211,9 @@ private fun SelectChainScreenPreview() {
selectedChainId = null,
searchQuery = null
)
- FearlessThemeBlackBg {
- Column(
- Modifier.background(black4)
- ) {
- ChainSelectContent(state = state)
- }
+ Column(
+ Modifier.background(black4)
+ ) {
+ ChainSelectContent(state = state)
}
}
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/detail/BalanceDetailViewModel.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/detail/BalanceDetailViewModel.kt
index afe7a8fa54..5d4b59fca0 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/detail/BalanceDetailViewModel.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/detail/BalanceDetailViewModel.kt
@@ -276,7 +276,7 @@ class BalanceDetailViewModel @Inject constructor(
}
private fun openSwapTokensScreen(assetPayload: AssetPayload) {
- router.openSwapTokensScreen(assetPayload)
+ router.openSwapTokensScreen(assetPayload.chainAssetId, assetPayload.chainId)
}
private fun receiveClicked(assetPayload: AssetPayload) {
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/list/BalanceListFragment.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/list/BalanceListFragment.kt
index 0181bb7991..97a5d0df0a 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/list/BalanceListFragment.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/list/BalanceListFragment.kt
@@ -19,7 +19,6 @@ import androidx.lifecycle.lifecycleScope
import coil.ImageLoader
import com.journeyapps.barcodescanner.ScanOptions
import dagger.hilt.android.AndroidEntryPoint
-import javax.inject.Inject
import jp.co.soramitsu.common.PLAY_MARKET_APP_URI
import jp.co.soramitsu.common.PLAY_MARKET_BROWSER_URI
import jp.co.soramitsu.common.base.BaseComposeFragment
@@ -37,8 +36,11 @@ import jp.co.soramitsu.common.utils.hideKeyboard
import jp.co.soramitsu.common.view.bottomSheet.AlertBottomSheet
import jp.co.soramitsu.common.view.bottomSheet.list.dynamic.DynamicListBottomSheet
import jp.co.soramitsu.feature_wallet_impl.R
+import jp.co.soramitsu.oauth.base.sdk.contract.SoraCardResult
+import jp.co.soramitsu.oauth.base.sdk.signin.SoraCardSignInContract
import jp.co.soramitsu.wallet.impl.presentation.common.askPermissionsSafely
import kotlinx.coroutines.launch
+import javax.inject.Inject
@AndroidEntryPoint
class BalanceListFragment : BaseComposeFragment() {
@@ -54,6 +56,23 @@ class BalanceListFragment : BaseComposeFragment() {
}
}
+ private val soraCardSignIn = registerForActivityResult(
+ SoraCardSignInContract()
+ ) { result ->
+ when (result) {
+ is SoraCardResult.Failure -> {}
+ is SoraCardResult.Canceled -> {}
+ is SoraCardResult.Success -> {
+ viewModel.updateSoraCardInfo(
+ accessToken = result.accessToken,
+ refreshToken = result.refreshToken,
+ accessTokenExpirationTime = result.accessTokenExpirationTime,
+ kycStatus = result.status.toString()
+ )
+ }
+ }
+ }
+
@OptIn(ExperimentalMaterialApi::class)
@Composable
override fun Content(padding: PaddingValues, scrollState: ScrollState, modalBottomSheetState: ModalBottomSheetState) {
@@ -99,6 +118,9 @@ class BalanceListFragment : BaseComposeFragment() {
viewModel.showFiatChooser.observeEvent(::showFiatChooser)
viewModel.showUnsupportedChainAlert.observeEvent { showUnsupportedChainAlert() }
viewModel.openPlayMarket.observeEvent { openPlayMarket() }
+ viewModel.launchSoraCardSignIn.observeEvent { contractData ->
+ soraCardSignIn.launch(contractData)
+ }
}
fun initViews() {
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/list/BalanceListViewModel.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/list/BalanceListViewModel.kt
index b4751f4881..0157460628 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/list/BalanceListViewModel.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/list/BalanceListViewModel.kt
@@ -10,6 +10,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import jp.co.soramitsu.account.api.domain.interfaces.AccountRepository
import jp.co.soramitsu.account.api.presentation.actions.AddAccountBottomSheet
import jp.co.soramitsu.common.AlertViewState
+import jp.co.soramitsu.common.BuildConfig
import jp.co.soramitsu.common.address.AddressIconGenerator
import jp.co.soramitsu.common.address.AddressModel
import jp.co.soramitsu.common.address.createAddressModel
@@ -29,7 +30,6 @@ import jp.co.soramitsu.common.domain.AppVersion
import jp.co.soramitsu.common.domain.FiatCurrencies
import jp.co.soramitsu.common.domain.GetAvailableFiatCurrencies
import jp.co.soramitsu.common.domain.SelectedFiat
-import jp.co.soramitsu.common.domain.get
import jp.co.soramitsu.common.mixin.api.NetworkStateMixin
import jp.co.soramitsu.common.mixin.api.NetworkStateUi
import jp.co.soramitsu.common.mixin.api.UpdatesMixin
@@ -53,11 +53,18 @@ import jp.co.soramitsu.core.extrinsic.KeyPairProvider
import jp.co.soramitsu.core.extrinsic.mortality.IChainStateRepository
import jp.co.soramitsu.fearless_utils.ss58.SS58Encoder.addressByteOrNull
import jp.co.soramitsu.feature_wallet_impl.R
+import jp.co.soramitsu.oauth.base.sdk.SoraCardEnvironmentType
+import jp.co.soramitsu.oauth.base.sdk.SoraCardInfo
+import jp.co.soramitsu.oauth.base.sdk.contract.SoraCardCommonVerification
+import jp.co.soramitsu.oauth.base.sdk.signin.SoraCardSignInContractData
+import jp.co.soramitsu.oauth.common.domain.KycRepository
import jp.co.soramitsu.runtime.multiNetwork.chain.model.Chain
import jp.co.soramitsu.runtime.multiNetwork.chain.model.ChainId
import jp.co.soramitsu.runtime.multiNetwork.chain.model.defaultChainSort
import jp.co.soramitsu.runtime.multiNetwork.chain.model.getWithToken
import jp.co.soramitsu.runtime.multiNetwork.chain.model.polkadotChainId
+import jp.co.soramitsu.soracard.api.domain.SoraCardInteractor
+import jp.co.soramitsu.soracard.impl.presentation.SoraCardItemViewState
import jp.co.soramitsu.wallet.impl.data.mappers.mapAssetToAssetModel
import jp.co.soramitsu.wallet.impl.domain.ChainInteractor
import jp.co.soramitsu.wallet.impl.domain.CurrentAccountAddressUseCase
@@ -88,6 +95,8 @@ import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.math.BigDecimal
+import java.util.Locale
+import java.util.concurrent.TimeUnit
import javax.inject.Inject
private const val CURRENT_ICON_SIZE = 40
@@ -95,6 +104,7 @@ private const val CURRENT_ICON_SIZE = 40
@HiltViewModel
class BalanceListViewModel @Inject constructor(
private val interactor: WalletInteractor,
+ private val soraCardInteractor: SoraCardInteractor,
private val chainInteractor: ChainInteractor,
private val addressIconGenerator: AddressIconGenerator,
private val router: WalletRouter,
@@ -108,7 +118,8 @@ class BalanceListViewModel @Inject constructor(
private val currentAccountAddress: CurrentAccountAddressUseCase,
private val chainRegistry: IChainRegistry,
private val keyPairProvider: KeyPairProvider,
- private val chainStateRepository: IChainStateRepository
+ private val chainStateRepository: IChainStateRepository,
+ private val kycRepository: KycRepository
) : BaseViewModel(), UpdatesProviderUi by updatesMixin, NetworkStateUi by networkStateMixin, WalletScreenInterface {
private val accountAddressToChainIdMap = mutableMapOf()
@@ -125,6 +136,9 @@ class BalanceListViewModel @Inject constructor(
private val _openPlayMarket = MutableLiveData>()
val openPlayMarket: LiveData> = _openPlayMarket
+ private val _launchSoraCardSignIn = MutableLiveData>()
+ val launchSoraCardSignIn: LiveData> = _launchSoraCardSignIn
+
private val connectingChainIdsFlow = networkStateMixin.chainConnectionsLiveData.map {
it.filter { (_, isConnecting) -> isConnecting }.keys
}.asFlow()
@@ -141,7 +155,7 @@ class BalanceListViewModel @Inject constructor(
.inBackground()
private val fiatSymbolFlow = combine(selectedFiat.flow(), getAvailableFiatCurrencies.flow()) { selectedFiat: String, fiatCurrencies: FiatCurrencies ->
- fiatCurrencies[selectedFiat]?.symbol
+ fiatCurrencies.associateBy { it.id }[selectedFiat]?.symbol
}.onEach {
sync()
}
@@ -321,15 +335,25 @@ class BalanceListViewModel @Inject constructor(
.thenBy { it.chainId.defaultChainSort() }
.thenBy { it.chainName }
+ private val soraCardState = combine(
+ interactor.observeIsShowSoraCard(),
+ soraCardInteractor.subscribeSoraCardInfo()
+ ) { isShow, soraCardInfo ->
+ val kycStatus = soraCardInfo?.kycStatus?.let(::mapKycStatus)
+ SoraCardItemViewState(kycStatus, soraCardInfo, null, isShow)
+ }
+
val state = combine(
assetStates,
assetTypeSelectorState,
balanceFlow,
- selectedChainId
+ selectedChainId,
+ soraCardState
) { assetsListItemStates: List,
multiToggleButtonState: MultiToggleButtonState,
balanceModel: BalanceModel,
- selectedChainId: ChainId? ->
+ selectedChainId: ChainId?,
+ soraCardState: SoraCardItemViewState ->
val selectedChainAddress = selectedChainId?.let {
currentAccountAddress(chainId = it)
@@ -349,12 +373,12 @@ class BalanceListViewModel @Inject constructor(
assets = assetsListItemStates,
multiToggleButtonState = multiToggleButtonState,
balance = balanceState,
- hasNetworkIssues = hasNetworkIssues
+ hasNetworkIssues = hasNetworkIssues,
+ soraCardState = soraCardState
)
}.stateIn(scope = this, started = SharingStarted.Eagerly, initialValue = WalletState.default)
val toolbarState = combine(currentAddressModelFlow(), selectedChainItemFlow) { addressModel, chain ->
- chainsFlow
LoadingState.Loaded(
MainToolbarViewState(
title = addressModel.nameOrAddress,
@@ -365,6 +389,8 @@ class BalanceListViewModel @Inject constructor(
}.stateIn(scope = this, started = SharingStarted.Eagerly, initialValue = LoadingState.Loading())
init {
+ updateSoraCardStatus()
+
router.chainSelectorPayloadFlow.map { chainId ->
val walletId = interactor.getSelectedMetaAccount().id
interactor.saveChainId(walletId, chainId)
@@ -374,6 +400,24 @@ class BalanceListViewModel @Inject constructor(
interactor.selectedMetaAccountFlow().map { wallet ->
selectedChainId.value = interactor.getSavedChainId(wallet.id)
}.launchIn(this)
+
+ if (!interactor.isShowGetSoraCard()) {
+ interactor.decreaseSoraCardHiddenSessions()
+ }
+ }
+
+ private fun updateSoraCardStatus() {
+ viewModelScope.launch {
+ val soraCardInfo = soraCardInteractor.getSoraCardInfo() ?: return@launch
+ val accessTokenExpirationTime = soraCardInfo.accessTokenExpirationTime
+ val accessTokenExpired =
+ accessTokenExpirationTime < TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis())
+
+ if (!accessTokenExpired) {
+ val kycStatus: SoraCardCommonVerification? = kycRepository.getKycLastFinalStatus(soraCardInfo.accessToken)
+ soraCardInteractor.updateSoraCardKycStatus(kycStatus = kycStatus?.toString().orEmpty())
+ }
+ }
}
private fun sync() {
@@ -517,6 +561,18 @@ class BalanceListViewModel @Inject constructor(
}
}
+ override fun soraCardClicked() {
+ if (state.value.soraCardState?.kycStatus == null) {
+ router.openGetSoraCard()
+ } else {
+ onSoraCardStatusClicked()
+ }
+ }
+
+ override fun soraCardClose() {
+ interactor.hideSoraCard()
+ }
+
fun onFiatSelected(item: FiatCurrency) {
viewModelScope.launch {
selectedFiat.set(item.id)
@@ -574,4 +630,64 @@ class BalanceListViewModel @Inject constructor(
val message = resourceManager.getString(R.string.common_copied)
showMessage(message)
}
+
+ private fun mapKycStatus(kycStatus: String): String? {
+ return when (runCatching { SoraCardCommonVerification.valueOf(kycStatus) }.getOrNull()) {
+ SoraCardCommonVerification.Pending -> {
+ resourceManager.getString(R.string.sora_card_verification_in_progress)
+ }
+ SoraCardCommonVerification.Successful -> {
+ resourceManager.getString(R.string.sora_card_verification_successful)
+ }
+ SoraCardCommonVerification.Rejected -> {
+ resourceManager.getString(R.string.sora_card_verification_rejected)
+ }
+ SoraCardCommonVerification.Failed -> {
+ resourceManager.getString(R.string.sora_card_verification_failed)
+ }
+ SoraCardCommonVerification.NoFreeAttempt -> {
+ resourceManager.getString(R.string.sora_card_no_more_free_tries)
+ }
+ else -> {
+ null
+ }
+ }
+ }
+
+ private fun onSoraCardStatusClicked() {
+ _launchSoraCardSignIn.value = Event(
+ SoraCardSignInContractData(
+ locale = Locale.ENGLISH,
+ apiKey = BuildConfig.SORA_CARD_API_KEY,
+ domain = BuildConfig.SORA_CARD_DOMAIN,
+ environment = when {
+ BuildConfig.DEBUG -> SoraCardEnvironmentType.TEST
+ else -> SoraCardEnvironmentType.PRODUCTION
+ },
+ soraCardInfo = state.value.soraCardState?.soraCardInfo?.let {
+ SoraCardInfo(
+ accessToken = it.accessToken,
+ refreshToken = it.refreshToken,
+ accessTokenExpirationTime = it.accessTokenExpirationTime
+ )
+ }
+ )
+ )
+ }
+
+ fun updateSoraCardInfo(
+ accessToken: String,
+ refreshToken: String,
+ accessTokenExpirationTime: Long,
+ kycStatus: String
+ ) {
+ launch {
+ soraCardInteractor.updateSoraCardInfo(
+ accessToken,
+ refreshToken,
+ accessTokenExpirationTime,
+ kycStatus
+ )
+ }
+ }
}
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/list/WalletScreen.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/list/WalletScreen.kt
index 70dfdb11b1..03131d0b78 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/list/WalletScreen.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/list/WalletScreen.kt
@@ -1,6 +1,8 @@
package jp.co.soramitsu.wallet.impl.presentation.balance.list
+import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
+import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
@@ -10,6 +12,7 @@ import androidx.compose.material.SwipeableState
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import jp.co.soramitsu.common.compose.component.ActionItemType
@@ -25,6 +28,8 @@ import jp.co.soramitsu.common.compose.component.SwipeState
import jp.co.soramitsu.common.compose.theme.FearlessTheme
import jp.co.soramitsu.common.compose.viewstate.AssetListItemViewState
import jp.co.soramitsu.runtime.multiNetwork.chain.model.ChainId
+import jp.co.soramitsu.soracard.impl.presentation.SoraCardItem
+import jp.co.soramitsu.soracard.impl.presentation.SoraCardItemViewState
import jp.co.soramitsu.wallet.impl.presentation.balance.list.model.AssetType
import jp.co.soramitsu.wallet.impl.presentation.common.AssetsList
import jp.co.soramitsu.wallet.impl.presentation.common.AssetsListInterface
@@ -32,10 +37,13 @@ import jp.co.soramitsu.wallet.impl.presentation.common.AssetsListInterface
interface WalletScreenInterface : AssetsListInterface {
fun onAddressClick()
fun onBalanceClicked()
+ fun soraCardClicked()
+ fun soraCardClose()
fun onNetworkIssuesClicked()
fun assetTypeChanged(type: AssetType)
}
+@OptIn(ExperimentalFoundationApi::class)
@Composable
fun WalletScreen(
data: WalletState,
@@ -63,11 +71,35 @@ fun WalletScreen(
Modifier
.fillMaxSize()
.padding(bottom = 80.dp)
+ .pointerInput(Unit) {
+ detectTapGestures(
+ onPress = { /* Called when the gesture starts */ },
+ onDoubleTap = { /* Called on Double Tap */ },
+ onLongPress = {
+ throw RuntimeException("Test Crash in the NFT section") // Force a crash
+ /* Called on Long Press */
+ },
+ onTap = { /* Called on Tap */ }
+ )
+ }
)
} else {
+ val header: @Composable (() -> Unit)? = when {
+ data.soraCardState?.visible != true -> null
+ else -> {
+ {
+ SoraCardItem(
+ state = data.soraCardState,
+ onClose = callback::soraCardClose,
+ onClick = callback::soraCardClicked
+ )
+ }
+ }
+ }
AssetsList(
data = data,
- callback = callback
+ callback = callback,
+ header = header
)
}
}
@@ -78,6 +110,8 @@ fun WalletScreen(
private fun PreviewWalletScreen() {
@OptIn(ExperimentalMaterialApi::class)
val emptyCallback = object : WalletScreenInterface {
+ override fun soraCardClicked() {}
+ override fun soraCardClose() {}
override fun onAddressClick() {}
override fun onBalanceClicked() {}
override fun onNetworkIssuesClicked() {}
@@ -86,15 +120,38 @@ private fun PreviewWalletScreen() {
override fun actionItemClicked(actionType: ActionItemType, chainId: ChainId, chainAssetId: String, swipeableState: SwipeableState) {}
}
+ val assets: List = listOf(
+ AssetListItemViewState(
+ assetIconUrl = "",
+ assetChainName = "Chain",
+ assetSymbol = "SMB",
+ displayName = "Sora",
+ assetName = "Sora Asset",
+ assetTokenFiat = null,
+ assetTokenRate = null,
+ assetTransferableBalance = null,
+ assetTransferableBalanceFiat = null,
+ assetChainUrls = emptyMap(),
+ chainId = "",
+ chainAssetId = "",
+ isSupported = true,
+ isHidden = false,
+ hasAccount = true,
+ priceId = null,
+ hasNetworkIssue = false
+ )
+ )
+
FearlessTheme {
Surface(Modifier.background(Color.Black)) {
Column {
WalletScreen(
data = WalletState(
multiToggleButtonState = MultiToggleButtonState(AssetType.Currencies, listOf(AssetType.Currencies, AssetType.NFTs)),
- assets = emptyList(),
+ assets = assets,
balance = AssetBalanceViewState("TRANSFERABLE BALANCE", "ADDRESS", true, ChangeBalanceViewState("+100%", "+50$")),
- hasNetworkIssues = true
+ hasNetworkIssues = true,
+ soraCardState = SoraCardItemViewState(null, null, null, true)
),
callback = emptyCallback
)
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/list/WalletState.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/list/WalletState.kt
index 2ad15d7a29..6cb7b22672 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/list/WalletState.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/list/WalletState.kt
@@ -4,6 +4,7 @@ import jp.co.soramitsu.common.compose.component.AssetBalanceViewState
import jp.co.soramitsu.common.compose.component.ChangeBalanceViewState
import jp.co.soramitsu.common.compose.component.MultiToggleButtonState
import jp.co.soramitsu.common.compose.viewstate.AssetListItemViewState
+import jp.co.soramitsu.soracard.impl.presentation.SoraCardItemViewState
import jp.co.soramitsu.wallet.impl.presentation.balance.list.model.AssetType
import jp.co.soramitsu.wallet.impl.presentation.common.AssetListState
@@ -11,14 +12,16 @@ data class WalletState(
override val assets: List,
val multiToggleButtonState: MultiToggleButtonState,
val balance: AssetBalanceViewState,
- val hasNetworkIssues: Boolean
+ val hasNetworkIssues: Boolean,
+ val soraCardState: SoraCardItemViewState?
) : AssetListState(assets) {
companion object {
val default = WalletState(
multiToggleButtonState = MultiToggleButtonState(AssetType.Currencies, listOf(AssetType.Currencies, AssetType.NFTs)),
assets = emptyList(),
balance = AssetBalanceViewState("", "", false, ChangeBalanceViewState("", "")),
- hasNetworkIssues = false
+ hasNetworkIssues = false,
+ soraCardState = null
)
}
}
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/common/AssetsList.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/common/AssetsList.kt
index 18d2755273..ad8ac3d3d1 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/common/AssetsList.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/common/AssetsList.kt
@@ -31,7 +31,8 @@ interface AssetsListInterface {
@Composable
fun AssetsList(
data: AssetListState,
- callback: AssetsListInterface
+ callback: AssetsListInterface,
+ header: (@Composable () -> Unit)? = null
) {
val listState = rememberLazyListState(0)
val isShowHidden = remember { mutableStateOf(false) }
@@ -50,6 +51,9 @@ fun AssetsList(
state = listState,
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
+ if (header != null) {
+ item { header() }
+ }
items(data.visibleAssets, key = { it.key }) { assetState ->
SwipeableAssetListItem(
assetState = assetState,
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index c5b0880011..03c0b0e2aa 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -1,12 +1,23 @@
[versions]
-dagger = "2.43"
+dagger = "2.45"
compose = "1.2.1"
fragmentKtx = "1.5.2"
composeThemeAdapter = "1.2.1"
material = "1.6.1"
coroutines = "1.6.4"
+soraUi = "0.0.63"
+soraCard = "0.0.30"
+kotlinxSerializationjson = "1.4.1"
+xNetworking = "0.0.55"
[libraries]
+sora-ui = { module = "jp.co.soramitsu:ui-core", version.ref = "soraUi" }
+sora-card = { module = "jp.co.soramitsu:android-sora-card", version.ref = "soraCard" }
+
+xnetworking-android = { module = "jp.co.soramitsu:XNetworking-android", version.ref = "xNetworking" }
+
+kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationjson" }
+
hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "dagger" }
hilt-compiler = { module = "com.google.dagger:hilt-compiler", version.ref = "dagger" }
diff --git a/scripts/secrets.gradle b/scripts/secrets.gradle
index b84f1fc285..ddc33eab05 100644
--- a/scripts/secrets.gradle
+++ b/scripts/secrets.gradle
@@ -8,9 +8,12 @@ if (localPropertiesFile.exists()) {
ext.readSecret = { secretName ->
def localPropSecret = localProperties.getProperty(secretName)
-
def secret = (localPropSecret != null) ? localPropSecret : System.getenv(secretName)
+ return secret
+}
+ext.readSecretInQuotes = { secretName ->
+ def secret = readSecret(secretName)
return maybeWrapInQuotes(secret)
}
diff --git a/settings.gradle b/settings.gradle
index 4680957025..53d722aecf 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -18,3 +18,5 @@ include ':feature-polkaswap-api'
include ':feature-polkaswap-impl'
include ':feature-success-api'
include ':feature-success-impl'
+include ':feature-soracard-api'
+include ':feature-soracard-impl'