Skip to content

Commit

Permalink
Merge pull request #1274 from novasamatech/rc/7.6.0
Browse files Browse the repository at this point in the history
Rc/7.6.0
  • Loading branch information
valentunn authored Dec 20, 2023
2 parents 7da646c + e842f61 commit 1019b53
Show file tree
Hide file tree
Showing 64 changed files with 615 additions and 196 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/update_tag.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ jobs:

steps:
- uses: actions/checkout@v2
with:
token: ${{ secrets.WRITE_SECRET_PAT }}

- name: Version in build.gradle
run: |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import io.novafoundation.nova.common.utils.divideToDecimal
import io.novafoundation.nova.runtime.ethereum.gas.LegacyGasPriceProvider
import io.novafoundation.nova.runtime.ethereum.gas.MaxPriorityFeeGasProvider
import io.novafoundation.nova.runtime.ext.Ids
import io.novafoundation.nova.runtime.multiNetwork.awaitCallEthereumApiOrThrow
import io.novafoundation.nova.runtime.multiNetwork.getCallEthereumApiOrThrow
import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.map
Expand All @@ -18,7 +18,7 @@ class GasPriceProviderIntegrationTest : BaseIntegrationTest() {

@Test
fun compareLegacyAndImprovedGasPriceEstimations() = runTest {
val api = chainRegistry.awaitCallEthereumApiOrThrow(Chain.Ids.MOONBEAM)
val api = chainRegistry.getCallEthereumApiOrThrow(Chain.Ids.MOONBEAM)

val legacy = LegacyGasPriceProvider(api)
val improved = MaxPriorityFeeGasProvider(api)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ class GovernanceIntegrationTest : BaseIntegrationTest() {
Log.d(this@GovernanceIntegrationTest.LOG_TAG, referendumDetails.toString())

val callDetails = referendumDetailsInteractor.detailsFor(
preImage = referendumDetails.onChainMetadata!!.preImage!!,
preImage = referendumDetails?.onChainMetadata!!.preImage!!,
chain = chain
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import io.novafoundation.nova.runtime.ethereum.contract.base.querySingle
import io.novafoundation.nova.runtime.ethereum.contract.erc20.Erc20Queries
import io.novafoundation.nova.runtime.ethereum.contract.erc20.Erc20Standard
import io.novafoundation.nova.runtime.ethereum.sendSuspend
import io.novafoundation.nova.runtime.multiNetwork.awaitEthereumApiOrThrow
import io.novafoundation.nova.runtime.multiNetwork.getEthereumApiOrThrow
import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emitAll
Expand Down Expand Up @@ -132,6 +132,6 @@ class Web3jServiceIntegrationTest : BaseIntegrationTest() {
private suspend fun moonbeamWeb3j(): Web3Api {
val moonbeamChainId = "fe58ea77779b7abda7da4ec526d14db9b1e9cd40a217c34892af80a9b332b76d"

return chainRegistry.awaitEthereumApiOrThrow(moonbeamChainId, Chain.Node.ConnectionType.WSS)
return chainRegistry.getEthereumApiOrThrow(moonbeamChainId, Chain.Node.ConnectionType.WSS)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,9 @@ class BalancesIntegrationTest(
companion object {
@JvmStatic
@Parameterized.Parameters(name = "{1}")
fun data(): ArrayList<Array<String?>> {
fun data(): List<Array<String?>> {
val arrayOfNetworks: Array<TestData> = Gson().fromJson(URL(TEST_CHAINS_URL).readText())
val listNetworks: ArrayList<Array<String?>> = ArrayList()
arrayOfNetworks.forEach { listNetworks.add(arrayOf(it.chainId, it.name, it.account)) }
return listNetworks
return arrayOfNetworks.map { arrayOf(it.chainId, it.name, it.account) }
}

class TestData(
Expand Down
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
buildscript {
ext {
// App version
versionName = '7.5.0'
versionCode = 102
versionName = '7.6.0'
versionCode = 104

applicationId = "io.novafoundation.nova"
releaseApplicationSuffix = "market"
Expand Down Expand Up @@ -51,7 +51,7 @@ buildscript {

web3jVersion = '4.9.5'

fearlessLibVersion = '1.9.1'
fearlessLibVersion = '1.10.1'

gifVersion = '1.2.19'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ private const val HTTP_CACHE = "http_cache"
private const val CACHE_SIZE = 50L * 1024L * 1024L // 50 MiB
private const val TIMEOUT_SECONDS = 20L

private const val SOCKET_CONNECTION_TIMEOUT = 5_000

@Module
class NetworkModule {

Expand Down Expand Up @@ -103,7 +105,9 @@ class NetworkModule {

@Provides
@ApplicationScope
fun provideSocketFactory() = WebSocketFactory()
fun provideSocketFactory() = WebSocketFactory().apply {
connectionTimeout = SOCKET_CONNECTION_TIMEOUT
}

@Provides
fun provideReconnector() = Reconnector()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,7 @@ val <T> LoadingState<T>.dataOrNull: T?
else -> null
}

val LoadingState<*>.isLoading: Boolean
get() = this is LoadingState.Loading

suspend inline fun <reified T> Flow<LoadingState<T>>.firstLoaded(): T = first { it.dataOrNull != null }.dataOrNull as T
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancel
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.channels.SendChannel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.channelFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.flow.drop
Expand Down Expand Up @@ -259,7 +261,7 @@ private fun <K> MutableMap<K, CoroutineScope>.removeAndCancel(key: K) {
remove(key)?.also(CoroutineScope::cancel)
}

fun <T : Identifiable, R> Flow<List<T>>.transformLatestDiffed(transform: suspend FlowCollector<R>.(value: T) -> Unit): Flow<R> = flow {
fun <T : Identifiable, R> Flow<List<T>>.transformLatestDiffed(transform: suspend FlowCollector<R>.(value: T) -> Unit): Flow<R> = channelFlow {
val parentScope = CoroutineScope(coroutineContext)
val itemScopes = mutableMapOf<String, CoroutineScope>()

Expand All @@ -275,12 +277,18 @@ fun <T : Identifiable, R> Flow<List<T>>.transformLatestDiffed(transform: suspend
itemScopes[newOrUpdatedItem.identifier] = chainScope

chainScope.launch {
transform(this@flow, newOrUpdatedItem)
transform(SendingCollector(this@channelFlow), newOrUpdatedItem)
}
}
}.launchIn(parentScope)
}

private class SendingCollector<T>(
private val channel: SendChannel<T>
) : FlowCollector<T> {
override suspend fun emit(value: T): Unit = channel.send(value)
}

fun <T> singleReplaySharedFlow() = MutableSharedFlow<T>(replay = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)

fun <T> Flow<T>.inBackground() = flowOn(Dispatchers.Default)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ import io.novafoundation.nova.core_db.dao.StorageDao
import io.novafoundation.nova.core_db.dao.TokenDao
import io.novafoundation.nova.core_db.dao.WalletConnectSessionsDao
import io.novafoundation.nova.core_db.migrations.AddAdditionalFieldToChains_12_13
import io.novafoundation.nova.core_db.migrations.AddBalanceModesToAssets_51_52
import io.novafoundation.nova.core_db.migrations.AddBrowserHostSettings_34_35
import io.novafoundation.nova.core_db.migrations.AddBuyProviders_7_8
import io.novafoundation.nova.core_db.migrations.AddChainColor_4_5
import io.novafoundation.nova.core_db.migrations.AddConnectionStateToChains_53_54
import io.novafoundation.nova.core_db.migrations.AddContributions_23_24
import io.novafoundation.nova.core_db.migrations.AddCurrencies_18_19
import io.novafoundation.nova.core_db.migrations.AddDAppAuthorizations_1_2
Expand Down Expand Up @@ -132,7 +132,7 @@ import io.novafoundation.nova.core_db.model.operation.SwapTypeLocal
import io.novafoundation.nova.core_db.model.operation.TransferTypeLocal

@Database(
version = 53,
version = 54,
entities = [
AccountLocal::class,
NodeLocal::class,
Expand Down Expand Up @@ -219,8 +219,8 @@ abstract class AppDatabase : RoomDatabase() {
.addMigrations(AddStakingDashboardItems_41_42, StakingRewardPeriods_42_43)
.addMigrations(AddRewardAccountToStakingDashboard_43_44, AddStakingTypeToTotalRewards_44_45, AddExternalBalances_45_46)
.addMigrations(AddPoolIdToOperations_46_47, AddEventIdToOperation_47_48, AddSwapOption_48_49)
.addMigrations(RefactorOperations_49_50, AddTransactionVersionToRuntime_50_51, AddBalanceModesToAssets_51_52)
.addMigrations(ChangeSessionTopicToParing_52_53)
.addMigrations(RefactorOperations_49_50, AddTransactionVersionToRuntime_50_51)
.addMigrations(ChangeSessionTopicToParing_52_53, AddConnectionStateToChains_53_54)
.build()
}
return instance!!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,24 @@ package io.novafoundation.nova.core_db.converters

import androidx.room.TypeConverter
import io.novafoundation.nova.common.utils.enumValueOfOrNull
import io.novafoundation.nova.core_db.model.chain.ChainLocal.ConnectionStateLocal
import io.novafoundation.nova.core_db.model.chain.ChainLocal.NodeSelectionStrategyLocal

class ChainConverters {

@TypeConverter
fun from(strategy: NodeSelectionStrategyLocal): String = strategy.name
fun fromNodeStrategy(strategy: NodeSelectionStrategyLocal): String = strategy.name

@TypeConverter
fun to(name: String): NodeSelectionStrategyLocal {
fun toNodeStrategy(name: String): NodeSelectionStrategyLocal {
return enumValueOfOrNull<NodeSelectionStrategyLocal>(name) ?: NodeSelectionStrategyLocal.UNKNOWN
}

@TypeConverter
fun fromConnection(connectionState: ConnectionStateLocal): String = connectionState.name

@TypeConverter
fun toConnection(name: String): ConnectionStateLocal {
return enumValueOfOrNull<ConnectionStateLocal>(name) ?: ConnectionStateLocal.LIGHT_SYNC
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ abstract class ChainDao {
@Query("UPDATE chain_runtimes SET syncedVersion = :syncedVersion WHERE chainId = :chainId")
abstract suspend fun updateSyncedRuntimeVersion(chainId: String, syncedVersion: Int)

@Query("UPDATE chains SET connectionState = :connectionState WHERE id = :chainId")
abstract suspend fun setConnectionState(chainId: String, connectionState: ChainLocal.ConnectionStateLocal)

@Transaction
open suspend fun updateRemoteRuntimeVersionIfChainExists(chainId: String, runtimeVersion: Int, transactionVersion: Int) {
if (!chainExists(chainId)) return
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package io.novafoundation.nova.core_db.migrations

import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import io.novafoundation.nova.core_db.model.chain.ChainLocal

val AddConnectionStateToChains_53_54 = object : Migration(53, 54) {
override fun migrate(database: SupportSQLiteDatabase) {
val defaultConnectionState = ChainLocal.Default.CONNECTION_STATE_DEFAULT

database.execSQL("ALTER TABLE chains ADD COLUMN connectionState TEXT NOT NULL DEFAULT '$defaultConnectionState'")

// Enable full for chains that have some balance synced
database.execSQL(
"""
UPDATE chains SET connectionState = 'FULL_SYNC'
WHERE id IN (
SELECT DISTINCT chainId
FROM assets
WHERE freeInPlanks > 0 OR frozenInPlanks > 0 OR reservedInPlanks > 0
) OR hasSubstrateRuntime = 0
""".trimIndent()
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ data class ChainLocal(
val swap: String,
val governance: String,
val additional: String?,
val connectionState: ConnectionStateLocal,
@ColumnInfo(defaultValue = NODE_SELECTION_STRATEGY_DEFAULT)
val nodeSelectionStrategy: NodeSelectionStrategyLocal,
) : Identifiable {
Expand All @@ -33,11 +34,17 @@ data class ChainLocal(
ROUND_ROBIN, UNIFORM, UNKNOWN
}

enum class ConnectionStateLocal {
FULL_SYNC, LIGHT_SYNC, DISABLED
}

object Default {

const val NODE_SELECTION_STRATEGY_DEFAULT = "ROUND_ROBIN"

const val HAS_SUBSTRATE_RUNTIME = 1

const val CONNECTION_STATE_DEFAULT = "LIGHT_SYNC"
}

@Ignore
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,6 @@ class ExtrinsicTypeLocal(
class ExtrinsicTypeJoin(
val contentType: ExtrinsicTypeLocal.ContentType,
val module: String,
val call: String,
val call: String?,
val fee: BigInteger,
)
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import io.novafoundation.nova.feature_account_api.data.model.Fee
import io.novafoundation.nova.runtime.extrinsic.ExtrinsicStatus
import io.novafoundation.nova.runtime.extrinsic.multi.CallBuilder
import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain
import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId
import jp.co.soramitsu.fearless_utils.runtime.AccountId
import jp.co.soramitsu.fearless_utils.runtime.extrinsic.ExtrinsicBuilder
import kotlinx.coroutines.flow.Flow
Expand Down Expand Up @@ -78,5 +77,5 @@ interface ExtrinsicService {
formExtrinsic: FormMultiExtrinsic,
): BigInteger

suspend fun estimateFee(chainId: ChainId, extrinsic: String): Fee
suspend fun estimateFee(chain: Chain, extrinsic: String): Fee
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import io.novafoundation.nova.runtime.ethereum.gas.GasPriceProviderFactory
import io.novafoundation.nova.runtime.ethereum.sendSuspend
import io.novafoundation.nova.runtime.ethereum.transaction.builder.EvmTransactionBuilder
import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry
import io.novafoundation.nova.runtime.multiNetwork.awaitCallEthereumApiOrThrow
import io.novafoundation.nova.runtime.multiNetwork.getCallEthereumApiOrThrow
import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain
import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId
import jp.co.soramitsu.fearless_utils.encrypt.SignatureWrapper
Expand Down Expand Up @@ -46,7 +46,7 @@ internal class RealEvmTransactionService(
fallbackGasLimit: BigInteger,
building: EvmTransactionBuilding
): Fee {
val web3Api = chainRegistry.awaitCallEthereumApiOrThrow(chainId)
val web3Api = chainRegistry.getCallEthereumApiOrThrow(chainId)
val chain = chainRegistry.getChain(chainId)

val submittingMetaAccount = findMetaAccountFor(origin)
Expand All @@ -72,7 +72,7 @@ internal class RealEvmTransactionService(
val submittingMetaAccount = findMetaAccountFor(origin)
val submittingAddress = submittingMetaAccount.requireAddressIn(chain)

val web3Api = chainRegistry.awaitCallEthereumApiOrThrow(chainId)
val web3Api = chainRegistry.getCallEthereumApiOrThrow(chainId)
val txBuilder = EvmTransactionBuilder().apply(building)

val evmFee = presetFee?.castOrNull<EvmFee>() ?: run {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import io.novafoundation.nova.runtime.extrinsic.multi.ExtrinsicSplitter
import io.novafoundation.nova.runtime.extrinsic.multi.SimpleCallBuilder
import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry
import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain
import io.novafoundation.nova.runtime.multiNetwork.chain.model.ChainId
import io.novafoundation.nova.runtime.multiNetwork.getRuntime
import io.novafoundation.nova.runtime.network.rpc.RpcCalls
import jp.co.soramitsu.fearless_utils.extensions.toHexString
Expand Down Expand Up @@ -116,7 +115,7 @@ class RealExtrinsicService(
.also { it.formExtrinsic() }
.build()

return rpcCalls.getExtrinsicFee(chain.id, extrinsic)
return rpcCalls.getExtrinsicFee(chain, extrinsic)
}

override suspend fun estimateFee(
Expand All @@ -127,15 +126,16 @@ class RealExtrinsicService(
extrinsicBuilder.formExtrinsic()
val extrinsic = extrinsicBuilder.build()

return estimateFee(chain.id, extrinsic).amount
return estimateFee(chain, extrinsic).amount
}

override suspend fun estimateFeeV2(chain: Chain, formExtrinsic: suspend ExtrinsicBuilder.() -> Unit): Fee {
return InlineFee(estimateFee(chain, formExtrinsic))
}

override suspend fun estimateFee(chainId: ChainId, extrinsic: String): Fee {
val baseFee = rpcCalls.getExtrinsicFee(chainId, extrinsic).partialFee
override suspend fun estimateFee(chain: Chain, extrinsic: String): Fee {
val chainId = chain.id
val baseFee = rpcCalls.getExtrinsicFee(chain, extrinsic).partialFee

val runtime = chainRegistry.getRuntime(chainId)

Expand All @@ -151,7 +151,7 @@ class RealExtrinsicService(

val extrinsics = constructSplitExtrinsics(chain, formExtrinsic, feeExtrinsicBuilderSequence)

val separateFees = extrinsics.map { estimateFee(chain.id, it).amount }
val separateFees = extrinsics.map { estimateFee(chain, it).amount }

return separateFees.sum()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ private fun mapExtrinsicFromLocal(
val content = when (local.contentType) {
ExtrinsicTypeLocal.ContentType.SUBSTRATE_CALL -> Content.SubstrateCall(
module = local.module,
call = local.call
call = local.call.orEmpty()
)
ExtrinsicTypeLocal.ContentType.SMART_CONTRACT_CALL -> Content.ContractCall(
contractAddress = local.module,
Expand Down
Loading

0 comments on commit 1019b53

Please sign in to comment.