Skip to content

Commit

Permalink
Rc/7.7.0 (#1331)
Browse files Browse the repository at this point in the history
* Refactor local account directory. Add proxy account in db

* Add migration for proxy accounts

* Minor changes

* Proxies syncing in progress

* Implemented proxies sync

* Run ktlint

* Update RealProxySyncService.kt

* Minor changes

* Minor changes

* Clean code

* Select wallet screen + logic

* Fixed migration

* Run ktlint

* Delegated accounts updates

* Update MetaAccountWithBalanceListingMixin.kt

* Update MetaAccountGroupingInteractorImpl.kt

* Update MetaAccount.kt

* Added sort for delegated accounts

* Increase susbtrate library version

* Fixed pr notes

* Fixed pr notes

* Added run catching

* Add failure handling

* Add run catching

* Proxied signer implementation + fee signer

* Run ktlint

* Clean code

* Update AccountFeatureModule.kt

* Fixed bugs

* Fixed pr notes

* Fixed pr notes

* Update ProxiedSigner.kt

* Fixed dependencies

* Save proxieds in transaction

* Filter delayed proxies

* Feature/proxied signer (#1270)

* Proxied signer implementation + fee signer

* Run ktlint

* Clean code

* Update AccountFeatureModule.kt

* Fixed bugs

* Fixed pr notes

* Update ProxiedSigner.kt

* Fixed dependencies

* Fix merge conflicts

* Fixed delegated updates item subtitle

* Fix signing

* Fix - exotic nonce structures

* Code style

* Fix/staking paged exposures (#1267)

* Paged exposures

* Payouts

* Fixes

* Fixes

* Update tags

* Code style

* Remove unused class

* Remove unused logs

* Fix tests

* Update NftUniquesIntegrationTest.kt (#1278)

* Wallet details refactoring and Proxied wallet details implementation

* Clean code

* Fixed wildcard import

* Realtime proxy updates

* Fixes

* Code style

* Fixes

* Implemented proxy fee validation

* Code style

* Refactor extrinsic service

* Fix - send title is not visible until xcm config is synced (#1281)

* Code style

* Fixes

* Fixed proxied deactivated state

* Removed Parity sugner wallet details mixin

* Fixed imports

* Update ProxiedWalletDetailsMixin.kt

* Add proxy fee validation

* Update MetaAccountDao.kt

* Run ktlint

* Remove dependency in account build module

* Disable removing proxieds

* Fixed pr notes

* Update ProxyHaveEnoughFeeValidation.kt

* Update ProxyExtrinsicValidationRequestBusHandler.kt

* Update ProxyExtrinsicValidationRequestBusHandler.kt

* Add dwellir secret (#1295)

* Remove redundant code

* Fix/sync added accounts (#1291)

* Refactoring adding meta accounts

* Fix DI

* Refactor proxySyncService

* Removing deactivated proxieds

* Run ktlint

* Clean code

* Merge conflicts

---------

Co-authored-by: Valentun <[email protected]>

* Proxy/fee validation (#1294)

* Add support for non-requested account fee payment in validations

* Code style

* Remove debug logs

* Improve comments

* Fix conflicts

* per chain proxy sync (#1303)

* Fix/setup staking state transitions (#1302)

* Fix bugs in start staking state transitions

* Code style

* Fix - crash for proxied receive (#1304)

* Fix - proxy icon opacity (#1305)

* Fixed proxy types matching

* Fixed pr notes

* Selecting first meta account in case when selected proxied is removed due to deactivation

* Use on chain balance for proxy fee validation (#1310)

* Use on chain balance for proxy fee validation

* Rename variables

* Proxy bugs and improvements

Update proxy wiki link
Replace text in Settings account title
Update proxy type title formatting
Fixed bug when after revoke access no wallet is selected in bottom-sheet

* Update ProxyFormatter.kt

* Update ProxyFormatter.kt

* Improve account switching logic

* Fix/proxy ledger (#1313)

* Fix proxy signing with ledger

* Code style

* Do not sync WO proxies in production (#1315)

* Localization (#1316)

* Localization

* Fixes

* Fix - robonomics demoracy unlock call encoding (#1317)

* Revisit usages of all accounts (#1318)

* Fixes (#1324)

* Fix - first proxy sync after update does not detect proxy chains in config

* Fix - not enough permissions with no proxies case

* Non proxy fixes (#1325)

* Update github update link

* Fix crash when failed to retrieve metadata

* Fix tests

* Fix/staking reactive updates for relaychain staking (#1320)

* Fix reactive updates for relaychain unbondings

* Fix reactive updates for relaychain stake summary

* Fix/tests (#1319)

* Fix integration tests

* Increase timeout back

* Use wrapped payload for fee validation (#1327)

* Fixed res names and values: stacking to staking and unstacking to unstaking (#1328)

* Apply localization changes to localize

* Bump version

---------

Co-authored-by: antonijzelinskij <[email protected]>
Co-authored-by: antonijzelinskij <[email protected]>
  • Loading branch information
3 people authored Jan 18, 2024
1 parent 47e9628 commit f8bf93d
Show file tree
Hide file tree
Showing 542 changed files with 9,629 additions and 3,552 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/android_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ jobs:
fileName: ${{ inputs.keystore-file-name }}
fileDir: './app/'
encodedString: ${{ env.CI_GITHUB_KEYSTORE_KEY_FILE }}

- name: 🔐 Getting market sign key
if: ${{ startsWith(inputs.keystore-file-name, 'market_key.jks') }}
uses: timheuer/[email protected]
Expand Down
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ android {
versionNameSuffix '-github'
applicationIdSuffix '.github'

buildConfigField "String", "APP_UPDATE_SOURCE_LINK", "\"https://github.com/novasamatech/nova-wallet-android-releases/releases\""
buildConfigField "String", "APP_UPDATE_SOURCE_LINK", "\"https://github.com/novasamatech/nova-wallet-android/releases\""
}
develop {
signingConfig signingConfigs.dev
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import io.novafoundation.nova.runtime.di.RuntimeApi
import io.novafoundation.nova.runtime.di.RuntimeComponent
import io.novafoundation.nova.runtime.ext.addressOf
import io.novafoundation.nova.runtime.multiNetwork.connection.ChainConnection
import io.novafoundation.nova.runtime.storage.source.multi.MultiQueryBuilder
import io.novafoundation.nova.runtime.storage.source.query.multi
import jp.co.soramitsu.fearless_utils.runtime.AccountId
import jp.co.soramitsu.fearless_utils.runtime.definitions.types.composite.Struct
import jp.co.soramitsu.fearless_utils.runtime.metadata.storage
Expand Down Expand Up @@ -88,60 +90,71 @@ class NftUniquesIntegrationTest {

val classesIds = classesWithInstances.map { (collection, _) -> collection }.distinct()

val classMetadataStorage = runtime.metadata.uniques().storage("ClassMetadataOf")
val classStorage = runtime.metadata.uniques().storage("Class")
val instanceMetadataStorage = runtime.metadata.uniques().storage("InstanceMetadataOf")
val instanceDetailsStorage = runtime.metadata.uniques().storage("Asset")
val classDetailsDescriptor: MultiQueryBuilder.Descriptor<BigInteger, UniquesClass.Details>
val classMetadatasDescriptor: MultiQueryBuilder.Descriptor<BigInteger, UniquesClass.Metadata?>
val instancesDetailsDescriptor: MultiQueryBuilder.Descriptor<Pair<BigInteger, BigInteger>, UniquesInstance.Details>
val instancesMetadataDescriptor: MultiQueryBuilder.Descriptor<Pair<BigInteger, BigInteger>, UniquesInstance.Metadata?>

val multiQueryResults = multi {
classMetadataStorage.querySingleArgKeys(classesIds)
classStorage.querySingleArgKeys(classesIds)
instanceMetadataStorage.queryKeys(classesWithInstances)
instanceDetailsStorage.queryKeys(classesWithInstances)
}
classDetailsDescriptor = runtime.metadata.uniques().storage("Class").querySingleArgKeys(
keysArgs = classesIds,
keyExtractor = { it.component1<BigInteger>() },
binding = { parsedValue ->
val classDetailsStruct = parsedValue.cast<Struct.Instance>()

UniquesClass.Details(
instances = classDetailsStruct.getTyped("instances"),
frozen = classDetailsStruct.getTyped("isFrozen")
)
}
)

val classDetails = multiQueryResults.getValue(classStorage)
.mapKeys { (keyComponents, _) -> keyComponents.component1<BigInteger>() }
.mapValues { (_, parsedValue) ->
val classDetailsStruct = parsedValue.cast<Struct.Instance>()
classMetadatasDescriptor = runtime.metadata.uniques().storage("ClassMetadataOf").querySingleArgKeys(
keysArgs = classesIds,
keyExtractor = { it.component1<BigInteger>() },
binding = { parsedValue ->
parsedValue?.cast<Struct.Instance>()?.let { classMetadataStruct ->
UniquesClass.Metadata(
deposit = classMetadataStruct.getTyped("deposit"),
data = bindString(classMetadataStruct["data"])
)
}
}
)

UniquesClass.Details(
instances = classDetailsStruct.getTyped("instances"),
frozen = classDetailsStruct.getTyped("isFrozen")
)
}
instancesDetailsDescriptor = runtime.metadata.uniques().storage("Asset").queryKeys(
keysArgs = classesWithInstances,
keyExtractor = { it.component1<BigInteger>() to it.component2<BigInteger>() },
binding = { parsedValue ->
val instanceDetailsStruct = parsedValue.cast<Struct.Instance>()

val classMetadatas = multiQueryResults.getValue(classMetadataStorage)
.mapKeys { (keyComponents, _) -> keyComponents.component1<BigInteger>() }
.mapValues { (_, parsedValue) ->
parsedValue?.cast<Struct.Instance>()?.let { classMetadataStruct ->
UniquesClass.Metadata(
deposit = classMetadataStruct.getTyped("deposit"),
data = bindString(classMetadataStruct["data"])
UniquesInstance.Details(
owner = chain.addressOf(bindAccountId(instanceDetailsStruct["owner"])),
frozen = bindBoolean(instanceDetailsStruct["isFrozen"])
)
}
}
)

val instancesDetails = multiQueryResults.getValue(instanceDetailsStorage)
.mapKeys { (keyComponents, _) -> keyComponents.component1<BigInteger>() to keyComponents.component2<BigInteger>() }
.mapValues { (_, parsedValue) ->
val instanceDetailsStruct = parsedValue.cast<Struct.Instance>()
instancesMetadataDescriptor = runtime.metadata.uniques().storage("InstanceMetadataOf").queryKeys(
keysArgs = classesWithInstances,
keyExtractor = { it.component1<BigInteger>() to it.component2<BigInteger>() },
binding = { parsedValue ->
parsedValue?.cast<Struct.Instance>()?.let {
UniquesInstance.Metadata(
data = bindString(it["data"])
)
}
}
)
}

UniquesInstance.Details(
owner = chain.addressOf(bindAccountId(instanceDetailsStruct["owner"])),
frozen = bindBoolean(instanceDetailsStruct["isFrozen"])
)
}
val classDetails = multiQueryResults[classDetailsDescriptor]

val instancesMetadatas = multiQueryResults.getValue(instanceMetadataStorage)
.mapKeys { (keyComponents, _) -> keyComponents.component1<BigInteger>() to keyComponents.component2<BigInteger>() }
.mapValues { (_, parsedValue) ->
parsedValue?.cast<Struct.Instance>()?.let {
UniquesInstance.Metadata(
data = bindString(it["data"])
)
}
}
val classMetadatas = multiQueryResults[classMetadatasDescriptor]

val instancesDetails = multiQueryResults[instancesDetailsDescriptor]

val instancesMetadatas = multiQueryResults[instancesMetadataDescriptor]

val classes = classesIds.associateWith { classId ->
UniquesClass(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,15 @@ import com.google.gson.Gson
import io.novafoundation.nova.common.data.network.runtime.binding.AccountInfo
import io.novafoundation.nova.common.data.network.runtime.binding.bindAccountInfo
import io.novafoundation.nova.common.di.FeatureUtils
import io.novafoundation.nova.common.utils.emptyEthereumAccountId
import io.novafoundation.nova.common.utils.emptySubstrateAccountId
import io.novafoundation.nova.common.utils.fromJson
import io.novafoundation.nova.common.utils.hasModule
import io.novafoundation.nova.common.utils.system
import io.novafoundation.nova.feature_account_api.data.ethereum.transaction.TransactionOrigin
import io.novafoundation.nova.feature_account_api.di.AccountFeatureApi
import io.novafoundation.nova.feature_account_api.domain.model.LightMetaAccount
import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount
import io.novafoundation.nova.feature_account_impl.di.AccountFeatureComponent
import io.novafoundation.nova.runtime.BuildConfig.TEST_CHAINS_URL
import io.novafoundation.nova.runtime.di.RuntimeApi
Expand Down Expand Up @@ -122,7 +127,7 @@ class BalancesIntegrationTest(
private suspend fun testFeeLoadingAsync(chain: Chain) {
return coroutineScope {
withTimeout(80.seconds) {
extrinsicService.estimateFee(chain) {
extrinsicService.estimateFee(chain, testTransactionOrigin()) {
systemRemark(byteArrayOf(0))

val haveBatch = runtime.metadata.hasModule("Utility")
Expand All @@ -133,4 +138,21 @@ class BalancesIntegrationTest(
}
}
}

private fun testTransactionOrigin(): TransactionOrigin = TransactionOrigin.Wallet(
MetaAccount(
id = 0,
chainAccounts = emptyMap(),
proxy = null,
substratePublicKey = null,
substrateCryptoType = null,
substrateAccountId = emptySubstrateAccountId(),
ethereumAddress = emptyEthereumAccountId(),
ethereumPublicKey = null,
isSelected = true,
name = "Test",
type = LightMetaAccount.Type.WATCH_ONLY,
status = LightMetaAccount.Status.ACTIVE
)
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import io.novafoundation.nova.common.utils.coroutines.RootScope
import io.novafoundation.nova.common.utils.sequrity.AutomaticInteractionGate
import io.novafoundation.nova.common.utils.sequrity.BackgroundAccessObserver
import io.novafoundation.nova.common.utils.systemCall.SystemCallExecutor
import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService
import io.novafoundation.nova.feature_account_api.data.proxy.validation.ProxyExtrinsicValidationRequestBus
import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository
import io.novafoundation.nova.feature_account_api.domain.account.common.EncryptionDefaults
import io.novafoundation.nova.feature_assets.data.network.BalancesUpdateSystem
Expand All @@ -21,6 +23,7 @@ import io.novafoundation.nova.feature_governance_api.data.MutableGovernanceState
import io.novafoundation.nova.feature_staking_api.domain.api.StakingRepository
import io.novafoundation.nova.feature_versions_api.domain.UpdateNotificationsInteractor
import io.novafoundation.nova.feature_wallet_api.domain.interfaces.WalletRepository
import io.novafoundation.nova.feature_wallet_api.domain.validation.ProxyHaveEnoughFeeValidationFactory
import io.novafoundation.nova.feature_wallet_connect_api.domain.sessions.WalletConnectSessionsUseCase
import io.novafoundation.nova.feature_wallet_connect_api.presentation.WalletConnectService
import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry
Expand Down Expand Up @@ -61,12 +64,18 @@ interface RootDependencies {

fun rootScope(): RootScope

fun proxySyncService(): ProxySyncService

fun governanceStateUpdater(): MutableGovernanceState

fun dappMetadataRepository(): DAppMetadataRepository

fun encryptionDefaults(): EncryptionDefaults

fun proxyExtrinsicValidationRequestBus(): ProxyExtrinsicValidationRequestBus

fun proxyHaveEnoughFeeValidationFactory(): ProxyHaveEnoughFeeValidationFactory

val systemCallExecutor: SystemCallExecutor

val contextManager: ContextManager
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,30 @@ package io.novafoundation.nova.app.root.di

import dagger.Module
import dagger.Provides
import io.novafoundation.nova.app.root.di.busHandler.RequestBusHandlerModule
import io.novafoundation.nova.app.root.domain.RootInteractor
import io.novafoundation.nova.common.di.scope.FeatureScope
import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService
import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository
import io.novafoundation.nova.feature_assets.data.network.BalancesUpdateSystem
import io.novafoundation.nova.feature_wallet_api.domain.interfaces.WalletRepository

@Module
@Module(includes = [RequestBusHandlerModule::class])
class RootFeatureModule {

@Provides
@FeatureScope
fun provideRootInteractor(
walletRepository: WalletRepository,
accountRepository: AccountRepository,
balancesUpdateSystem: BalancesUpdateSystem
balancesUpdateSystem: BalancesUpdateSystem,
proxySyncService: ProxySyncService
): RootInteractor {
return RootInteractor(
updateSystem = balancesUpdateSystem,
walletRepository = walletRepository,
accountRepository = accountRepository
accountRepository = accountRepository,
proxySyncService = proxySyncService
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package io.novafoundation.nova.app.root.di.busHandler

import dagger.Module
import dagger.Provides
import dagger.multibindings.IntoSet
import io.novafoundation.nova.app.root.presentation.requestBusHandler.CompoundRequestBusHandler
import io.novafoundation.nova.app.root.presentation.requestBusHandler.ProxyExtrinsicValidationRequestBusHandler
import io.novafoundation.nova.app.root.presentation.requestBusHandler.RequestBusHandler
import io.novafoundation.nova.common.di.scope.FeatureScope
import io.novafoundation.nova.common.resources.ResourceManager
import io.novafoundation.nova.common.utils.coroutines.RootScope
import io.novafoundation.nova.feature_account_api.data.proxy.validation.ProxyExtrinsicValidationRequestBus
import io.novafoundation.nova.feature_wallet_api.domain.validation.ProxyHaveEnoughFeeValidationFactory

@Module
class RequestBusHandlerModule {

@Provides
@FeatureScope
@IntoSet
fun provideProxyExtrinsicValidationRequestBusHandler(
scope: RootScope,
proxyProxyExtrinsicValidationRequestBus: ProxyExtrinsicValidationRequestBus,
proxyHaveEnoughFeeValidationFactory: ProxyHaveEnoughFeeValidationFactory,
resourceManager: ResourceManager
): RequestBusHandler {
return ProxyExtrinsicValidationRequestBusHandler(
scope,
proxyProxyExtrinsicValidationRequestBus,
proxyHaveEnoughFeeValidationFactory,
resourceManager
)
}

@Provides
@FeatureScope
fun provideCompoundRequestBusHandler(
handlers: Set<@JvmSuppressWildcards RequestBusHandler>
): CompoundRequestBusHandler {
return CompoundRequestBusHandler(handlers)
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
package io.novafoundation.nova.app.root.domain

import io.novafoundation.nova.core.updater.Updater
import io.novafoundation.nova.feature_account_api.data.proxy.ProxySyncService
import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository
import io.novafoundation.nova.feature_assets.data.network.BalancesUpdateSystem
import io.novafoundation.nova.feature_buy_impl.domain.providers.ExternalProvider
import io.novafoundation.nova.feature_wallet_api.domain.interfaces.WalletRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.mapLatest

class RootInteractor(
private val updateSystem: BalancesUpdateSystem,
private val walletRepository: WalletRepository,
private val accountRepository: AccountRepository
private val accountRepository: AccountRepository,
private val proxySyncService: ProxySyncService
) {

fun runBalancesUpdate(): Flow<Updater.SideEffect> = updateSystem.start()
Expand All @@ -30,4 +33,10 @@ class RootInteractor(
suspend fun isPinCodeSet(): Boolean {
return accountRepository.isCodeSet()
}

fun syncProxies(): Flow<*> {
return proxySyncService.proxySyncTrigger().mapLatest {
proxySyncService.startSyncingSuspend()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import io.novafoundation.nova.feature_account_api.presenatation.account.add.Impo
import io.novafoundation.nova.feature_account_impl.presentation.AccountRouter
import io.novafoundation.nova.feature_account_impl.presentation.account.advancedEncryption.AdvancedEncryptionFragment
import io.novafoundation.nova.feature_account_impl.presentation.account.advancedEncryption.AdvancedEncryptionModePayload
import io.novafoundation.nova.feature_account_impl.presentation.account.details.AccountDetailsFragment
import io.novafoundation.nova.feature_account_impl.presentation.account.details.WalletDetailsFragment
import io.novafoundation.nova.feature_account_impl.presentation.exporting.ExportPayload
import io.novafoundation.nova.feature_account_impl.presentation.exporting.json.confirm.ExportJsonConfirmFragment
import io.novafoundation.nova.feature_account_impl.presentation.exporting.json.confirm.ExportJsonConfirmPayload
Expand Down Expand Up @@ -179,7 +179,7 @@ class Navigator(
val destination = when (val currentDestinationId = navController?.currentDestination?.id) {
R.id.welcomeFragment -> R.id.action_welcomeFragment_to_mnemonic_nav_graph
R.id.createAccountFragment -> R.id.action_createAccountFragment_to_mnemonic_nav_graph
R.id.accountDetailsFragment -> R.id.action_accountDetailsFragment_to_mnemonic_nav_graph
R.id.walletDetailsFragment -> R.id.action_accountDetailsFragment_to_mnemonic_nav_graph
else -> throw IllegalArgumentException("Unknown current destination to open mnemonic screen: $currentDestinationId")
}

Expand Down Expand Up @@ -284,6 +284,10 @@ class Navigator(
navController?.navigate(R.id.action_open_switch_wallet)
}

override fun openDelegatedAccountsUpdates() {
navController?.navigate(R.id.action_switchWalletFragment_to_delegatedAccountUpdates)
}

override fun openSelectAddress(arguments: Bundle) {
navController?.navigate(R.id.action_open_select_address, arguments)
}
Expand Down Expand Up @@ -405,8 +409,8 @@ class Navigator(
}
}

override fun openAccountDetails(metaId: Long) {
val extras = AccountDetailsFragment.getBundle(metaId)
override fun openWalletDetails(metaId: Long) {
val extras = WalletDetailsFragment.getBundle(metaId)

navController?.navigate(R.id.action_open_account_details, extras)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ class GovernanceNavigator(
}
}

override fun openAccountDetails(id: Long) {
commonNavigator.openAccountDetails(id)
override fun openWalletDetails(id: Long) {
commonNavigator.openWalletDetails(id)
}

override fun openAddDelegation() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ class SettingsNavigator(
args = PincodeFragment.getPinCodeBundle(PinCodeAction.Change)
)

override fun openAccountDetails(metaId: Long) {
delegate.openAccountDetails(metaId)
override fun openWalletDetails(metaId: Long) {
delegate.openWalletDetails(metaId)
}

override fun openSwitchWallet() {
Expand Down
Loading

0 comments on commit f8bf93d

Please sign in to comment.