diff --git a/android-foundation b/android-foundation index a75a6d67f..a5be15486 160000 --- a/android-foundation +++ b/android-foundation @@ -1 +1 @@ -Subproject commit a75a6d67fb65c608af232cfebcc66ad11dcd2bba +Subproject commit a5be154865d8cb01051f6fc827126487210de7c9 diff --git a/common/src/main/java/jp/co/soramitsu/common/domain/Asset.kt b/common/src/main/java/jp/co/soramitsu/common/domain/Asset.kt index 3e8f7a474..9b88c775c 100644 --- a/common/src/main/java/jp/co/soramitsu/common/domain/Asset.kt +++ b/common/src/main/java/jp/co/soramitsu/common/domain/Asset.kt @@ -79,6 +79,8 @@ data class AssetBalance( fun createAssetBalance(b: BigDecimal = BigDecimal.ZERO) = AssetBalance(b, b, b, b, b, b, b, b) +typealias TokenPrecision = Pair + @Parcelize data class Token( val id: String, diff --git a/core_db/src/main/java/jp/co/soramitsu/core_db/dao/AssetDao.kt b/core_db/src/main/java/jp/co/soramitsu/core_db/dao/AssetDao.kt index c35ec02c2..292594a3c 100644 --- a/core_db/src/main/java/jp/co/soramitsu/core_db/dao/AssetDao.kt +++ b/core_db/src/main/java/jp/co/soramitsu/core_db/dao/AssetDao.kt @@ -73,7 +73,7 @@ interface AssetDao { private const val QUERY_ASSET_TOKEN_ACTIVE = """ select * from assets inner join ($joinFiatToken) tokensfiats on assets.tokenId=tokensfiats.id where assets.accountAddress=:address and tokensfiats.whitelistName=:whitelist - and ((assets.visibility=1 or assets.displayAsset=1 or tokensfiats.isHidable = 0) or (tokensfiats.id in (select tokenIdTarget from allpools)) or (tokensfiats.id in (select tokenId from poolBaseTokens))) order by assets.position + and ((assets.visibility=1 or assets.displayAsset=1 or tokensfiats.isHidable = 0) or (tokensfiats.id = "0x02000e0000000000000000000000000000000000000000000000000000000000") or (tokensfiats.id in (select tokenIdTarget from allpools)) or (tokensfiats.id in (select tokenId from poolBaseTokens))) order by assets.position """ } diff --git a/feature_polkaswap_api/src/main/java/jp/co/soramitsu/feature_polkaswap_api/domain/interfaces/PolkaswapExtrinsicRepository.kt b/feature_polkaswap_api/src/main/java/jp/co/soramitsu/feature_polkaswap_api/domain/interfaces/PolkaswapExtrinsicRepository.kt index 704b67dd4..c3fb09500 100644 --- a/feature_polkaswap_api/src/main/java/jp/co/soramitsu/feature_polkaswap_api/domain/interfaces/PolkaswapExtrinsicRepository.kt +++ b/feature_polkaswap_api/src/main/java/jp/co/soramitsu/feature_polkaswap_api/domain/interfaces/PolkaswapExtrinsicRepository.kt @@ -35,6 +35,7 @@ package jp.co.soramitsu.feature_polkaswap_api.domain.interfaces import java.math.BigDecimal import jp.co.soramitsu.common.domain.Market import jp.co.soramitsu.common.domain.Token +import jp.co.soramitsu.common.domain.TokenPrecision import jp.co.soramitsu.common_wallet.domain.model.WithDesired import jp.co.soramitsu.sora.substrate.models.ExtrinsicSubmitStatus import jp.co.soramitsu.xsubstrate.encrypt.keypair.substrate.Sr25519Keypair @@ -82,8 +83,8 @@ interface PolkaswapExtrinsicRepository { suspend fun calcAddLiquidityNetworkFee( address: String, - tokenFrom: Token, - tokenTo: Token, + tokenFrom: TokenPrecision, + tokenTo: TokenPrecision, tokenFromAmount: BigDecimal, tokenToAmount: BigDecimal, pairEnabled: Boolean, @@ -92,8 +93,8 @@ interface PolkaswapExtrinsicRepository { ): BigDecimal? suspend fun calcRemoveLiquidityNetworkFee( - tokenId1: Token, - tokenId2: Token, - address: String + tokenId1: TokenPrecision, + tokenId2: TokenPrecision, + address: String, ): BigDecimal? } diff --git a/feature_polkaswap_api/src/main/java/jp/co/soramitsu/feature_polkaswap_api/domain/interfaces/PolkaswapSubscriptionRepository.kt b/feature_polkaswap_api/src/main/java/jp/co/soramitsu/feature_polkaswap_api/domain/interfaces/PolkaswapSubscriptionRepository.kt index ee50a6c1e..92b7dab43 100644 --- a/feature_polkaswap_api/src/main/java/jp/co/soramitsu/feature_polkaswap_api/domain/interfaces/PolkaswapSubscriptionRepository.kt +++ b/feature_polkaswap_api/src/main/java/jp/co/soramitsu/feature_polkaswap_api/domain/interfaces/PolkaswapSubscriptionRepository.kt @@ -45,10 +45,12 @@ interface PolkaswapSubscriptionRepository { fun subscribeEachBlock(): Flow suspend fun getRemotePoolReserves( - tokenFrom: Token, - tokenTo: Token, + tokenFromId: String, + tokenFromPrecision: Int, + tokenToId: String, + tokenToPrecision: Int, enabled: Boolean, - presented: Boolean + presented: Boolean, ): LiquidityData suspend fun updateAccountPools(address: String) diff --git a/feature_polkaswap_impl/src/main/java/jp/co/soramitsu/feature_polkaswap_impl/data/repository/PolkaswapExtrinsicRepositoryImpl.kt b/feature_polkaswap_impl/src/main/java/jp/co/soramitsu/feature_polkaswap_impl/data/repository/PolkaswapExtrinsicRepositoryImpl.kt index cad59b446..c6b539300 100644 --- a/feature_polkaswap_impl/src/main/java/jp/co/soramitsu/feature_polkaswap_impl/data/repository/PolkaswapExtrinsicRepositoryImpl.kt +++ b/feature_polkaswap_impl/src/main/java/jp/co/soramitsu/feature_polkaswap_impl/data/repository/PolkaswapExtrinsicRepositoryImpl.kt @@ -36,6 +36,7 @@ import java.math.BigDecimal import javax.inject.Inject import jp.co.soramitsu.common.domain.Market import jp.co.soramitsu.common.domain.Token +import jp.co.soramitsu.common.domain.TokenPrecision import jp.co.soramitsu.common.util.mapBalance import jp.co.soramitsu.common_wallet.domain.model.WithDesired import jp.co.soramitsu.common_wallet.presentation.compose.util.PolkaswapFormulas @@ -191,8 +192,8 @@ class PolkaswapExtrinsicRepositoryImpl @Inject constructor( override suspend fun calcAddLiquidityNetworkFee( address: String, - tokenFrom: Token, - tokenTo: Token, + tokenFrom: TokenPrecision, + tokenTo: TokenPrecision, tokenFromAmount: BigDecimal, tokenToAmount: BigDecimal, pairEnabled: Boolean, @@ -201,7 +202,7 @@ class PolkaswapExtrinsicRepositoryImpl @Inject constructor( ): BigDecimal? { val amountFromMin = PolkaswapFormulas.calculateMinAmount(tokenFromAmount, slippageTolerance) val amountToMin = PolkaswapFormulas.calculateMinAmount(tokenToAmount, slippageTolerance) - val dexId = getPoolBaseTokenDexId(tokenFrom.id) + val dexId = getPoolBaseTokenDexId(tokenFrom.first) val fee = extrinsicManager.calcFee( from = address, ) { @@ -209,49 +210,49 @@ class PolkaswapExtrinsicRepositoryImpl @Inject constructor( if (!pairEnabled) { register( dexId = dexId, - tokenFrom.id, tokenTo.id + tokenFrom.first, tokenTo.first ) } initializePool( dexId = dexId, - tokenFrom.id, tokenTo.id + tokenFrom.first, tokenTo.first ) } depositLiquidity( dexId = dexId, - tokenFrom.id, - tokenTo.id, - mapBalance(tokenFromAmount, tokenFrom.precision), - mapBalance(tokenToAmount, tokenTo.precision), - mapBalance(amountFromMin, tokenFrom.precision), - mapBalance(amountToMin, tokenTo.precision) + tokenFrom.first, + tokenTo.first, + mapBalance(tokenFromAmount, tokenFrom.second), + mapBalance(tokenToAmount, tokenTo.second), + mapBalance(amountFromMin, tokenFrom.second), + mapBalance(amountToMin, tokenTo.second) ) } return fee?.let { - mapBalance(it, tokenFrom.precision) + mapBalance(it, tokenFrom.second) } } override suspend fun calcRemoveLiquidityNetworkFee( - tokenId1: Token, - tokenId2: Token, + tokenId1: TokenPrecision, + tokenId2: TokenPrecision, address: String, ): BigDecimal? { val fee = extrinsicManager.calcFee( from = address ) { removeLiquidity( - dexId = getPoolBaseTokenDexId(tokenId1.id), - outputAssetIdA = tokenId1.id, - outputAssetIdB = tokenId2.id, - markerAssetDesired = mapBalance(BigDecimal.ONE, tokenId1.precision), - outputAMin = mapBalance(BigDecimal.ONE, tokenId1.precision), - outputBMin = mapBalance(BigDecimal.ONE, tokenId1.precision) + dexId = getPoolBaseTokenDexId(tokenId1.first), + outputAssetIdA = tokenId1.first, + outputAssetIdB = tokenId2.first, + markerAssetDesired = mapBalance(BigDecimal.ONE, tokenId1.second), + outputAMin = mapBalance(BigDecimal.ONE, tokenId1.second), + outputBMin = mapBalance(BigDecimal.ONE, tokenId1.second) ) } return fee?.let { - mapBalance(it, tokenId1.precision) + mapBalance(it, tokenId1.second) } } } diff --git a/feature_polkaswap_impl/src/main/java/jp/co/soramitsu/feature_polkaswap_impl/data/repository/PolkaswapSubscriptionRepositoryImpl.kt b/feature_polkaswap_impl/src/main/java/jp/co/soramitsu/feature_polkaswap_impl/data/repository/PolkaswapSubscriptionRepositoryImpl.kt index 9fe0f1064..5b41f8112 100644 --- a/feature_polkaswap_impl/src/main/java/jp/co/soramitsu/feature_polkaswap_impl/data/repository/PolkaswapSubscriptionRepositoryImpl.kt +++ b/feature_polkaswap_impl/src/main/java/jp/co/soramitsu/feature_polkaswap_impl/data/repository/PolkaswapSubscriptionRepositoryImpl.kt @@ -226,24 +226,26 @@ class PolkaswapSubscriptionRepositoryImpl @Inject constructor( } override suspend fun getRemotePoolReserves( - tokenFrom: Token, - tokenTo: Token, + tokenFromId: String, + tokenFromPrecision: Int, + tokenToId: String, + tokenToPrecision: Int, enabled: Boolean, - presented: Boolean + presented: Boolean, ): LiquidityData { return if (presented || enabled) { val (reservesFirst, reservesSecond) = wsConnection.getPoolReserves( - tokenFrom.id, - tokenTo.id + tokenFromId, + tokenToId, ) ?: (BigInteger.ZERO to BigInteger.ZERO) - val poolLocal = db.poolDao().getBasicPool(tokenFrom.id, tokenTo.id) + val poolLocal = db.poolDao().getBasicPool(tokenFromId, tokenToId) LiquidityData( - firstReserves = mapBalance(reservesFirst, tokenFrom.precision), - secondReserves = mapBalance(reservesSecond, tokenTo.precision), - firstPooled = mapBalance(BigInteger.ZERO, tokenFrom.precision), - secondPooled = mapBalance(BigInteger.ZERO, tokenTo.precision), + firstReserves = mapBalance(reservesFirst, tokenFromPrecision), + secondReserves = mapBalance(reservesSecond, tokenToPrecision), + firstPooled = mapBalance(BigInteger.ZERO, tokenFromPrecision), + secondPooled = mapBalance(BigInteger.ZERO, tokenToPrecision), sbApy = poolLocal?.reservesAccount?.let { getPoolStrategicBonusAPY(it)?.times(100) }, diff --git a/feature_polkaswap_impl/src/main/java/jp/co/soramitsu/feature_polkaswap_impl/domain/PoolsInteractorImpl.kt b/feature_polkaswap_impl/src/main/java/jp/co/soramitsu/feature_polkaswap_impl/domain/PoolsInteractorImpl.kt index d5ed21453..bef8fd03e 100644 --- a/feature_polkaswap_impl/src/main/java/jp/co/soramitsu/feature_polkaswap_impl/domain/PoolsInteractorImpl.kt +++ b/feature_polkaswap_impl/src/main/java/jp/co/soramitsu/feature_polkaswap_impl/domain/PoolsInteractorImpl.kt @@ -60,6 +60,7 @@ import jp.co.soramitsu.feature_polkaswap_api.domain.interfaces.PolkaswapSubscrip import jp.co.soramitsu.feature_polkaswap_api.domain.interfaces.PoolsInteractor import jp.co.soramitsu.sora.substrate.runtime.SubstrateOptionsProvider import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.emitAll @@ -106,8 +107,8 @@ class PoolsInteractorImpl( return removeLiquidityNetworkFee ?: ( ( polkaswapExtrinsicRepository.calcRemoveLiquidityNetworkFee( - tokenId1, - tokenId2, + tokenId1.id.kensetsu() to tokenId1.precision, + tokenId2.id to tokenId2.precision, userRepository.getCurSoraAccount().substrateAddress, ) ?: BigDecimal.ZERO ).also { @@ -128,8 +129,8 @@ class PoolsInteractorImpl( val user = userRepository.getCurSoraAccount().substrateAddress val result = polkaswapExtrinsicRepository.calcAddLiquidityNetworkFee( user, - tokenFrom, - tokenTo, + tokenFrom.id.kensetsu() to tokenFrom.precision, + tokenTo.id to tokenTo.precision, tokenFromAmount, tokenToAmount, pairEnabled, @@ -185,6 +186,7 @@ class PoolsInteractorImpl( return result } + @OptIn(FlowPreview::class) override fun subscribePoolsChangesOfAccount(address: String): Flow { return polkaswapSubscriptionRepository.subscribeToPoolsAssets(address) .debounce(300) @@ -355,8 +357,8 @@ class PoolsInteractorImpl( userRepository.flowCurSoraAccount().flatMapLatest { polkaswapRepository.subscribeLocalPoolReserves( it.substrateAddress, - baseTokenId, - assetId + baseTokenId.kensetsu(), + assetId, ) } @@ -364,23 +366,23 @@ class PoolsInteractorImpl( val address = userRepository.getCurSoraAccount().substrateAddress emitAll( polkaswapSubscriptionRepository.isPairEnabled( - inputAssetId, + inputAssetId.kensetsu(), outputAssetId, - address + address, ) ) } override fun isPairPresentedInNetwork( baseTokenId: String, - tokenId: String + tokenId: String, ): Flow = flow { val address = userRepository.getCurSoraAccount().substrateAddress emitAll( polkaswapSubscriptionRepository.isPairPresentedInNetwork( - baseTokenId, + baseTokenId.kensetsu(), tokenId, - address + address, ) ) } @@ -389,11 +391,13 @@ class PoolsInteractorImpl( tokenFrom: Token, tokenTo: Token, enabled: Boolean, - presented: Boolean + presented: Boolean, ): LiquidityData { return polkaswapSubscriptionRepository.getRemotePoolReserves( - tokenFrom, - tokenTo, + tokenFrom.id.kensetsu(), + tokenFrom.precision, + tokenTo.id.kensetsu(), + tokenTo.precision, enabled, presented ) @@ -440,4 +444,7 @@ class PoolsInteractorImpl( override suspend fun getRewardToken(): Token { return requireNotNull(assetsRepository.getToken(SubstrateOptionsProvider.pswapAssetId)) } + + private fun String.kensetsu() = + if (this == SubstrateOptionsProvider.kxorTokenId) SubstrateOptionsProvider.feeAssetId else this } diff --git a/feature_polkaswap_impl/src/main/java/jp/co/soramitsu/feature_polkaswap_impl/presentation/screens/liquidityadd/LiquidityAddViewModel.kt b/feature_polkaswap_impl/src/main/java/jp/co/soramitsu/feature_polkaswap_impl/presentation/screens/liquidityadd/LiquidityAddViewModel.kt index f4dfdc085..e2aa92da1 100644 --- a/feature_polkaswap_impl/src/main/java/jp/co/soramitsu/feature_polkaswap_impl/presentation/screens/liquidityadd/LiquidityAddViewModel.kt +++ b/feature_polkaswap_impl/src/main/java/jp/co/soramitsu/feature_polkaswap_impl/presentation/screens/liquidityadd/LiquidityAddViewModel.kt @@ -509,7 +509,12 @@ class LiquidityAddViewModel @AssistedInject constructor( fun onToken1Click() { if (assets.isNotEmpty()) { viewModelScope.launch { - val bases = poolsInteractor.getPoolDexList().map { it.tokenId } + val bases = buildList { + if (addToken2 == null || addToken2 == SubstrateOptionsProvider.ethTokenId) { + add(SubstrateOptionsProvider.kxorTokenId) + } + addAll(poolsInteractor.getPoolDexList().map { it.tokenId }) + } val list = assets.filter { it.token.id in bases && it.token.id != addToken2 } _addState.value = _addState.value.copy( assetState1 = _addState.value.assetState1?.copy( @@ -532,6 +537,13 @@ class LiquidityAddViewModel @AssistedInject constructor( val bases = poolsInteractor.getPoolDexList() val curBase = bases.find { it.tokenId == addToken1 } val list = assets + .filter { asset -> + if (addToken1 != null && addToken1 == SubstrateOptionsProvider.kxorTokenId) { + asset.token.id == SubstrateOptionsProvider.ethTokenId + } else { + true + } + } .filter { asset -> val inBases = bases.find { it.tokenId == asset.token.id } if (inBases != null && curBase != null) { diff --git a/sorasubstrate/src/main/java/jp/co/soramitsu/sora/substrate/runtime/SubstrateOptionsProvider.kt b/sorasubstrate/src/main/java/jp/co/soramitsu/sora/substrate/runtime/SubstrateOptionsProvider.kt index cf63607f9..2d9aacca3 100644 --- a/sorasubstrate/src/main/java/jp/co/soramitsu/sora/substrate/runtime/SubstrateOptionsProvider.kt +++ b/sorasubstrate/src/main/java/jp/co/soramitsu/sora/substrate/runtime/SubstrateOptionsProvider.kt @@ -58,6 +58,7 @@ object SubstrateOptionsProvider { const val xstTokenId = "0x0200090000000000000000000000000000000000000000000000000000000000" const val xstusdTokenId = "0x0200080000000000000000000000000000000000000000000000000000000000" const val ethTokenId = "0x0200070000000000000000000000000000000000000000000000000000000000" + const val kxorTokenId = "0x02000e0000000000000000000000000000000000000000000000000000000000" } fun String.isSynthetic(): Boolean = this.matches(syntheticTokenRegex)