From 428c0bb09d107fa7163fd44df5b89c05e2bf4423 Mon Sep 17 00:00:00 2001
From: Aleksey Kazakov <kazakov@soramitsu.co.jp>
Date: Thu, 30 Nov 2023 17:59:37 +0300
Subject: [PATCH 01/35] turn off checks switch to test jenkins library branch

---
 Jenkinsfile | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/Jenkinsfile b/Jenkinsfile
index 28a32a5f6a..75270da343 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -1,4 +1,4 @@
-@Library('jenkins-library')
+@Library('jenkins-library@feature/2890/upload-android-app-to-nexus')
 
 // Job properties
 def jobParams = [
@@ -7,7 +7,9 @@ def jobParams = [
 
 def pipeline = new org.android.AppPipeline(
     steps:            this,
-    sonar:            true,
+    sonar:            false,
+    test:             false,
+    dojo:             false, 
     sonarCommand:     './gradlew sonar -x :core-db:compileDebugUnitTestKotlin -x :core-db:compileDebugAndroidTestKotlin -x :feature-crowdloan-impl:compileDebugAndroidTestKotlin -x :runtime:compileDebugUnitTestKotlin -x :app:kaptDebugAndroidTestKotlin -x :app:compileDebugAndroidTestKotlin -Dsonar.coverage.jacoco.xmlReportPaths=**/coverage/*.xml',
     sonarProjectName: 'fearless-android',
     sonarProjectKey:  'fearless:fearless-android',

From f0ca9bb8e92fd9b6e152ee8214d277d068dcd98f Mon Sep 17 00:00:00 2001
From: Aleksey Kazakov <kazakov@soramitsu.co.jp>
Date: Fri, 8 Dec 2023 15:05:31 +0300
Subject: [PATCH 02/35] add param upload_to_nexus

---
 Jenkinsfile | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Jenkinsfile b/Jenkinsfile
index 75270da343..54003b4b6a 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -3,6 +3,7 @@
 // Job properties
 def jobParams = [
   booleanParam(defaultValue: false, description: 'push to the dev profile', name: 'prDeployment'),
+  booleanParam(defaultValue: false, description: 'Upload builds to nexus(master branches upload always)', name: 'upload_to_nexus'),
 ]
 
 def pipeline = new org.android.AppPipeline(
@@ -19,6 +20,7 @@ def pipeline = new org.android.AppPipeline(
     publishCmd:       'publishReleaseApk',
     jobParams:        jobParams,
     appPushNoti:      true,
-    dojoProductType:  'android'
+    dojoProductType:  'android',
+    uploadToNexusFor: ['master','develop','stage'],
 )
 pipeline.runPipeline('fearless')

From ce395715cae349617f92deb5aa596ddb6a5eeb89 Mon Sep 17 00:00:00 2001
From: Aleksey Kazakov <kazakov@soramitsu.co.jp>
Date: Tue, 16 Jan 2024 13:59:11 +0300
Subject: [PATCH 03/35] return tests

---
 Jenkinsfile | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/Jenkinsfile b/Jenkinsfile
index 54003b4b6a..30f578d4c7 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -9,8 +9,6 @@ def jobParams = [
 def pipeline = new org.android.AppPipeline(
     steps:            this,
     sonar:            false,
-    test:             false,
-    dojo:             false, 
     sonarCommand:     './gradlew sonar -x :core-db:compileDebugUnitTestKotlin -x :core-db:compileDebugAndroidTestKotlin -x :feature-crowdloan-impl:compileDebugAndroidTestKotlin -x :runtime:compileDebugUnitTestKotlin -x :app:kaptDebugAndroidTestKotlin -x :app:compileDebugAndroidTestKotlin -Dsonar.coverage.jacoco.xmlReportPaths=**/coverage/*.xml',
     sonarProjectName: 'fearless-android',
     sonarProjectKey:  'fearless:fearless-android',
@@ -21,6 +19,6 @@ def pipeline = new org.android.AppPipeline(
     jobParams:        jobParams,
     appPushNoti:      true,
     dojoProductType:  'android',
-    uploadToNexusFor: ['master','develop','stage'],
+    uploadToNexusFor: ['master','develop','staging']
 )
 pipeline.runPipeline('fearless')

From 62bd7d10aa041a3018533ab71be96a3382abcea0 Mon Sep 17 00:00:00 2001
From: Aleksey Kazakov <kazakov@soramitsu.co.jp>
Date: Tue, 16 Jan 2024 14:27:37 +0300
Subject: [PATCH 04/35] add sonar test

---
 Jenkinsfile | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Jenkinsfile b/Jenkinsfile
index 30f578d4c7..757d0c0839 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -3,12 +3,12 @@
 // Job properties
 def jobParams = [
   booleanParam(defaultValue: false, description: 'push to the dev profile', name: 'prDeployment'),
-  booleanParam(defaultValue: false, description: 'Upload builds to nexus(master branches upload always)', name: 'upload_to_nexus'),
+  booleanParam(defaultValue: false, description: 'Upload builds to nexus(master,develop and staging branches upload always)', name: 'upload_to_nexus'),
 ]
 
 def pipeline = new org.android.AppPipeline(
     steps:            this,
-    sonar:            false,
+    sonar:            true,
     sonarCommand:     './gradlew sonar -x :core-db:compileDebugUnitTestKotlin -x :core-db:compileDebugAndroidTestKotlin -x :feature-crowdloan-impl:compileDebugAndroidTestKotlin -x :runtime:compileDebugUnitTestKotlin -x :app:kaptDebugAndroidTestKotlin -x :app:compileDebugAndroidTestKotlin -Dsonar.coverage.jacoco.xmlReportPaths=**/coverage/*.xml',
     sonarProjectName: 'fearless-android',
     sonarProjectKey:  'fearless:fearless-android',

From 2f546751fd7b6adec5948af6513ee2c7e2fabe3e Mon Sep 17 00:00:00 2001
From: Aleksey Kazakov <kazakov@soramitsu.co.jp>
Date: Thu, 18 Jan 2024 14:03:10 +0300
Subject: [PATCH 05/35] switch back on master branch for jenkins lib

---
 Jenkinsfile | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Jenkinsfile b/Jenkinsfile
index 757d0c0839..ae1e104dfb 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -1,4 +1,4 @@
-@Library('jenkins-library@feature/2890/upload-android-app-to-nexus')
+@Library('jenkins-library')
 
 // Job properties
 def jobParams = [
@@ -21,4 +21,4 @@ def pipeline = new org.android.AppPipeline(
     dojoProductType:  'android',
     uploadToNexusFor: ['master','develop','staging']
 )
-pipeline.runPipeline('fearless')
+pipeline.runPipeline('fearless')
\ No newline at end of file

From ba2d9a527203e5fdce865dcbff5bb3d43bb6617a Mon Sep 17 00:00:00 2001
From: Sergey Pankratov <pankratov@soramitsu.co.jp>
Date: Tue, 6 Feb 2024 18:00:53 +0500
Subject: [PATCH 06/35] chainlink

---
 build.gradle                                  |  4 +-
 .../jp/co/soramitsu/coredb/dao/Helpers.kt     | 12 ++-
 .../jp/co/soramitsu/coredb/AppDatabase.kt     |  4 +-
 .../co/soramitsu/coredb/dao/TokenPriceDao.kt  |  3 +
 .../soramitsu/coredb/migrations/Migrations.kt | 34 +++++++++
 .../coredb/model/chain/ChainAssetLocal.kt     |  5 +-
 .../coredb/model/chain/ChainLocal.kt          |  3 +-
 .../interfaces/AssetNotNeedAccountUseCase.kt  |  1 -
 .../domain/AssetNotNeedAccountUseCaseImpl.kt  |  6 +-
 .../details/AccountDetailsViewModel.kt        | 16 +---
 .../rewards/SoraStakingRewardsScenario.kt     |  2 +-
 .../wallet/api/data/cache/AssetCache.kt       | 35 ++++++---
 .../domain/interfaces/WalletInteractor.kt     |  2 -
 .../domain/interfaces/WalletRepository.kt     |  2 -
 .../impl/domain/model/BuyTokenRegistry.kt     |  2 +-
 feature-wallet-impl/build.gradle              |  2 +
 .../blockchain/EthereumRemoteSource.kt        | 54 +++++++++++++
 .../data/repository/TokenRepositoryImpl.kt    |  6 +-
 .../data/repository/WalletRepositoryImpl.kt   | 76 +++++++++++++++----
 .../wallet/impl/di/WalletFeatureModule.kt     |  5 +-
 .../wallet/impl/domain/ChainInteractor.kt     |  6 +-
 .../impl/domain/WalletInteractorImpl.kt       |  4 -
 .../balance/list/BalanceListViewModel.kt      |  2 +-
 .../list/model/BalanceListItemModel.kt        |  2 +-
 gradle/libs.versions.toml                     |  2 +-
 .../runtime/multiNetwork/ChainRegistry.kt     |  2 +-
 .../runtime/multiNetwork/chain/Mappers.kt     | 27 +++++--
 .../runtime/multiNetwork/chain/model/Chain.kt | 11 ++-
 .../chain/remote/model/ChainAssetRemote.kt    |  5 +-
 .../multiNetwork/connection/ConnectionPool.kt |  2 +-
 .../chain/ChainSyncServiceTest.kt             |  3 +-
 31 files changed, 254 insertions(+), 86 deletions(-)

diff --git a/build.gradle b/build.gradle
index bc64dc3901..ddda60abe4 100644
--- a/build.gradle
+++ b/build.gradle
@@ -83,7 +83,7 @@ buildscript {
         minifyRelease = true
         beaconVersion = "3.2.4"
 
-        sharedFeaturesVersion = "1.1.1.20-FLW"
+        sharedFeaturesVersion = "1.1.1.22-FLW"
 
         coilDep = "io.coil-kt:coil:$coilVersion"
         coilSvg = "io.coil-kt:coil-svg:$coilVersion"
@@ -207,6 +207,8 @@ buildscript {
         sharedFeaturesBackupDep = "jp.co.soramitsu.shared_features:backup:$sharedFeaturesVersion"
 
         web3jDep = "org.web3j:core:4.8.8-android"
+        web3jContractsDep = "org.web3j:contracts:4.8.8-android"
+        web3jGethDep = "org.web3j:geth:4.8.8-android"
 
         withoutJavaWS = { exclude module: 'java-websocket-lib' }
 
diff --git a/core-db/src/androidTest/java/jp/co/soramitsu/coredb/dao/Helpers.kt b/core-db/src/androidTest/java/jp/co/soramitsu/coredb/dao/Helpers.kt
index 54bd810cd3..6eab1eb513 100644
--- a/core-db/src/androidTest/java/jp/co/soramitsu/coredb/dao/Helpers.kt
+++ b/core-db/src/androidTest/java/jp/co/soramitsu/coredb/dao/Helpers.kt
@@ -40,7 +40,11 @@ fun chainOf(
     externalApi = null,
     hasCrowdloans = false,
     minSupportedVersion = "2.0.3",
-    supportStakingPool = false
+    supportStakingPool = false,
+    isEthereumChain = false,
+    paraId = null,
+    rank = null,
+    isChainlinkProvider = false
 )
 
 fun ChainLocal.nodeOf(
@@ -64,14 +68,16 @@ fun ChainLocal.assetOf(
     priceId = null,
     staking = "test",
     icon = "",
-    priceProviders = null,
+    purchaseProviders = null,
     symbol = symbol,
     isUtility = null,
     type = null,
     currencyId = null,
     existentialDeposit = null,
     color = null,
-    isNative = null
+    isNative = null,
+    ethereumType = null,
+    priceProvider = null
 )
 
 suspend fun ChainDao.addChain(joinedChainInfo: JoinedChainInfo) {
diff --git a/core-db/src/main/java/jp/co/soramitsu/coredb/AppDatabase.kt b/core-db/src/main/java/jp/co/soramitsu/coredb/AppDatabase.kt
index 45459e8db2..2940ee74e0 100644
--- a/core-db/src/main/java/jp/co/soramitsu/coredb/AppDatabase.kt
+++ b/core-db/src/main/java/jp/co/soramitsu/coredb/AppDatabase.kt
@@ -63,6 +63,7 @@ import jp.co.soramitsu.coredb.migrations.Migration_56_57
 import jp.co.soramitsu.coredb.migrations.Migration_57_58
 import jp.co.soramitsu.coredb.migrations.Migration_58_59
 import jp.co.soramitsu.coredb.migrations.Migration_59_60
+import jp.co.soramitsu.coredb.migrations.Migration_60_61
 import jp.co.soramitsu.coredb.migrations.RemoveAccountForeignKeyFromAsset_17_18
 import jp.co.soramitsu.coredb.migrations.RemoveLegacyData_35_36
 import jp.co.soramitsu.coredb.migrations.RemoveStakingRewardsTable_22_23
@@ -88,7 +89,7 @@ import jp.co.soramitsu.coredb.model.chain.FavoriteChainLocal
 import jp.co.soramitsu.coredb.model.chain.MetaAccountLocal
 
 @Database(
-    version = 60,
+    version = 61,
     entities = [
         AccountLocal::class,
         AddressBookContact::class,
@@ -169,6 +170,7 @@ abstract class AppDatabase : RoomDatabase() {
                     .addMigrations(Migration_57_58)
                     .addMigrations(Migration_58_59)
                     .addMigrations(Migration_59_60)
+                    .addMigrations(Migration_60_61)
                     .build()
             }
             return instance!!
diff --git a/core-db/src/main/java/jp/co/soramitsu/coredb/dao/TokenPriceDao.kt b/core-db/src/main/java/jp/co/soramitsu/coredb/dao/TokenPriceDao.kt
index 445b7b4372..5b4eab0d4a 100644
--- a/core-db/src/main/java/jp/co/soramitsu/coredb/dao/TokenPriceDao.kt
+++ b/core-db/src/main/java/jp/co/soramitsu/coredb/dao/TokenPriceDao.kt
@@ -22,6 +22,9 @@ abstract class TokenPriceDao {
     @Insert(onConflict = OnConflictStrategy.REPLACE)
     abstract suspend fun insertTokenPrice(token: TokenPriceLocal)
 
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    abstract suspend fun insertTokensPrice(tokens: List<TokenPriceLocal>)
+
     @Insert(onConflict = OnConflictStrategy.IGNORE)
     abstract suspend fun insertTokenPriceOrIgnore(token: TokenPriceLocal)
 
diff --git a/core-db/src/main/java/jp/co/soramitsu/coredb/migrations/Migrations.kt b/core-db/src/main/java/jp/co/soramitsu/coredb/migrations/Migrations.kt
index 3b871a1ab8..5b83d10592 100644
--- a/core-db/src/main/java/jp/co/soramitsu/coredb/migrations/Migrations.kt
+++ b/core-db/src/main/java/jp/co/soramitsu/coredb/migrations/Migrations.kt
@@ -3,6 +3,40 @@ package jp.co.soramitsu.coredb.migrations
 import androidx.room.migration.Migration
 import androidx.sqlite.db.SupportSQLiteDatabase
 
+val Migration_60_61 = object : Migration(60, 61) {
+    override fun migrate(database: SupportSQLiteDatabase) {
+        database.execSQL("ALTER TABLE chains ADD COLUMN `isChainlinkProvider` INTEGER NOT NULL DEFAULT 0")
+
+        database.execSQL("DROP TABLE IF EXISTS chain_assets")
+
+        database.execSQL(
+            """
+            CREATE TABLE IF NOT EXISTS `chain_assets` (
+            `id` TEXT NOT NULL, 
+            `name` TEXT, 
+            `symbol` TEXT NOT NULL, 
+            `chainId` TEXT NOT NULL, 
+            `icon` TEXT NOT NULL, 
+            `priceId` TEXT, 
+            `staking` TEXT NOT NULL, 
+            `precision` INTEGER NOT NULL, 
+            `purchaseProviders` TEXT, 
+            `isUtility` INTEGER, 
+            `type` TEXT, 
+            `currencyId` TEXT, 
+            `existentialDeposit` TEXT, 
+            `color` TEXT, 
+            `isNative` INTEGER, 
+            `ethereumType` TEXT DEFAULT NULL,
+            `priceProvider` TEXT, 
+            PRIMARY KEY(`chainId`, `id`), 
+            FOREIGN KEY(`chainId`) REFERENCES `chains`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )
+            """.trimIndent()
+        )
+        database.execSQL("CREATE INDEX IF NOT EXISTS `index_chain_assets_chainId` ON `chain_assets` (`chainId`)")
+    }
+}
+
 val Migration_59_60 = object : Migration(59, 60) {
     override fun migrate(database: SupportSQLiteDatabase) {
         database.execSQL("ALTER TABLE chains ADD COLUMN `paraId` TEXT NULL")
diff --git a/core-db/src/main/java/jp/co/soramitsu/coredb/model/chain/ChainAssetLocal.kt b/core-db/src/main/java/jp/co/soramitsu/coredb/model/chain/ChainAssetLocal.kt
index efed568351..df010a5c4c 100644
--- a/core-db/src/main/java/jp/co/soramitsu/coredb/model/chain/ChainAssetLocal.kt
+++ b/core-db/src/main/java/jp/co/soramitsu/coredb/model/chain/ChainAssetLocal.kt
@@ -28,12 +28,13 @@ data class ChainAssetLocal(
     val priceId: String?,
     val staking: String,
     val precision: Int,
-    val priceProviders: String?,
+    val purchaseProviders: String?,
     val isUtility: Boolean?,
     val type: String?,
     val currencyId: String?,
     val existentialDeposit: String?,
     val color: String?,
     val isNative: Boolean?,
-    val ethereumType: String?
+    val ethereumType: String?,
+    val priceProvider: String?
 )
diff --git a/core-db/src/main/java/jp/co/soramitsu/coredb/model/chain/ChainLocal.kt b/core-db/src/main/java/jp/co/soramitsu/coredb/model/chain/ChainLocal.kt
index cc297c4e51..e886b1075b 100644
--- a/core-db/src/main/java/jp/co/soramitsu/coredb/model/chain/ChainLocal.kt
+++ b/core-db/src/main/java/jp/co/soramitsu/coredb/model/chain/ChainLocal.kt
@@ -20,7 +20,8 @@ class ChainLocal(
     val isTestNet: Boolean,
     val hasCrowdloans: Boolean,
     val supportStakingPool: Boolean,
-    val isEthereumChain: Boolean
+    val isEthereumChain: Boolean,
+    val isChainlinkProvider: Boolean
 ) {
 
     class ExternalApi(
diff --git a/feature-account-api/src/main/java/jp/co/soramitsu/account/api/domain/interfaces/AssetNotNeedAccountUseCase.kt b/feature-account-api/src/main/java/jp/co/soramitsu/account/api/domain/interfaces/AssetNotNeedAccountUseCase.kt
index 23b169570d..ab3df4da98 100644
--- a/feature-account-api/src/main/java/jp/co/soramitsu/account/api/domain/interfaces/AssetNotNeedAccountUseCase.kt
+++ b/feature-account-api/src/main/java/jp/co/soramitsu/account/api/domain/interfaces/AssetNotNeedAccountUseCase.kt
@@ -9,7 +9,6 @@ interface AssetNotNeedAccountUseCase {
      * Mark asset without account - as correct, no need of account
      * used in lists sort
      */
-    suspend fun markNotNeed(chainId: ChainId, metaId: Long, assetId: String, priceId: String?)
     suspend fun markChainAssetsNotNeed(chainId: ChainId, metaId: Long)
 
     /**
diff --git a/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/domain/AssetNotNeedAccountUseCaseImpl.kt b/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/domain/AssetNotNeedAccountUseCaseImpl.kt
index 6faaa72030..fb9cb2bf0c 100644
--- a/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/domain/AssetNotNeedAccountUseCaseImpl.kt
+++ b/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/domain/AssetNotNeedAccountUseCaseImpl.kt
@@ -17,14 +17,10 @@ class AssetNotNeedAccountUseCaseImpl(
     private val tokenPriceDao: TokenPriceDao
 ) : AssetNotNeedAccountUseCase {
 
-    override suspend fun markNotNeed(chainId: ChainId, metaId: Long, assetId: String, priceId: String?) {
-        updateAssetNotNeed(metaId, chainId, assetId, priceId)
-    }
-
     override suspend fun markChainAssetsNotNeed(chainId: ChainId, metaId: Long) {
         val chainAssets = chainRegistry.getChain(chainId).assets
         chainAssets.forEach {
-            updateAssetNotNeed(metaId, chainId, it.id, it.priceId)
+            updateAssetNotNeed(metaId, chainId, it.id, it.priceProvider?.id ?: it.priceId)
         }
     }
 
diff --git a/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/presentation/account/details/AccountDetailsViewModel.kt b/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/presentation/account/details/AccountDetailsViewModel.kt
index 97f5404b98..0ba2c7e5a7 100644
--- a/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/presentation/account/details/AccountDetailsViewModel.kt
+++ b/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/presentation/account/details/AccountDetailsViewModel.kt
@@ -256,7 +256,7 @@ class AccountDetailsViewModel @Inject constructor(
                     chainId = item.chainId,
                     chainName = item.chainName,
                     assetId = utilityAsset?.id.orEmpty(),
-                    priceId = utilityAsset?.priceId,
+                    priceId = utilityAsset?.priceProvider?.id ?: utilityAsset?.priceId,
                     markedAsNotNeed = item.markedAsNotNeed
                 )
                 accountRouter.openOptionsAddAccount(payload)
@@ -277,18 +277,4 @@ class AccountDetailsViewModel @Inject constructor(
     fun updateAppClicked() {
         _openPlayMarket.value = Event(Unit)
     }
-
-    fun createAccount(chainId: ChainId, metaId: Long) {
-        accountRouter.openOnboardingNavGraph(chainId = chainId, metaId = metaId, isImport = false)
-    }
-
-    fun importAccount(chainId: ChainId, metaId: Long) {
-        accountRouter.openOnboardingNavGraph(chainId = chainId, metaId = metaId, isImport = true)
-    }
-
-    fun noNeedAccount(chainId: ChainId, metaId: Long, assetId: String, priceId: String?) {
-        launch {
-            assetNotNeedAccount.markNotNeed(chainId = chainId, metaId = metaId, assetId = assetId, priceId = priceId)
-        }
-    }
 }
diff --git a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/domain/rewards/SoraStakingRewardsScenario.kt b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/domain/rewards/SoraStakingRewardsScenario.kt
index 7617aba743..e3f714a1d7 100644
--- a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/domain/rewards/SoraStakingRewardsScenario.kt
+++ b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/domain/rewards/SoraStakingRewardsScenario.kt
@@ -37,7 +37,7 @@ class SoraStakingRewardsScenario(
     suspend fun getRewardAsset(): Token {
         val chain = chainRegistry.getChain(SORA_MAIN_NET_CHAIN_ID)
         val rewardAsset = requireNotNull(chain.assetsById[REWARD_ASSET_ID])
-        val priceId = requireNotNull(rewardAsset.priceId)
+        val priceId = requireNotNull(rewardAsset.priceProvider?.id ?: rewardAsset.priceId)
         val token = tokenDao.getTokenPrice(priceId)
 
         return Token(
diff --git a/feature-wallet-api/src/main/java/jp/co/soramitsu/wallet/api/data/cache/AssetCache.kt b/feature-wallet-api/src/main/java/jp/co/soramitsu/wallet/api/data/cache/AssetCache.kt
index 219699b8a6..c9cd697550 100644
--- a/feature-wallet-api/src/main/java/jp/co/soramitsu/wallet/api/data/cache/AssetCache.kt
+++ b/feature-wallet-api/src/main/java/jp/co/soramitsu/wallet/api/data/cache/AssetCache.kt
@@ -1,6 +1,7 @@
 package jp.co.soramitsu.wallet.api.data.cache
 
 import jp.co.soramitsu.account.api.domain.interfaces.AccountRepository
+import jp.co.soramitsu.common.domain.SelectedFiat
 import jp.co.soramitsu.common.mixin.api.UpdatesMixin
 import jp.co.soramitsu.common.mixin.api.UpdatesProviderUi
 import jp.co.soramitsu.core.models.Asset
@@ -21,7 +22,8 @@ class AssetCache(
     private val tokenPriceDao: TokenPriceDao,
     private val accountRepository: AccountRepository,
     private val assetDao: AssetDao,
-    private val updatesMixin: UpdatesMixin
+    private val updatesMixin: UpdatesMixin,
+    private val selectedFiat: SelectedFiat
 ) : AssetReadOnlyCache by assetDao,
     UpdatesProviderUi by updatesMixin {
 
@@ -35,7 +37,12 @@ class AssetCache(
     ) = withContext(Dispatchers.IO) {
         val chainId = chainAsset.chainId
         val assetId = chainAsset.id
-        val priceId = chainAsset.priceId
+        val shouldUseChainlinkForRates = selectedFiat.get() == "usd" && chainAsset.priceProvider?.id != null
+        val priceId = if (shouldUseChainlinkForRates) {
+            chainAsset.priceProvider?.id
+        } else {
+            chainAsset.priceId
+        }
 
         assetUpdateMutex.withLock {
             priceId?.let { tokenPriceDao.ensureTokenPrice(it) }
@@ -56,26 +63,27 @@ class AssetCache(
 
                 cachedAsset.accountId.contentEquals(emptyAccountIdValue) -> {
                     assetDao.deleteAsset(metaId, emptyAccountIdValue, chainId, assetId)
-                    assetDao.insertAsset(builder.invoke(cachedAsset.copy(accountId = accountId)))
+                    assetDao.insertAsset(builder.invoke(cachedAsset.copy(accountId = accountId, tokenPriceId = priceId)))
                 }
 
                 else -> {
-                    val updatedAsset = builder.invoke(cachedAsset)
+                    val updatedAsset = builder.invoke(cachedAsset.copy(tokenPriceId = priceId))
                     if (cachedAsset.bondedInPlanks == updatedAsset.bondedInPlanks &&
                         cachedAsset.feeFrozenInPlanks == updatedAsset.feeFrozenInPlanks &&
                         cachedAsset.miscFrozenInPlanks == updatedAsset.miscFrozenInPlanks &&
                         cachedAsset.freeInPlanks == updatedAsset.freeInPlanks &&
                         cachedAsset.redeemableInPlanks == updatedAsset.redeemableInPlanks &&
                         cachedAsset.reservedInPlanks == updatedAsset.reservedInPlanks &&
-                        cachedAsset.unbondingInPlanks == updatedAsset.unbondingInPlanks
+                        cachedAsset.unbondingInPlanks == updatedAsset.unbondingInPlanks &&
+                        cachedAsset.tokenPriceId == updatedAsset.tokenPriceId
                     ) {
                         return@withLock
                     }
                     assetDao.updateAsset(updatedAsset)
                 }
             }
-            updatesMixin.finishUpdateAsset(metaId, chainId, accountId, assetId)
         }
+        updatesMixin.finishUpdateAsset(metaId, chainId, accountId, assetId)
     }
 
     suspend fun updateAsset(
@@ -90,18 +98,21 @@ class AssetCache(
         }
     }
 
+    suspend fun updateTokensPrice(
+        update: List<TokenPriceLocal>
+    ) = withContext(Dispatchers.IO) {
+        tokenPriceDao.insertTokensPrice(update)
+    }
+
     suspend fun updateTokenPrice(
         priceId: String,
         builder: (local: TokenPriceLocal) -> TokenPriceLocal
     ) = withContext(Dispatchers.IO) {
-        assetUpdateMutex.withLock {
-            val tokenPriceLocal =
-                tokenPriceDao.getTokenPrice(priceId) ?: TokenPriceLocal.createEmpty(priceId)
+        val tokenPriceLocal = tokenPriceDao.getTokenPrice(priceId) ?: TokenPriceLocal.createEmpty(priceId)
 
-            val newToken = builder.invoke(tokenPriceLocal)
+        val newToken = builder.invoke(tokenPriceLocal)
 
-            tokenPriceDao.insertTokenPrice(newToken)
-        }
+        tokenPriceDao.insertTokenPrice(newToken)
     }
 
     suspend fun updateAsset(updateModel: List<AssetUpdateItem>) {
diff --git a/feature-wallet-api/src/main/java/jp/co/soramitsu/wallet/impl/domain/interfaces/WalletInteractor.kt b/feature-wallet-api/src/main/java/jp/co/soramitsu/wallet/impl/domain/interfaces/WalletInteractor.kt
index 0d33b5778a..59f75fb54a 100644
--- a/feature-wallet-api/src/main/java/jp/co/soramitsu/wallet/impl/domain/interfaces/WalletInteractor.kt
+++ b/feature-wallet-api/src/main/java/jp/co/soramitsu/wallet/impl/domain/interfaces/WalletInteractor.kt
@@ -105,8 +105,6 @@ interface WalletInteractor {
 
     suspend fun getChainAddressForSelectedMetaAccount(chainId: ChainId): String?
 
-    suspend fun updateAssets(newItems: List<AssetUpdateItem>)
-
     suspend fun markAssetAsHidden(chainId: ChainId, chainAssetId: String)
 
     suspend fun markAssetAsShown(chainId: ChainId, chainAssetId: String)
diff --git a/feature-wallet-api/src/main/java/jp/co/soramitsu/wallet/impl/domain/interfaces/WalletRepository.kt b/feature-wallet-api/src/main/java/jp/co/soramitsu/wallet/impl/domain/interfaces/WalletRepository.kt
index cff7198fe0..18c62e8d6f 100644
--- a/feature-wallet-api/src/main/java/jp/co/soramitsu/wallet/impl/domain/interfaces/WalletRepository.kt
+++ b/feature-wallet-api/src/main/java/jp/co/soramitsu/wallet/impl/domain/interfaces/WalletRepository.kt
@@ -95,8 +95,6 @@ interface WalletRepository {
 
     suspend fun getEquilibriumAccountInfo(asset: CoreAsset, accountId: AccountId): EqAccountInfo?
 
-    suspend fun updateAssets(newItems: List<AssetUpdateItem>)
-
     suspend fun getRemoteConfig(): Result<AppConfigRemote>
 
     fun chainRegistrySyncUp()
diff --git a/feature-wallet-api/src/main/java/jp/co/soramitsu/wallet/impl/domain/model/BuyTokenRegistry.kt b/feature-wallet-api/src/main/java/jp/co/soramitsu/wallet/impl/domain/model/BuyTokenRegistry.kt
index e4c539a311..6e42482cfb 100644
--- a/feature-wallet-api/src/main/java/jp/co/soramitsu/wallet/impl/domain/model/BuyTokenRegistry.kt
+++ b/feature-wallet-api/src/main/java/jp/co/soramitsu/wallet/impl/domain/model/BuyTokenRegistry.kt
@@ -15,7 +15,7 @@ class BuyTokenRegistry(val availableProviders: List<Provider<*>>) {
         @get:DrawableRes
         val icon: Int
 
-        fun isTokenSupported(chainAsset: CoreAsset) = name.lowercase() in chainAsset.priceProviders.orEmpty()
+        fun isTokenSupported(chainAsset: CoreAsset) = name.lowercase() in chainAsset.purchaseProviders.orEmpty()
 
         fun createIntegrator(chainAsset: CoreAsset, address: String): I
     }
diff --git a/feature-wallet-impl/build.gradle b/feature-wallet-impl/build.gradle
index 8192ef6605..2d8907d2ee 100644
--- a/feature-wallet-impl/build.gradle
+++ b/feature-wallet-impl/build.gradle
@@ -140,4 +140,6 @@ dependencies {
     implementation sharedFeaturesBackupDep
 
     implementation web3jDep
+    implementation web3jContractsDep
+//    implementation web3jGethDep
 }
\ No newline at end of file
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/blockchain/EthereumRemoteSource.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/blockchain/EthereumRemoteSource.kt
index bc4ed8337a..f77b56dc51 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/blockchain/EthereumRemoteSource.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/blockchain/EthereumRemoteSource.kt
@@ -25,9 +25,13 @@ import kotlinx.coroutines.flow.onStart
 import kotlinx.coroutines.reactive.asFlow
 import kotlinx.coroutines.withContext
 import kotlinx.coroutines.yield
+import org.web3j.abi.DefaultFunctionReturnDecoder
 import org.web3j.abi.FunctionEncoder
+import org.web3j.abi.TypeReference
 import org.web3j.abi.datatypes.Address
 import org.web3j.abi.datatypes.Function
+import org.web3j.abi.datatypes.generated.Int256
+import org.web3j.abi.datatypes.generated.Uint80
 import org.web3j.crypto.Credentials
 import org.web3j.crypto.RawTransaction
 import org.web3j.crypto.TransactionEncoder
@@ -137,6 +141,18 @@ class EthereumRemoteSource(private val ethereumConnectionPool: EthereumConnectio
         return web3.fetchEthBalance(asset, address)
     }
 
+    suspend fun fetchPriceFeed(
+        chainId: ChainId,
+        receiverAddress: String
+    ): BigInteger? {
+        val connection = ethereumConnectionPool.get(chainId)
+        connection?.connect()
+
+        val web3 = connection?.web3j ?: return null
+
+        return web3.fetchPriceFeed(receiverAddress)
+    }
+
     private suspend fun Ethereum.fetchEthBalance(asset: Asset, address: String): BigInteger {
         return if (asset.isUtility) {
             withContext(Dispatchers.IO) {
@@ -167,6 +183,44 @@ class EthereumRemoteSource(private val ethereumConnectionPool: EthereumConnectio
         }
     }
 
+    private suspend fun Ethereum.fetchPriceFeed(address: String): BigInteger? {
+        val outParameters = listOf(
+            Uint80::class.java,
+            Int256::class.java,
+            Int256::class.java,
+            Int256::class.java,
+            Uint80::class.java
+        ).map {
+            TypeReference.create(it)
+        }
+
+        val latestRoundDataFunction = Function(
+            "latestRoundData",
+            emptyList(),
+            outParameters
+        )
+
+        val latestRoundData = withContext(Dispatchers.IO) {
+            kotlin.runCatching {
+                ethCall(
+                    Transaction.createEthCallTransaction(
+                        null,
+                        Address(address).value,
+                        latestRoundDataFunction.encode()
+                    ),
+                    DefaultBlockParameterName.LATEST
+                ).send().value
+            }.getOrNull()
+        }
+
+        val decodeResult = DefaultFunctionReturnDecoder.decode(
+            latestRoundData,
+            latestRoundDataFunction.outputParameters
+        )
+
+        return decodeResult[1].value as? BigInteger
+    }
+
     fun listenGas(transfer: Transfer, chain: Chain): Flow<BigInteger> {
         val connection = requireNotNull(ethereumConnectionPool.get(chain.id))
         val web3j = requireNotNull(connection.web3j)
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/repository/TokenRepositoryImpl.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/repository/TokenRepositoryImpl.kt
index 7b8fcd99d8..b23776dd2f 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/repository/TokenRepositoryImpl.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/repository/TokenRepositoryImpl.kt
@@ -17,13 +17,15 @@ class TokenRepositoryImpl(
 ) : TokenRepository {
 
     override suspend fun getToken(chainAsset: Asset): Token = withContext(Dispatchers.Default) {
-        val tokenPriceLocal = chainAsset.priceId?.let { tokenPriceDao.getTokenPrice(it) ?: TokenPriceLocal.createEmpty(it) }
+        val priceId = chainAsset.priceProvider?.id ?: chainAsset.priceId
+        val tokenPriceLocal = priceId?.let { tokenPriceDao.getTokenPrice(it) ?: TokenPriceLocal.createEmpty(it) }
 
         combineAssetWithPrices(chainAsset, tokenPriceLocal)
     }
 
     override fun observeToken(chainAsset: Asset): Flow<Token> {
-        return when (val priceId = chainAsset.priceId) {
+        val priceId = chainAsset.priceProvider?.id ?: chainAsset.priceId
+        return when (priceId) {
             null -> flowOf {
                 combineAssetWithPrices(chainAsset, null)
             }
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 de96091cc0..4f48e9b46d 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
@@ -20,6 +20,7 @@ import jp.co.soramitsu.common.mixin.api.UpdatesMixin
 import jp.co.soramitsu.common.mixin.api.UpdatesProviderUi
 import jp.co.soramitsu.common.utils.orZero
 import jp.co.soramitsu.common.utils.requireValue
+import jp.co.soramitsu.core.models.Asset.PriceProvider
 import jp.co.soramitsu.core.utils.utilityAsset
 import jp.co.soramitsu.coredb.dao.OperationDao
 import jp.co.soramitsu.coredb.dao.PhishingDao
@@ -28,6 +29,7 @@ import jp.co.soramitsu.coredb.model.AssetUpdateItem
 import jp.co.soramitsu.coredb.model.AssetWithToken
 import jp.co.soramitsu.coredb.model.OperationLocal
 import jp.co.soramitsu.coredb.model.PhishingLocal
+import jp.co.soramitsu.coredb.model.TokenPriceLocal
 import jp.co.soramitsu.runtime.ext.accountIdOf
 import jp.co.soramitsu.runtime.ext.addressOf
 import jp.co.soramitsu.runtime.multiNetwork.ChainRegistry
@@ -151,14 +153,15 @@ class WalletRepositoryImpl(
 
     private fun buildNetworkIssues(items: List<AssetWithStatus>): Set<NetworkIssueItemState> {
         return items.map {
+            val configuration = it.asset.token.configuration
             NetworkIssueItemState(
-                iconUrl = it.asset.token.configuration.iconUrl,
-                title = "${it.asset.token.configuration.chainName} ${it.asset.token.configuration.name}",
+                iconUrl = configuration.iconUrl,
+                title = "${configuration.chainName} ${configuration.name}",
                 type = NetworkIssueType.Node,
-                chainId = it.asset.token.configuration.chainId,
-                chainName = it.asset.token.configuration.chainName,
-                assetId = it.asset.token.configuration.id,
-                priceId = it.asset.token.configuration.priceId
+                chainId = configuration.chainId,
+                chainName = configuration.chainName,
+                assetId = configuration.id,
+                priceId = configuration.priceProvider?.id ?: configuration.priceId
             )
         }.toSet()
     }
@@ -189,13 +192,51 @@ class WalletRepositoryImpl(
 
     override suspend fun syncAssetsRates(currencyId: String) {
         val chains = chainsRepository.getChains()
+        if (currencyId == "usd") {
+            syncChainlinkRates(chains)
+        }
+        syncCoingeckoRates(chains, currencyId)
+    }
+
+    private suspend fun syncChainlinkRates(chains: List<Chain>) {
+        val chainlinkIds = chains.map { it.assets.mapNotNull { it.priceProvider?.id } }.flatten().toSet()
+
+        val chainlinkProvider = chains.firstOrNull { it.chainlinkProvider }
+        val chainlinkProviderId = chainlinkProvider?.id
+        println("!!! chainlinkProvider is ${chainlinkProvider?.name} $chainlinkProviderId ")
+
+        val chainlinkTokens = chainlinkIds.map { priceId ->
+            val assetConfig = chains.flatMap { it.assets }.firstOrNull { it.priceProvider?.id == priceId }
+            val priceProvider = assetConfig?.priceProvider
+
+            val price = if (chainlinkProviderId != null && priceProvider != null) {
+                getChainlinkPrices(priceProvider = priceProvider, chainId = chainlinkProviderId)
+            } else {
+                null
+            }
+            val usdCurrency = availableFiatCurrencies["usd"]
+
+            TokenPriceLocal(
+                priceId = priceId,
+                fiatRate = price,
+                fiatSymbol = usdCurrency?.symbol,
+                recentRateChange = null
+            )
+        }
+
+        updatesMixin.startUpdateTokens(chainlinkIds)
+        updateAssetsRates(chainlinkTokens)
+        updatesMixin.finishUpdateTokens(chainlinkIds)
+    }
+
+    private suspend fun syncCoingeckoRates(chains: List<Chain>, currencyId: String) {
         val priceIds = chains.map { it.assets.mapNotNull { it.priceId } }.flatten().toSet()
-        val priceStats = getAssetPriceCoingecko(*priceIds.toTypedArray(), currencyId = currencyId)
+        val coingeckoPriceStats = getAssetPriceCoingecko(*priceIds.toTypedArray(), currencyId = currencyId)
 
         updatesMixin.startUpdateTokens(priceIds)
 
         priceIds.forEach { priceId ->
-            val stat = priceStats[priceId] ?: return@forEach
+            val stat = coingeckoPriceStats[priceId] ?: return@forEach
             val price = stat[currencyId]
             val changeKey = "${currencyId}_24h_change"
             val change = stat[changeKey]
@@ -206,6 +247,15 @@ class WalletRepositoryImpl(
         updatesMixin.finishUpdateTokens(priceIds)
     }
 
+    private suspend fun getChainlinkPrices(priceProvider: PriceProvider, chainId: ChainId): BigDecimal? {
+        return ethereumSource.fetchPriceFeed(
+            chainId = chainId,
+            receiverAddress = priceProvider.id
+        )?.let { price ->
+            BigDecimal(price, priceProvider.precision)
+        }
+    }
+
     override fun assetFlow(
         metaId: Long,
         accountId: AccountId,
@@ -243,7 +293,7 @@ class WalletRepositoryImpl(
                 id = chainAsset.id,
                 sortIndex = Int.MAX_VALUE, // Int.MAX_VALUE on sorting because we don't use it anymore - just random value
                 enabled = !isHidden,
-                tokenPriceId = chainAsset.priceId
+                tokenPriceId = chainAsset.priceProvider?.id ?: chainAsset.priceId
             )
         )
 
@@ -441,10 +491,6 @@ class WalletRepositoryImpl(
     override suspend fun getEquilibriumAccountInfo(asset: CoreAsset, accountId: AccountId) =
         substrateSource.getEquilibriumAccountInfo(asset, accountId)
 
-    override suspend fun updateAssets(newItems: List<AssetUpdateItem>) {
-        assetCache.updateAsset(newItems)
-    }
-
     private fun createOperation(
         hash: String,
         transfer: Transfer,
@@ -479,6 +525,10 @@ class WalletRepositoryImpl(
         )
     }
 
+    private suspend fun updateAssetsRates(
+        items: List<TokenPriceLocal>
+    ) = assetCache.updateTokensPrice(items)
+
     override suspend fun getSingleAssetPriceCoingecko(
         priceId: String,
         currency: String
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 9ba651da32..0493cfb4a9 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
@@ -113,9 +113,10 @@ class WalletFeatureModule {
         tokenPriceDao: TokenPriceDao,
         assetDao: AssetDao,
         accountRepository: AccountRepository,
-        updatesMixin: UpdatesMixin
+        updatesMixin: UpdatesMixin,
+        selectedFiat: SelectedFiat
     ): AssetCache {
-        return AssetCache(tokenPriceDao, accountRepository, assetDao, updatesMixin)
+        return AssetCache(tokenPriceDao, accountRepository, assetDao, updatesMixin, selectedFiat)
     }
 
     @Provides
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/domain/ChainInteractor.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/domain/ChainInteractor.kt
index 556e309cf3..3f8f3921e5 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/domain/ChainInteractor.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/domain/ChainInteractor.kt
@@ -6,6 +6,7 @@ import jp.co.soramitsu.core.models.ChainAssetType
 import jp.co.soramitsu.core.models.ChainId
 import jp.co.soramitsu.coredb.dao.ChainDao
 import jp.co.soramitsu.runtime.multiNetwork.chain.mapChainLocalToChain
+import jp.co.soramitsu.runtime.multiNetwork.chain.mapToPriceProvider
 import jp.co.soramitsu.runtime.multiNetwork.chain.model.Chain
 import jp.co.soramitsu.runtime.multiNetwork.chain.model.polkadotChainId
 import jp.co.soramitsu.wallet.api.domain.model.XcmChainType
@@ -37,7 +38,7 @@ class ChainInteractor(
                     priceId = it.priceId,
                     precision = it.precision,
                     staking = Asset.StakingType.UNSUPPORTED,
-                    priceProviders = emptyList(),
+                    purchaseProviders = emptyList(),
                     chainName = "",
                     chainIcon = it.icon,
                     isTestNet = false,
@@ -47,7 +48,8 @@ class ChainInteractor(
                     currencyId = it.currencyId,
                     existentialDeposit = it.existentialDeposit,
                     color = it.color,
-                    isNative = it.isNative
+                    isNative = it.isNative,
+                    priceProvider = mapToPriceProvider(it.priceProvider)
                 )
             }
         }
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 9969afd203..a3e37f2840 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
@@ -413,10 +413,6 @@ class WalletInteractorImpl(
         }
     }
 
-    override suspend fun updateAssets(newItems: List<AssetUpdateItem>) {
-        walletRepository.updateAssets(newItems)
-    }
-
     private fun mapAccountToWalletAccount(chain: Chain, account: MetaAccount) = with(account) {
         WalletAccount(account.address(chain)!!, name)
     }
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 a2940ff0e2..2987bf8b50 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
@@ -273,7 +273,7 @@ class BalanceListViewModel @Inject constructor(
                     chainAssetId = chainAsset.id,
                     isSupported = true,
                     isHidden = false,
-                    priceId = chainAsset.priceId,
+                    priceId = chainAsset.priceProvider?.id ?: chainAsset.priceId,
                     isTestnet = chainAsset.isTestNet ?: false
                 )
             }.filter { selectedChainId.value == null || selectedChainId.value == it.chainId }
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/list/model/BalanceListItemModel.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/list/model/BalanceListItemModel.kt
index 156c598727..633836a960 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/list/model/BalanceListItemModel.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/list/model/BalanceListItemModel.kt
@@ -36,6 +36,6 @@ fun BalanceListItemModel.toAssetState(index: Int? = null) = AssetListItemViewSta
     chainAssetId = asset.id,
     isSupported = chain?.isSupported != false,
     isHidden = isHidden,
-    priceId = asset.priceId,
+    priceId = asset.priceProvider?.id ?: asset.priceId,
     isTestnet = chain?.isTestNet == true
 )
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index e186b8eb5b..6e08840bf7 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -16,7 +16,7 @@ detekt = "1.23.0"
 kotlin = "1.8.10"
 dagger = "2.47"
 android_plugin = "7.4.2"
-sharedFeaturesVersion = "1.1.1.20-FLW"
+sharedFeaturesVersion = "1.1.1.22-FLW"
 web3j = "4.8.8-android"
 walletconnectBom = "1.18.0"
 coilVersion = "2.2.2"
diff --git a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/ChainRegistry.kt b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/ChainRegistry.kt
index 7c1efda9c9..bdc62e31d6 100644
--- a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/ChainRegistry.kt
+++ b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/ChainRegistry.kt
@@ -267,6 +267,6 @@ fun Chain.toSyncIssue(): NetworkIssueItemState {
         chainId = this.id,
         chainName = this.name,
         assetId = this.utilityAsset?.id.orEmpty(),
-        priceId = this.utilityAsset?.priceId
+        priceId = this.utilityAsset?.priceProvider?.id ?: this.utilityAsset?.priceId
     )
 }
diff --git a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/Mappers.kt b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/Mappers.kt
index 9bc190bc94..3a45f66853 100644
--- a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/Mappers.kt
+++ b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/Mappers.kt
@@ -5,6 +5,7 @@ import com.google.gson.reflect.TypeToken
 import jp.co.soramitsu.core.models.Asset
 import jp.co.soramitsu.core.models.ChainAssetType
 import jp.co.soramitsu.core.models.ChainNode
+import jp.co.soramitsu.core.runtime.mappers.mapRemoteToModel
 import jp.co.soramitsu.coredb.model.chain.ChainAssetLocal
 import jp.co.soramitsu.coredb.model.chain.ChainExplorerLocal
 import jp.co.soramitsu.coredb.model.chain.ChainLocal
@@ -16,6 +17,7 @@ import jp.co.soramitsu.runtime.multiNetwork.chain.remote.model.ChainRemote
 
 private const val ETHEREUM_BASED_OPTION = "ethereumBased"
 private const val ETHEREUM_OPTION = "ethereum"
+private const val CHAINLINK_PROVIDER_OPTION = "chainlinkProvider"
 private const val CROWDLOAN_OPTION = "crowdloans"
 private const val TESTNET_OPTION = "testnet"
 private const val NOMINATION_POOL_OPTION = "poolStaking"
@@ -146,6 +148,7 @@ fun ChainRemote.toChain(): Chain {
         hasCrowdloans = CROWDLOAN_OPTION in optionsOrEmpty,
         supportStakingPool = NOMINATION_POOL_OPTION in optionsOrEmpty,
         isEthereumChain = ETHEREUM_OPTION in optionsOrEmpty,
+        chainlinkProvider = CHAINLINK_PROVIDER_OPTION in optionsOrEmpty,
         paraId = this.paraId
     )
 }
@@ -166,7 +169,7 @@ private fun ChainRemote.assetConfigs(): List<Asset>? {
                     priceId = chainAsset.priceId,
                     precision = chainAsset.precision ?: DEFAULT_PRECISION,
                     staking = mapStakingStringToStakingType(chainAsset.staking),
-                    priceProviders = chainAsset.purchaseProviders,
+                    purchaseProviders = chainAsset.purchaseProviders,
                     supportStakingPool = NOMINATION_POOL_OPTION in this.options.orEmpty(),
                     isUtility = chainAsset.isUtility ?: false,
                     type = ChainAssetType.from(chainAsset.type),
@@ -174,7 +177,8 @@ private fun ChainRemote.assetConfigs(): List<Asset>? {
                     existentialDeposit = chainAsset.existentialDeposit,
                     color = chainAsset.color,
                     isNative = chainAsset.isNative,
-                    ethereumType = mapEthereumTypeStringToEthereumType(chainAsset.ethereumType)
+                    ethereumType = mapEthereumTypeStringToEthereumType(chainAsset.ethereumType),
+                    priceProvider = chainAsset.priceProvider?.mapRemoteToModel()
                 )
             }
         }.getOrNull()
@@ -201,7 +205,7 @@ fun mapChainLocalToChain(chainLocal: JoinedChainInfo): Chain {
             priceId = it.priceId,
             precision = it.precision,
             staking = mapStakingTypeFromLocal(it.staking),
-            priceProviders = mapToList(it.priceProviders),
+            purchaseProviders = mapToList(it.purchaseProviders),
             chainName = chainLocal.chain.name,
             chainIcon = chainLocal.chain.icon,
             isTestNet = chainLocal.chain.isTestNet,
@@ -212,7 +216,8 @@ fun mapChainLocalToChain(chainLocal: JoinedChainInfo): Chain {
             existentialDeposit = it.existentialDeposit,
             color = it.color,
             isNative = it.isNative,
-            ethereumType = mapEthereumTypeStringToEthereumType(it.ethereumType)
+            ethereumType = mapEthereumTypeStringToEthereumType(it.ethereumType),
+            priceProvider = mapToPriceProvider(it.priceProvider)
         )
     }
 
@@ -250,7 +255,8 @@ fun mapChainLocalToChain(chainLocal: JoinedChainInfo): Chain {
             hasCrowdloans = hasCrowdloans,
             supportStakingPool = supportStakingPool,
             isEthereumChain = isEthereumChain,
-            paraId = paraId
+            paraId = paraId,
+            chainlinkProvider = isChainlinkProvider
         )
     }
 }
@@ -276,14 +282,15 @@ fun mapChainToChainLocal(chain: Chain): JoinedChainInfo {
             chainId = chain.id,
             priceId = it.priceId,
             staking = mapStakingTypeToLocal(it.staking),
-            priceProviders = it.priceProviders?.let { Gson().toJson(it) },
+            purchaseProviders = it.purchaseProviders?.let { Gson().toJson(it) },
             isUtility = it.isUtility,
             type = it.type?.name,
             currencyId = it.currencyId,
             existentialDeposit = it.existentialDeposit,
             color = it.color,
             isNative = it.isNative,
-            ethereumType = mapEthereumTypeToLocal(it.ethereumType)
+            ethereumType = mapEthereumTypeToLocal(it.ethereumType),
+            priceProvider = it.priceProvider?.let { Gson().toJson(it) }
         )
     }
 
@@ -319,7 +326,8 @@ fun mapChainToChainLocal(chain: Chain): JoinedChainInfo {
             hasCrowdloans = hasCrowdloans,
             supportStakingPool = supportStakingPool,
             isEthereumChain = isEthereumChain,
-            paraId = paraId
+            paraId = paraId,
+            isChainlinkProvider = chainlinkProvider
         )
     }
 
@@ -333,3 +341,6 @@ fun mapChainToChainLocal(chain: Chain): JoinedChainInfo {
 
 private fun mapToList(json: String?) =
     json?.let { Gson().fromJson<List<String>>(it, object : TypeToken<List<String>>() {}.type) }
+
+fun mapToPriceProvider(json: String?) =
+    json?.let { Gson().fromJson<Asset.PriceProvider>(it, object : TypeToken<Asset.PriceProvider>() {}.type) }
\ No newline at end of file
diff --git a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/model/Chain.kt b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/model/Chain.kt
index 6f97706acb..2525a91b85 100644
--- a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/model/Chain.kt
+++ b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/model/Chain.kt
@@ -49,7 +49,8 @@ data class Chain(
     val hasCrowdloans: Boolean,
     override val parentId: String?,
     val supportStakingPool: Boolean,
-    val isEthereumChain: Boolean
+    val isEthereumChain: Boolean,
+    val chainlinkProvider: Boolean,
 ) : IChain {
     val assetsById = assets.associateBy(CoreAsset::id)
 
@@ -85,6 +86,7 @@ data class Chain(
         other as Chain
 
         if (id != other.id) return false
+        if (paraId != other.paraId) return false
         if (rank != other.rank) return false
         if (name != other.name) return false
         if (minSupportedVersion != other.minSupportedVersion) return false
@@ -97,6 +99,9 @@ data class Chain(
         if (isTestNet != other.isTestNet) return false
         if (hasCrowdloans != other.hasCrowdloans) return false
         if (parentId != other.parentId) return false
+        if (supportStakingPool != other.supportStakingPool) return false
+        if (isEthereumChain != other.isEthereumChain) return false
+        if (chainlinkProvider != other.chainlinkProvider) return false
 
         // custom comparison logic
         val defaultNodes = nodes.filter { it.isDefault }
@@ -111,6 +116,7 @@ data class Chain(
 
     override fun hashCode(): Int {
         var result = id.hashCode()
+        result = 31 * result + (paraId?.hashCode() ?: 0)
         result = 31 * result + (rank?.hashCode() ?: 0)
         result = 31 * result + name.hashCode()
         result = 31 * result + (minSupportedVersion?.hashCode() ?: 0)
@@ -124,6 +130,9 @@ data class Chain(
         result = 31 * result + isTestNet.hashCode()
         result = 31 * result + hasCrowdloans.hashCode()
         result = 31 * result + (parentId?.hashCode() ?: 0)
+        result = 31 * result + supportStakingPool.hashCode()
+        result = 31 * result + isEthereumChain.hashCode()
+        result = 31 * result + chainlinkProvider.hashCode()
         return result
     }
 }
diff --git a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/remote/model/ChainAssetRemote.kt b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/remote/model/ChainAssetRemote.kt
index 8b8bef0b83..04942ed29e 100644
--- a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/remote/model/ChainAssetRemote.kt
+++ b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/remote/model/ChainAssetRemote.kt
@@ -1,5 +1,7 @@
 package jp.co.soramitsu.runtime.multiNetwork.chain.remote.model
 
+import jp.co.soramitsu.core.models.remote.PriceProvider
+
 class ChainAssetRemote(
     val id: String?,
     val name: String?,
@@ -15,5 +17,6 @@ class ChainAssetRemote(
     val staking: String?,
     val purchaseProviders: List<String>?,
     val type: String?,
-    val ethereumType: String?
+    val ethereumType: String?,
+    val priceProvider: PriceProvider?
 )
diff --git a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/connection/ConnectionPool.kt b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/connection/ConnectionPool.kt
index f072056b39..fe122221f2 100644
--- a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/connection/ConnectionPool.kt
+++ b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/connection/ConnectionPool.kt
@@ -71,7 +71,7 @@ class ConnectionPool @Inject constructor(
                         chainId = chain.id,
                         chainName = chain.name,
                         assetId = chain.utilityAsset?.id.orEmpty(),
-                        priceId = chain.utilityAsset?.priceId
+                        priceId = chain.utilityAsset?.priceProvider?.id ?: chain.utilityAsset?.priceId
                     )
                 }
             issues
diff --git a/runtime/src/test/java/jp/co/soramitsu/runtime/multiNetwork/chain/ChainSyncServiceTest.kt b/runtime/src/test/java/jp/co/soramitsu/runtime/multiNetwork/chain/ChainSyncServiceTest.kt
index e22b8558a5..0fdbd7427e 100644
--- a/runtime/src/test/java/jp/co/soramitsu/runtime/multiNetwork/chain/ChainSyncServiceTest.kt
+++ b/runtime/src/test/java/jp/co/soramitsu/runtime/multiNetwork/chain/ChainSyncServiceTest.kt
@@ -41,7 +41,8 @@ class ChainSyncServiceTest {
                 existentialDeposit = null,
                 color = null,
                 isNative = null,
-                ethereumType = null
+                ethereumType = null,
+                priceProvider = null
             )
         ),
         nodes = listOf(

From 94925f89c3e52d8e8f0393cd819c067bee55756a Mon Sep 17 00:00:00 2001
From: Sergey Pankratov <pankratov@soramitsu.co.jp>
Date: Tue, 6 Feb 2024 22:47:41 +0500
Subject: [PATCH 07/35] chainlink, usd only check

---
 app/build.gradle                              |  1 -
 .../app/root/navigation/Navigator.kt          |  4 +-
 build.gradle                                  |  2 -
 .../common/compose/component/AssetListItem.kt |  1 -
 .../compose/component/NetworkIssueItem.kt     |  3 +-
 .../common/compose/component/SwipeBox.kt      |  1 -
 .../viewstate/AssetListItemViewState.kt       |  1 -
 .../soramitsu/common/domain/SelectedFiat.kt   |  1 +
 .../actions/AddAccountBottomSheet.kt          | 49 -------------------
 .../presentation/actions/AddAccountPayload.kt | 14 ++++++
 .../account/impl/di/AccountFeatureModule.kt   |  5 +-
 .../domain/AssetNotNeedAccountUseCaseImpl.kt  |  7 ++-
 .../impl/presentation/AccountRouter.kt        |  4 +-
 .../details/AccountDetailsViewModel.kt        |  6 +--
 .../OptionsAddAccountContent.kt               |  6 +--
 .../OptionsAddAccountFragment.kt              |  4 +-
 .../OptionsAddAccountViewModel.kt             | 10 ++--
 .../staking/impl/di/StakingFeatureModule.kt   |  5 +-
 .../rewards/SoraStakingRewardsScenario.kt     |  9 ++--
 .../wallet/api/data/cache/AssetCache.kt       |  2 +-
 feature-wallet-impl/build.gradle              |  2 -
 .../data/repository/TokenRepositoryImpl.kt    | 30 +++++++++---
 .../data/repository/WalletRepositoryImpl.kt   | 11 +++--
 .../wallet/impl/di/WalletFeatureModule.kt     | 12 +++--
 .../wallet/impl/presentation/WalletRouter.kt  |  4 +-
 .../balance/list/BalanceListViewModel.kt      |  1 -
 .../presentation/balance/list/WalletScreen.kt |  1 -
 .../list/model/BalanceListItemModel.kt        |  1 -
 .../networkissues/NetworkIssuesViewModel.kt   |  6 +--
 .../runtime/multiNetwork/ChainRegistry.kt     |  3 +-
 .../multiNetwork/connection/ConnectionPool.kt |  3 +-
 31 files changed, 91 insertions(+), 118 deletions(-)
 delete mode 100644 feature-account-api/src/main/java/jp/co/soramitsu/account/api/presentation/actions/AddAccountBottomSheet.kt
 create mode 100644 feature-account-api/src/main/java/jp/co/soramitsu/account/api/presentation/actions/AddAccountPayload.kt

diff --git a/app/build.gradle b/app/build.gradle
index 583bd8f5c7..9fde9d42a9 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -196,7 +196,6 @@ dependencies {
 
     implementation lifeCycleKtxDep
 
-//    implementation retrofitDep
     implementation gsonConvertedDep
 
     implementation gifDep
diff --git a/app/src/main/java/jp/co/soramitsu/app/root/navigation/Navigator.kt b/app/src/main/java/jp/co/soramitsu/app/root/navigation/Navigator.kt
index 030143d015..5e27d07cd3 100644
--- a/app/src/main/java/jp/co/soramitsu/app/root/navigation/Navigator.kt
+++ b/app/src/main/java/jp/co/soramitsu/app/root/navigation/Navigator.kt
@@ -19,7 +19,7 @@ import it.airgap.beaconsdk.blockchain.substrate.data.SubstrateSignerPayload
 import java.math.BigDecimal
 import jp.co.soramitsu.account.api.domain.model.ImportMode
 import jp.co.soramitsu.account.api.presentation.account.create.ChainAccountCreatePayload
-import jp.co.soramitsu.account.api.presentation.actions.AddAccountBottomSheet
+import jp.co.soramitsu.account.api.presentation.actions.AddAccountPayload
 import jp.co.soramitsu.account.api.presentation.create_backup_password.CreateBackupPasswordPayload
 import jp.co.soramitsu.account.impl.domain.account.details.AccountInChain
 import jp.co.soramitsu.account.impl.presentation.AccountRouter
@@ -1279,7 +1279,7 @@ class Navigator :
         navController?.navigate(R.id.networkIssuesFragment)
     }
 
-    override fun openOptionsAddAccount(payload: AddAccountBottomSheet.Payload) {
+    override fun openOptionsAddAccount(payload: AddAccountPayload) {
         val bundle = OptionsAddAccountFragment.getBundle(payload)
         navController?.navigate(R.id.optionsAddAccountFragment, bundle)
     }
diff --git a/build.gradle b/build.gradle
index ddda60abe4..1278b446c0 100644
--- a/build.gradle
+++ b/build.gradle
@@ -207,8 +207,6 @@ buildscript {
         sharedFeaturesBackupDep = "jp.co.soramitsu.shared_features:backup:$sharedFeaturesVersion"
 
         web3jDep = "org.web3j:core:4.8.8-android"
-        web3jContractsDep = "org.web3j:contracts:4.8.8-android"
-        web3jGethDep = "org.web3j:geth:4.8.8-android"
 
         withoutJavaWS = { exclude module: 'java-websocket-lib' }
 
diff --git a/common/src/main/java/jp/co/soramitsu/common/compose/component/AssetListItem.kt b/common/src/main/java/jp/co/soramitsu/common/compose/component/AssetListItem.kt
index 38cfb96bfa..e71d7986bf 100644
--- a/common/src/main/java/jp/co/soramitsu/common/compose/component/AssetListItem.kt
+++ b/common/src/main/java/jp/co/soramitsu/common/compose/component/AssetListItem.kt
@@ -351,7 +351,6 @@ private fun PreviewAssetListItem() {
         chainAssetId = "",
         isSupported = true,
         isHidden = false,
-        priceId = null,
         isTestnet = false
     )
     FearlessAppTheme {
diff --git a/common/src/main/java/jp/co/soramitsu/common/compose/component/NetworkIssueItem.kt b/common/src/main/java/jp/co/soramitsu/common/compose/component/NetworkIssueItem.kt
index 19c3bbc376..1f7f949e80 100644
--- a/common/src/main/java/jp/co/soramitsu/common/compose/component/NetworkIssueItem.kt
+++ b/common/src/main/java/jp/co/soramitsu/common/compose/component/NetworkIssueItem.kt
@@ -58,8 +58,7 @@ data class NetworkIssueItemState(
 
     val chainId: String,
     val chainName: String,
-    val assetId: String,
-    val priceId: String? = null
+    val assetId: String
 ) {
     override fun equals(other: Any?): Boolean {
         if (this === other) return true
diff --git a/common/src/main/java/jp/co/soramitsu/common/compose/component/SwipeBox.kt b/common/src/main/java/jp/co/soramitsu/common/compose/component/SwipeBox.kt
index 22c1d066cd..58258f02d8 100644
--- a/common/src/main/java/jp/co/soramitsu/common/compose/component/SwipeBox.kt
+++ b/common/src/main/java/jp/co/soramitsu/common/compose/component/SwipeBox.kt
@@ -175,7 +175,6 @@ private fun AssetItemSwipeBoxPreview() {
         chainAssetId = "",
         isSupported = true,
         isHidden = false,
-        priceId = null,
         isTestnet = false
     )
 
diff --git a/common/src/main/java/jp/co/soramitsu/common/compose/viewstate/AssetListItemViewState.kt b/common/src/main/java/jp/co/soramitsu/common/compose/viewstate/AssetListItemViewState.kt
index 76b549d632..f1ee3f5c66 100644
--- a/common/src/main/java/jp/co/soramitsu/common/compose/viewstate/AssetListItemViewState.kt
+++ b/common/src/main/java/jp/co/soramitsu/common/compose/viewstate/AssetListItemViewState.kt
@@ -15,7 +15,6 @@ data class AssetListItemViewState(
     val chainAssetId: String,
     val isSupported: Boolean,
     val isHidden: Boolean,
-    val priceId: String?,
     val isTestnet: Boolean
 ) {
     val key = listOf(index ?: 0, chainAssetId, chainId, isHidden).joinToString()
diff --git a/common/src/main/java/jp/co/soramitsu/common/domain/SelectedFiat.kt b/common/src/main/java/jp/co/soramitsu/common/domain/SelectedFiat.kt
index 75d870673c..55baf11ec3 100644
--- a/common/src/main/java/jp/co/soramitsu/common/domain/SelectedFiat.kt
+++ b/common/src/main/java/jp/co/soramitsu/common/domain/SelectedFiat.kt
@@ -9,6 +9,7 @@ private const val DEFAULT_SELECTED_FIAT = "usd"
 class SelectedFiat(private val preferences: Preferences) {
     fun flow() = preferences.stringFlow(SELECTED_FIAT_KEY) { get() }.filterNotNull()
     fun get() = preferences.getString(SELECTED_FIAT_KEY, DEFAULT_SELECTED_FIAT)
+    fun isUsd() = get() == DEFAULT_SELECTED_FIAT
 
     fun set(value: String) {
         preferences.putString(SELECTED_FIAT_KEY, value)
diff --git a/feature-account-api/src/main/java/jp/co/soramitsu/account/api/presentation/actions/AddAccountBottomSheet.kt b/feature-account-api/src/main/java/jp/co/soramitsu/account/api/presentation/actions/AddAccountBottomSheet.kt
deleted file mode 100644
index c76b4172aa..0000000000
--- a/feature-account-api/src/main/java/jp/co/soramitsu/account/api/presentation/actions/AddAccountBottomSheet.kt
+++ /dev/null
@@ -1,49 +0,0 @@
-package jp.co.soramitsu.account.api.presentation.actions
-
-import android.content.Context
-import android.os.Bundle
-import android.os.Parcelable
-import jp.co.soramitsu.common.R
-import jp.co.soramitsu.common.view.bottomSheet.list.fixed.FixedListBottomSheet
-import jp.co.soramitsu.common.view.bottomSheet.list.fixed.textItem
-import jp.co.soramitsu.runtime.multiNetwork.chain.model.ChainId
-import kotlinx.parcelize.Parcelize
-
-class AddAccountBottomSheet(
-    context: Context,
-    private val payload: Payload,
-    private val onCreate: (chainId: ChainId, metaId: Long) -> Unit,
-    private val onImport: (chainId: ChainId, metaId: Long) -> Unit,
-    private val onNoNeed: (chainId: ChainId, metaId: Long, assetId: String, priceId: String?) -> Unit
-) : FixedListBottomSheet(context) {
-
-    @Parcelize
-    data class Payload(
-        val metaId: Long,
-        val chainId: ChainId,
-        val chainName: String,
-        val assetId: String,
-        val priceId: String?,
-        val markedAsNotNeed: Boolean
-    ) : Parcelable
-
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-
-        setTitle(context.getString(R.string.account_template, payload.chainName))
-
-        textItem(R.string.create_new_account) {
-            onCreate(payload.chainId, payload.metaId)
-        }
-
-        textItem(R.string.already_have_account) {
-            onImport(payload.chainId, payload.metaId)
-        }
-
-        if (!payload.markedAsNotNeed) {
-            textItem(R.string.i_dont_need_account) {
-                onNoNeed(payload.chainId, payload.metaId, payload.assetId, payload.priceId)
-            }
-        }
-    }
-}
diff --git a/feature-account-api/src/main/java/jp/co/soramitsu/account/api/presentation/actions/AddAccountPayload.kt b/feature-account-api/src/main/java/jp/co/soramitsu/account/api/presentation/actions/AddAccountPayload.kt
new file mode 100644
index 0000000000..e36903340f
--- /dev/null
+++ b/feature-account-api/src/main/java/jp/co/soramitsu/account/api/presentation/actions/AddAccountPayload.kt
@@ -0,0 +1,14 @@
+package jp.co.soramitsu.account.api.presentation.actions
+
+import android.os.Parcelable
+import jp.co.soramitsu.runtime.multiNetwork.chain.model.ChainId
+import kotlinx.parcelize.Parcelize
+
+@Parcelize
+data class AddAccountPayload(
+    val metaId: Long,
+    val chainId: ChainId,
+    val chainName: String,
+    val assetId: String,
+    val markedAsNotNeed: Boolean
+) : Parcelable
\ No newline at end of file
diff --git a/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/di/AccountFeatureModule.kt b/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/di/AccountFeatureModule.kt
index 68de31b86c..330e80ab2d 100644
--- a/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/di/AccountFeatureModule.kt
+++ b/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/di/AccountFeatureModule.kt
@@ -203,9 +203,10 @@ class AccountFeatureModule {
     fun provideAssetNotNeedAccountUseCase(
         chainRegistry: ChainRegistry,
         assetDao: AssetDao,
-        tokenPriceDao: TokenPriceDao
+        tokenPriceDao: TokenPriceDao,
+        selectedFiat: SelectedFiat
     ): AssetNotNeedAccountUseCase {
-        return AssetNotNeedAccountUseCaseImpl(chainRegistry, assetDao, tokenPriceDao)
+        return AssetNotNeedAccountUseCaseImpl(chainRegistry, assetDao, tokenPriceDao, selectedFiat)
     }
 
     @Provides
diff --git a/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/domain/AssetNotNeedAccountUseCaseImpl.kt b/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/domain/AssetNotNeedAccountUseCaseImpl.kt
index fb9cb2bf0c..eec8285647 100644
--- a/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/domain/AssetNotNeedAccountUseCaseImpl.kt
+++ b/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/domain/AssetNotNeedAccountUseCaseImpl.kt
@@ -1,6 +1,7 @@
 package jp.co.soramitsu.account.impl.domain
 
 import jp.co.soramitsu.account.api.domain.interfaces.AssetNotNeedAccountUseCase
+import jp.co.soramitsu.common.domain.SelectedFiat
 import jp.co.soramitsu.common.model.AssetKey
 import jp.co.soramitsu.coredb.dao.AssetDao
 import jp.co.soramitsu.coredb.dao.TokenPriceDao
@@ -14,13 +15,15 @@ import kotlinx.coroutines.flow.map
 class AssetNotNeedAccountUseCaseImpl(
     private val chainRegistry: ChainRegistry,
     private val assetDao: AssetDao,
-    private val tokenPriceDao: TokenPriceDao
+    private val tokenPriceDao: TokenPriceDao,
+    private val selectedFiat: SelectedFiat
 ) : AssetNotNeedAccountUseCase {
 
     override suspend fun markChainAssetsNotNeed(chainId: ChainId, metaId: Long) {
         val chainAssets = chainRegistry.getChain(chainId).assets
         chainAssets.forEach {
-            updateAssetNotNeed(metaId, chainId, it.id, it.priceProvider?.id ?: it.priceId)
+            val priceId = it.priceProvider?.id?.takeIf { selectedFiat.isUsd() } ?: it.priceId
+            updateAssetNotNeed(metaId, chainId, it.id, priceId)
         }
     }
 
diff --git a/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/presentation/AccountRouter.kt b/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/presentation/AccountRouter.kt
index 9b46754208..79f28b8e8d 100644
--- a/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/presentation/AccountRouter.kt
+++ b/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/presentation/AccountRouter.kt
@@ -1,7 +1,7 @@
 package jp.co.soramitsu.account.impl.presentation
 
 import jp.co.soramitsu.account.api.presentation.account.create.ChainAccountCreatePayload
-import jp.co.soramitsu.account.api.presentation.actions.AddAccountBottomSheet
+import jp.co.soramitsu.account.api.presentation.actions.AddAccountPayload
 import jp.co.soramitsu.account.api.presentation.create_backup_password.CreateBackupPasswordPayload
 import jp.co.soramitsu.account.impl.domain.account.details.AccountInChain
 import jp.co.soramitsu.account.impl.presentation.exporting.json.confirm.ExportJsonConfirmPayload
@@ -85,7 +85,7 @@ interface AccountRouter : SecureRouter {
 
     fun openExperimentalFeatures()
 
-    fun openOptionsAddAccount(payload: AddAccountBottomSheet.Payload)
+    fun openOptionsAddAccount(payload: AddAccountPayload)
 
     fun openPolkaswapDisclaimerFromProfile()
 
diff --git a/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/presentation/account/details/AccountDetailsViewModel.kt b/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/presentation/account/details/AccountDetailsViewModel.kt
index 0ba2c7e5a7..d48ced6e4e 100644
--- a/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/presentation/account/details/AccountDetailsViewModel.kt
+++ b/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/presentation/account/details/AccountDetailsViewModel.kt
@@ -9,7 +9,7 @@ import javax.inject.Inject
 import jp.co.soramitsu.account.api.domain.interfaces.AssetNotNeedAccountUseCase
 import jp.co.soramitsu.account.api.domain.interfaces.TotalBalanceUseCase
 import jp.co.soramitsu.account.api.domain.model.hasChainAccount
-import jp.co.soramitsu.account.api.presentation.actions.AddAccountBottomSheet
+import jp.co.soramitsu.account.api.presentation.actions.AddAccountPayload
 import jp.co.soramitsu.account.api.presentation.actions.ExternalAccountActions
 import jp.co.soramitsu.account.api.presentation.exporting.ExportSource
 import jp.co.soramitsu.account.api.presentation.exporting.ExportSourceChooserPayload
@@ -23,6 +23,7 @@ import jp.co.soramitsu.common.base.BaseViewModel
 import jp.co.soramitsu.common.compose.component.ChangeBalanceViewState
 import jp.co.soramitsu.common.compose.component.WalletItemViewState
 import jp.co.soramitsu.common.data.network.BlockExplorerUrlBuilder
+import jp.co.soramitsu.common.domain.SelectedFiat
 import jp.co.soramitsu.common.list.headers.TextHeader
 import jp.co.soramitsu.common.list.toListWithHeaders
 import jp.co.soramitsu.common.resources.ResourceManager
@@ -251,12 +252,11 @@ class AccountDetailsViewModel @Inject constructor(
                 externalAccountActions.showExternalActions(ExternalAccountActions.Payload(item.address, item.chainId, item.chainName, supportedExplorers))
             } else {
                 val utilityAsset = chainRegistry.getChain(item.chainId).utilityAsset
-                val payload = AddAccountBottomSheet.Payload(
+                val payload = AddAccountPayload(
                     metaId = walletId,
                     chainId = item.chainId,
                     chainName = item.chainName,
                     assetId = utilityAsset?.id.orEmpty(),
-                    priceId = utilityAsset?.priceProvider?.id ?: utilityAsset?.priceId,
                     markedAsNotNeed = item.markedAsNotNeed
                 )
                 accountRouter.openOptionsAddAccount(payload)
diff --git a/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/presentation/optionsaddaccount/OptionsAddAccountContent.kt b/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/presentation/optionsaddaccount/OptionsAddAccountContent.kt
index 0f623beb82..57f4b3bf3d 100644
--- a/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/presentation/optionsaddaccount/OptionsAddAccountContent.kt
+++ b/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/presentation/optionsaddaccount/OptionsAddAccountContent.kt
@@ -30,8 +30,7 @@ data class OptionsAddAccountScreenViewState(
     val chainId: ChainId,
     val chainName: String,
     val markedAsNotNeed: Boolean,
-    val assetId: String,
-    val priceId: String?
+    val assetId: String
 )
 
 @Composable
@@ -114,8 +113,7 @@ private fun OptionsAddAccountScreenPreview() {
                 chainId = "",
                 chainName = "Kusama",
                 markedAsNotNeed = false,
-                assetId = "",
-                priceId = null
+                assetId = ""
             ),
             onCreate = { t, t2 -> },
             onImport = { t, t2 -> },
diff --git a/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/presentation/optionsaddaccount/OptionsAddAccountFragment.kt b/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/presentation/optionsaddaccount/OptionsAddAccountFragment.kt
index 875e2ee759..b53066ee9f 100644
--- a/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/presentation/optionsaddaccount/OptionsAddAccountFragment.kt
+++ b/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/presentation/optionsaddaccount/OptionsAddAccountFragment.kt
@@ -9,7 +9,7 @@ import androidx.core.os.bundleOf
 import androidx.fragment.app.viewModels
 import com.google.android.material.bottomsheet.BottomSheetBehavior
 import dagger.hilt.android.AndroidEntryPoint
-import jp.co.soramitsu.account.api.presentation.actions.AddAccountBottomSheet
+import jp.co.soramitsu.account.api.presentation.actions.AddAccountPayload
 import jp.co.soramitsu.common.base.BaseComposeBottomSheetDialogFragment
 
 @AndroidEntryPoint
@@ -18,7 +18,7 @@ class OptionsAddAccountFragment : BaseComposeBottomSheetDialogFragment<OptionsAd
     companion object {
         const val KEY_PAYLOAD = "payload"
 
-        fun getBundle(payload: AddAccountBottomSheet.Payload) = bundleOf(KEY_PAYLOAD to payload)
+        fun getBundle(payload: AddAccountPayload) = bundleOf(KEY_PAYLOAD to payload)
     }
 
     override val viewModel: OptionsAddAccountViewModel by viewModels()
diff --git a/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/presentation/optionsaddaccount/OptionsAddAccountViewModel.kt b/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/presentation/optionsaddaccount/OptionsAddAccountViewModel.kt
index 77a5182111..42e07aeced 100644
--- a/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/presentation/optionsaddaccount/OptionsAddAccountViewModel.kt
+++ b/feature-account-impl/src/main/java/jp/co/soramitsu/account/impl/presentation/optionsaddaccount/OptionsAddAccountViewModel.kt
@@ -6,7 +6,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel
 import javax.inject.Inject
 import jp.co.soramitsu.account.api.domain.interfaces.AccountInteractor
 import jp.co.soramitsu.account.api.domain.interfaces.AssetNotNeedAccountUseCase
-import jp.co.soramitsu.account.api.presentation.actions.AddAccountBottomSheet
+import jp.co.soramitsu.account.api.presentation.actions.AddAccountPayload
 import jp.co.soramitsu.account.impl.presentation.AccountRouter
 import jp.co.soramitsu.account.impl.presentation.optionsaddaccount.OptionsAddAccountFragment.Companion.KEY_PAYLOAD
 import jp.co.soramitsu.common.base.BaseViewModel
@@ -31,14 +31,13 @@ class OptionsAddAccountViewModel @Inject constructor(
         .share()
 
     val state: StateFlow<OptionsAddAccountScreenViewState> = selectedWallet.mapNotNull {
-        savedStateHandle.get<AddAccountBottomSheet.Payload>(KEY_PAYLOAD)?.let { payload ->
+        savedStateHandle.get<AddAccountPayload>(KEY_PAYLOAD)?.let { payload ->
             OptionsAddAccountScreenViewState(
                 metaId = it.id,
                 chainId = payload.chainId,
                 chainName = payload.chainName,
                 markedAsNotNeed = payload.markedAsNotNeed,
-                assetId = payload.assetId,
-                priceId = payload.priceId
+                assetId = payload.assetId
             )
         }
     }.stateIn(
@@ -49,8 +48,7 @@ class OptionsAddAccountViewModel @Inject constructor(
             chainId = "",
             chainName = "Dotsama",
             markedAsNotNeed = false,
-            assetId = "",
-            priceId = null
+            assetId = ""
         )
     )
 
diff --git a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/di/StakingFeatureModule.kt b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/di/StakingFeatureModule.kt
index e614ab7117..4c0e5a4e30 100644
--- a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/di/StakingFeatureModule.kt
+++ b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/di/StakingFeatureModule.kt
@@ -15,6 +15,7 @@ import jp.co.soramitsu.common.data.network.AppLinksProvider
 import jp.co.soramitsu.common.data.network.rpc.BulkRetriever
 import jp.co.soramitsu.common.data.network.subquery.SoraEraInfoValidatorResponse
 import jp.co.soramitsu.common.data.storage.Preferences
+import jp.co.soramitsu.common.domain.SelectedFiat
 import jp.co.soramitsu.common.resources.ResourceManager
 import jp.co.soramitsu.core.extrinsic.ExtrinsicService
 import jp.co.soramitsu.core.extrinsic.mortality.IChainStateRepository
@@ -587,8 +588,8 @@ class StakingFeatureModule {
     fun provideIdentitiesUseCase(identityRepository: IdentityRepository) = GetIdentitiesUseCase(identityRepository)
 
     @Provides
-    fun soraTokensRateUseCase(rpcCalls: RpcCalls, chainRegistry: ChainRegistry, tokenPriceDao: TokenPriceDao) =
-        SoraStakingRewardsScenario(rpcCalls, chainRegistry, tokenPriceDao)
+    fun soraTokensRateUseCase(rpcCalls: RpcCalls, chainRegistry: ChainRegistry, tokenPriceDao: TokenPriceDao, selectedFiat: SelectedFiat) =
+        SoraStakingRewardsScenario(rpcCalls, chainRegistry, tokenPriceDao, selectedFiat)
 
     @Provides
     @Singleton
diff --git a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/domain/rewards/SoraStakingRewardsScenario.kt b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/domain/rewards/SoraStakingRewardsScenario.kt
index e3f714a1d7..c3c850168d 100644
--- a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/domain/rewards/SoraStakingRewardsScenario.kt
+++ b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/domain/rewards/SoraStakingRewardsScenario.kt
@@ -1,6 +1,7 @@
 package jp.co.soramitsu.staking.impl.domain.rewards
 
 import java.math.BigInteger
+import jp.co.soramitsu.common.domain.SelectedFiat
 import jp.co.soramitsu.common.utils.orZero
 import jp.co.soramitsu.core.rpc.RpcCalls
 import jp.co.soramitsu.core.rpc.calls.liquidityProxyQuote
@@ -12,7 +13,8 @@ import jp.co.soramitsu.wallet.impl.domain.model.Token
 class SoraStakingRewardsScenario(
     private val rpcCalls: RpcCalls,
     private val chainRegistry: ChainRegistry,
-    private val tokenDao: TokenPriceDao
+    private val tokenDao: TokenPriceDao,
+    private val selectedFiat: SelectedFiat
 ) {
     companion object {
         private const val SORA_MAIN_NET_CHAIN_ID =
@@ -37,8 +39,9 @@ class SoraStakingRewardsScenario(
     suspend fun getRewardAsset(): Token {
         val chain = chainRegistry.getChain(SORA_MAIN_NET_CHAIN_ID)
         val rewardAsset = requireNotNull(chain.assetsById[REWARD_ASSET_ID])
-        val priceId = requireNotNull(rewardAsset.priceProvider?.id ?: rewardAsset.priceId)
-        val token = tokenDao.getTokenPrice(priceId)
+        val priceId = rewardAsset.priceProvider?.id?.takeIf { selectedFiat.isUsd() } ?: rewardAsset.priceId
+        val requirePriceId = requireNotNull(priceId)
+        val token = tokenDao.getTokenPrice(requirePriceId)
 
         return Token(
             configuration = rewardAsset,
diff --git a/feature-wallet-api/src/main/java/jp/co/soramitsu/wallet/api/data/cache/AssetCache.kt b/feature-wallet-api/src/main/java/jp/co/soramitsu/wallet/api/data/cache/AssetCache.kt
index c9cd697550..544a210550 100644
--- a/feature-wallet-api/src/main/java/jp/co/soramitsu/wallet/api/data/cache/AssetCache.kt
+++ b/feature-wallet-api/src/main/java/jp/co/soramitsu/wallet/api/data/cache/AssetCache.kt
@@ -37,7 +37,7 @@ class AssetCache(
     ) = withContext(Dispatchers.IO) {
         val chainId = chainAsset.chainId
         val assetId = chainAsset.id
-        val shouldUseChainlinkForRates = selectedFiat.get() == "usd" && chainAsset.priceProvider?.id != null
+        val shouldUseChainlinkForRates = selectedFiat.isUsd() && chainAsset.priceProvider?.id != null
         val priceId = if (shouldUseChainlinkForRates) {
             chainAsset.priceProvider?.id
         } else {
diff --git a/feature-wallet-impl/build.gradle b/feature-wallet-impl/build.gradle
index 2d8907d2ee..8192ef6605 100644
--- a/feature-wallet-impl/build.gradle
+++ b/feature-wallet-impl/build.gradle
@@ -140,6 +140,4 @@ dependencies {
     implementation sharedFeaturesBackupDep
 
     implementation web3jDep
-    implementation web3jContractsDep
-//    implementation web3jGethDep
 }
\ No newline at end of file
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/repository/TokenRepositoryImpl.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/repository/TokenRepositoryImpl.kt
index b23776dd2f..6ff1ee7daf 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/repository/TokenRepositoryImpl.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/repository/TokenRepositoryImpl.kt
@@ -1,5 +1,6 @@
 package jp.co.soramitsu.wallet.impl.data.repository
 
+import jp.co.soramitsu.common.domain.SelectedFiat
 import jp.co.soramitsu.common.utils.flowOf
 import jp.co.soramitsu.core.models.Asset
 import jp.co.soramitsu.coredb.dao.TokenPriceDao
@@ -9,28 +10,41 @@ import jp.co.soramitsu.wallet.impl.domain.interfaces.TokenRepository
 import jp.co.soramitsu.wallet.impl.domain.model.Token
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flatMapLatest
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.withContext
 
 class TokenRepositoryImpl(
-    private val tokenPriceDao: TokenPriceDao
+    private val tokenPriceDao: TokenPriceDao,
+    private val selectedFiat: SelectedFiat
 ) : TokenRepository {
 
     override suspend fun getToken(chainAsset: Asset): Token = withContext(Dispatchers.Default) {
-        val priceId = chainAsset.priceProvider?.id ?: chainAsset.priceId
+        val priceId = if (selectedFiat.isUsd() && chainAsset.priceProvider?.id != null) {
+            chainAsset.priceProvider?.id
+        } else {
+            chainAsset.priceId
+        }
         val tokenPriceLocal = priceId?.let { tokenPriceDao.getTokenPrice(it) ?: TokenPriceLocal.createEmpty(it) }
 
         combineAssetWithPrices(chainAsset, tokenPriceLocal)
     }
 
     override fun observeToken(chainAsset: Asset): Flow<Token> {
-        val priceId = chainAsset.priceProvider?.id ?: chainAsset.priceId
-        return when (priceId) {
-            null -> flowOf {
-                combineAssetWithPrices(chainAsset, null)
+        return selectedFiat.flow().map {
+            if (it == "usd" && chainAsset.priceProvider?.id != null) {
+                chainAsset.priceProvider?.id
+            } else {
+                chainAsset.priceId
             }
-            else -> tokenPriceDao.observeTokenPrice(priceId).map {
-                combineAssetWithPrices(chainAsset, it)
+        }.flatMapLatest { priceId ->
+            when (priceId) {
+                null -> flowOf {
+                    combineAssetWithPrices(chainAsset, null)
+                }
+                else -> tokenPriceDao.observeTokenPrice(priceId).map {
+                    combineAssetWithPrices(chainAsset, it)
+                }
             }
         }
     }
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 4f48e9b46d..50f2ef536b 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
@@ -16,6 +16,7 @@ import jp.co.soramitsu.common.data.secrets.v2.KeyPairSchema
 import jp.co.soramitsu.common.data.secrets.v2.MetaAccountSecrets
 import jp.co.soramitsu.common.data.storage.Preferences
 import jp.co.soramitsu.common.domain.GetAvailableFiatCurrencies
+import jp.co.soramitsu.common.domain.SelectedFiat
 import jp.co.soramitsu.common.mixin.api.UpdatesMixin
 import jp.co.soramitsu.common.mixin.api.UpdatesProviderUi
 import jp.co.soramitsu.common.utils.orZero
@@ -83,7 +84,8 @@ class WalletRepositoryImpl(
     private val remoteConfigFetcher: RemoteConfigFetcher,
     private val preferences: Preferences,
     private val accountRepository: AccountRepository,
-    private val chainsRepository: ChainsRepository
+    private val chainsRepository: ChainsRepository,
+    private val selectedFiat: SelectedFiat
 ) : WalletRepository, UpdatesProviderUi by updatesMixin {
 
     companion object {
@@ -160,8 +162,7 @@ class WalletRepositoryImpl(
                 type = NetworkIssueType.Node,
                 chainId = configuration.chainId,
                 chainName = configuration.chainName,
-                assetId = configuration.id,
-                priceId = configuration.priceProvider?.id ?: configuration.priceId
+                assetId = configuration.id
             )
         }.toSet()
     }
@@ -203,7 +204,6 @@ class WalletRepositoryImpl(
 
         val chainlinkProvider = chains.firstOrNull { it.chainlinkProvider }
         val chainlinkProviderId = chainlinkProvider?.id
-        println("!!! chainlinkProvider is ${chainlinkProvider?.name} $chainlinkProviderId ")
 
         val chainlinkTokens = chainlinkIds.map { priceId ->
             val assetConfig = chains.flatMap { it.assets }.firstOrNull { it.priceProvider?.id == priceId }
@@ -285,6 +285,7 @@ class WalletRepositoryImpl(
         isHidden: Boolean,
         chainAsset: CoreAsset
     ) {
+        val tokenPriceId = chainAsset.priceProvider?.id?.takeIf { selectedFiat.isUsd() } ?: chainAsset.priceId
         val updateItems = listOf(
             AssetUpdateItem(
                 metaId = metaId,
@@ -293,7 +294,7 @@ class WalletRepositoryImpl(
                 id = chainAsset.id,
                 sortIndex = Int.MAX_VALUE, // Int.MAX_VALUE on sorting because we don't use it anymore - just random value
                 enabled = !isHidden,
-                tokenPriceId = chainAsset.priceProvider?.id ?: chainAsset.priceId
+                tokenPriceId = tokenPriceId
             )
         )
 
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 0493cfb4a9..b74f397e28 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
@@ -145,9 +145,11 @@ class WalletFeatureModule {
 
     @Provides
     fun provideTokenRepository(
-        tokenPriceDao: TokenPriceDao
+        tokenPriceDao: TokenPriceDao,
+        selectedFiat: SelectedFiat
     ): TokenRepository = TokenRepositoryImpl(
-        tokenPriceDao
+        tokenPriceDao,
+        selectedFiat
     )
 
     @Provides
@@ -171,7 +173,8 @@ class WalletFeatureModule {
         remoteConfigFetcher: RemoteConfigFetcher,
         preferences: Preferences,
         accountRepository: AccountRepository,
-        chainsRepository: ChainsRepository
+        chainsRepository: ChainsRepository,
+        selectedFiat: SelectedFiat
     ): WalletRepository = WalletRepositoryImpl(
         substrateSource,
         ethereumRemoteSource,
@@ -188,7 +191,8 @@ class WalletFeatureModule {
         remoteConfigFetcher,
         preferences,
         accountRepository,
-        chainsRepository
+        chainsRepository,
+        selectedFiat
     )
 
     @Provides
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 16399320e5..4eedfdf180 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
@@ -4,7 +4,7 @@ import android.graphics.drawable.Drawable
 import it.airgap.beaconsdk.blockchain.substrate.data.SubstrateSignerPayload
 import java.math.BigDecimal
 import jp.co.soramitsu.account.api.domain.model.ImportMode
-import jp.co.soramitsu.account.api.presentation.actions.AddAccountBottomSheet
+import jp.co.soramitsu.account.api.presentation.actions.AddAccountPayload
 import jp.co.soramitsu.common.AlertViewState
 import jp.co.soramitsu.common.navigation.DelayedNavigation
 import jp.co.soramitsu.common.navigation.PinRequired
@@ -144,7 +144,7 @@ interface WalletRouter : SecureRouter, WalletRouterApi {
 
     fun openGetSoraCard()
 
-    fun openOptionsAddAccount(payload: AddAccountBottomSheet.Payload)
+    fun openOptionsAddAccount(payload: AddAccountPayload)
 
     fun openOptionsSwitchNode(
         metaId: Long,
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 2987bf8b50..b45185c9fd 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
@@ -273,7 +273,6 @@ class BalanceListViewModel @Inject constructor(
                     chainAssetId = chainAsset.id,
                     isSupported = true,
                     isHidden = false,
-                    priceId = chainAsset.priceProvider?.id ?: chainAsset.priceId,
                     isTestnet = chainAsset.isTestNet ?: false
                 )
             }.filter { selectedChainId.value == null || selectedChainId.value == it.chainId }
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 8c12e23fc1..7752e0459b 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
@@ -243,7 +243,6 @@ private fun PreviewWalletScreen() {
             chainAssetId = "",
             isSupported = true,
             isHidden = false,
-            priceId = null,
             isTestnet = false
         )
     )
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/list/model/BalanceListItemModel.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/list/model/BalanceListItemModel.kt
index 633836a960..f57fdedc7f 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/list/model/BalanceListItemModel.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/list/model/BalanceListItemModel.kt
@@ -36,6 +36,5 @@ fun BalanceListItemModel.toAssetState(index: Int? = null) = AssetListItemViewSta
     chainAssetId = asset.id,
     isSupported = chain?.isSupported != false,
     isHidden = isHidden,
-    priceId = asset.priceProvider?.id ?: asset.priceId,
     isTestnet = chain?.isTestNet == true
 )
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/networkissues/NetworkIssuesViewModel.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/networkissues/NetworkIssuesViewModel.kt
index 22b0be2281..2716e848b8 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/networkissues/NetworkIssuesViewModel.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/balance/networkissues/NetworkIssuesViewModel.kt
@@ -5,7 +5,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel
 import javax.inject.Inject
 import jp.co.soramitsu.account.api.domain.interfaces.AccountInteractor
 import jp.co.soramitsu.account.api.domain.interfaces.AssetNotNeedAccountUseCase
-import jp.co.soramitsu.account.api.presentation.actions.AddAccountBottomSheet
+import jp.co.soramitsu.account.api.presentation.actions.AddAccountPayload
 import jp.co.soramitsu.common.AlertViewState
 import jp.co.soramitsu.common.base.BaseViewModel
 import jp.co.soramitsu.common.compose.component.NetworkIssueItemState
@@ -20,7 +20,6 @@ import jp.co.soramitsu.wallet.impl.domain.interfaces.WalletInteractor
 import jp.co.soramitsu.wallet.impl.presentation.WalletRouter
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.combine
-import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.first
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.map
@@ -104,12 +103,11 @@ class NetworkIssuesViewModel @Inject constructor(
 
             NetworkIssueType.Account -> launch {
                 val meta = accountInteractor.selectedMetaAccountFlow().first()
-                val payload = AddAccountBottomSheet.Payload(
+                val payload = AddAccountPayload(
                     metaId = meta.id,
                     chainId = issue.chainId,
                     chainName = issue.chainName,
                     assetId = issue.assetId,
-                    priceId = issue.priceId,
                     markedAsNotNeed = false
                 )
                 walletRouter.openOptionsAddAccount(payload)
diff --git a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/ChainRegistry.kt b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/ChainRegistry.kt
index bdc62e31d6..aa1facfca4 100644
--- a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/ChainRegistry.kt
+++ b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/ChainRegistry.kt
@@ -266,7 +266,6 @@ fun Chain.toSyncIssue(): NetworkIssueItemState {
         },
         chainId = this.id,
         chainName = this.name,
-        assetId = this.utilityAsset?.id.orEmpty(),
-        priceId = this.utilityAsset?.priceProvider?.id ?: this.utilityAsset?.priceId
+        assetId = this.utilityAsset?.id.orEmpty()
     )
 }
diff --git a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/connection/ConnectionPool.kt b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/connection/ConnectionPool.kt
index fe122221f2..09bf2bd629 100644
--- a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/connection/ConnectionPool.kt
+++ b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/connection/ConnectionPool.kt
@@ -70,8 +70,7 @@ class ConnectionPool @Inject constructor(
                         },
                         chainId = chain.id,
                         chainName = chain.name,
-                        assetId = chain.utilityAsset?.id.orEmpty(),
-                        priceId = chain.utilityAsset?.priceProvider?.id ?: chain.utilityAsset?.priceId
+                        assetId = chain.utilityAsset?.id.orEmpty()
                     )
                 }
             issues

From d4875cc95515b8353fd8a5ca6c70c366bc4ea16d Mon Sep 17 00:00:00 2001
From: Sergey Pankratov <pankratov@soramitsu.co.jp>
Date: Wed, 7 Feb 2024 13:28:01 +0500
Subject: [PATCH 08/35] pr fix

---
 .../blockchain/EthereumRemoteSource.kt        |  3 +-
 .../data/repository/WalletRepositoryImpl.kt   | 41 +++++++++++++++----
 .../wallet/impl/di/WalletFeatureModule.kt     |  6 ++-
 3 files changed, 40 insertions(+), 10 deletions(-)

diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/blockchain/EthereumRemoteSource.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/blockchain/EthereumRemoteSource.kt
index f77b56dc51..fe4173395a 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/blockchain/EthereumRemoteSource.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/blockchain/EthereumRemoteSource.kt
@@ -148,7 +148,8 @@ class EthereumRemoteSource(private val ethereumConnectionPool: EthereumConnectio
         val connection = ethereumConnectionPool.get(chainId)
         connection?.connect()
 
-        val web3 = connection?.web3j ?: return null
+        val web3 = connection?.web3j
+            ?: throw RuntimeException("There is no connection created for chain ${chainId}")
 
         return web3.fetchPriceFeed(receiverAddress)
     }
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 50f2ef536b..7882c35263 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
@@ -25,6 +25,7 @@ import jp.co.soramitsu.core.models.Asset.PriceProvider
 import jp.co.soramitsu.core.utils.utilityAsset
 import jp.co.soramitsu.coredb.dao.OperationDao
 import jp.co.soramitsu.coredb.dao.PhishingDao
+import jp.co.soramitsu.coredb.dao.TokenPriceDao
 import jp.co.soramitsu.coredb.dao.emptyAccountIdValue
 import jp.co.soramitsu.coredb.model.AssetUpdateItem
 import jp.co.soramitsu.coredb.model.AssetWithToken
@@ -85,7 +86,8 @@ class WalletRepositoryImpl(
     private val preferences: Preferences,
     private val accountRepository: AccountRepository,
     private val chainsRepository: ChainsRepository,
-    private val selectedFiat: SelectedFiat
+    private val selectedFiat: SelectedFiat,
+    private val tokenPriceDao: TokenPriceDao
 ) : WalletRepository, UpdatesProviderUi by updatesMixin {
 
     companion object {
@@ -243,19 +245,44 @@ class WalletRepositoryImpl(
             val fiatCurrency = availableFiatCurrencies[currencyId]
 
             updateAssetRates(priceId, fiatCurrency?.symbol, price, change)
+
+            if (currencyId == "usd") {
+                val assetsWithChainlinkPrice = chains.map { it.assets.filter { it.priceProvider?.id != null } }.flatten().toSet()
+
+                updateChainlinkPriceWithCoingeckoChange(assetsWithChainlinkPrice, priceId, change)
+            }
         }
         updatesMixin.finishUpdateTokens(priceIds)
     }
 
-    private suspend fun getChainlinkPrices(priceProvider: PriceProvider, chainId: ChainId): BigDecimal? {
-        return ethereumSource.fetchPriceFeed(
-            chainId = chainId,
-            receiverAddress = priceProvider.id
-        )?.let { price ->
-            BigDecimal(price, priceProvider.precision)
+    private suspend fun WalletRepositoryImpl.updateChainlinkPriceWithCoingeckoChange(assetsWithChainlinkPrice: Set<jp.co.soramitsu.core.models.Asset>, priceId: String, change: BigDecimal?) {
+        val chainlinkId = assetsWithChainlinkPrice.firstOrNull {
+            it.priceId == priceId
+        }?.priceProvider?.id
+
+        chainlinkId?.let {
+            val tokenPrice = tokenPriceDao.getTokenPrice(chainlinkId)
+
+            updateAssetRates(
+                priceId = chainlinkId,
+                fiatSymbol = tokenPrice?.fiatSymbol,
+                price = tokenPrice?.fiatRate,
+                change = change
+            )
         }
     }
 
+    private suspend fun getChainlinkPrices(priceProvider: PriceProvider, chainId: ChainId): BigDecimal? {
+        return runCatching {
+            ethereumSource.fetchPriceFeed(
+                chainId = chainId,
+                receiverAddress = priceProvider.id
+            )?.let { price ->
+                BigDecimal(price, priceProvider.precision)
+            }
+        }.getOrNull()
+    }
+
     override fun assetFlow(
         metaId: Long,
         accountId: AccountId,
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 b74f397e28..76badf314c 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
@@ -174,7 +174,8 @@ class WalletFeatureModule {
         preferences: Preferences,
         accountRepository: AccountRepository,
         chainsRepository: ChainsRepository,
-        selectedFiat: SelectedFiat
+        selectedFiat: SelectedFiat,
+        tokenPriceDao: TokenPriceDao
     ): WalletRepository = WalletRepositoryImpl(
         substrateSource,
         ethereumRemoteSource,
@@ -192,7 +193,8 @@ class WalletFeatureModule {
         preferences,
         accountRepository,
         chainsRepository,
-        selectedFiat
+        selectedFiat,
+        tokenPriceDao
     )
 
     @Provides

From dc017295e15bb3795ead819dd3d5fbb572eb44b3 Mon Sep 17 00:00:00 2001
From: Sergey Pankratov <pankratov@soramitsu.co.jp>
Date: Thu, 8 Feb 2024 13:00:23 +0500
Subject: [PATCH 09/35] fix crash

---
 .../app/root/presentation/main/MainFragment.kt        | 11 +++++++++--
 build.gradle                                          |  2 +-
 gradle/libs.versions.toml                             |  2 +-
 3 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/app/src/main/java/jp/co/soramitsu/app/root/presentation/main/MainFragment.kt b/app/src/main/java/jp/co/soramitsu/app/root/presentation/main/MainFragment.kt
index 3ffaa0b033..586a261ad6 100644
--- a/app/src/main/java/jp/co/soramitsu/app/root/presentation/main/MainFragment.kt
+++ b/app/src/main/java/jp/co/soramitsu/app/root/presentation/main/MainFragment.kt
@@ -1,5 +1,7 @@
 package jp.co.soramitsu.app.root.presentation.main
 
+import android.os.Bundle
+import android.view.View
 import androidx.activity.OnBackPressedCallback
 import androidx.fragment.app.viewModels
 import androidx.navigation.NavController
@@ -25,7 +27,7 @@ class MainFragment : BaseFragment<MainViewModel>(R.layout.fragment_main) {
         }
     }
 
-    private val binding by viewBinding(FragmentMainBinding::bind)
+    private lateinit var binding: FragmentMainBinding
 
     override val viewModel: MainViewModel by viewModels()
 
@@ -35,6 +37,11 @@ class MainFragment : BaseFragment<MainViewModel>(R.layout.fragment_main) {
         backCallback.isEnabled = false
     }
 
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        binding = FragmentMainBinding.bind(view)
+        super.onViewCreated(view, savedInstanceState)
+    }
+
     override fun initViews() {
         binding.bottomNavigationView.setOnApplyWindowInsetsListener { _, insets ->
             // overwrite BottomNavigation behavior and ignore insets
@@ -60,7 +67,7 @@ class MainFragment : BaseFragment<MainViewModel>(R.layout.fragment_main) {
 
         binding.bottomNavigationView.setupWithNavController(navController!!)
 
-        binding.bottomNavigationView.setOnNavigationItemSelectedListener { item ->
+        binding.bottomNavigationView.setOnItemSelectedListener { item ->
             onNavDestinationSelected(item, navController!!)
         }
 
diff --git a/build.gradle b/build.gradle
index 1278b446c0..855d13af62 100644
--- a/build.gradle
+++ b/build.gradle
@@ -79,7 +79,7 @@ buildscript {
         serializationVersion = '1.5.1'
 
         activityKtx = '1.7.0'
-        fragmentKtx = '1.5.6'
+        fragmentKtx = '1.6.2'
         minifyRelease = true
         beaconVersion = "3.2.4"
 
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 6e08840bf7..fc76b1436c 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -1,7 +1,7 @@
 [versions]
 compose = "1.5.1"
 composeFoundation = "1.5.1"
-fragmentKtx = "1.5.6"
+fragmentKtx = "1.6.2"
 composeThemeAdapter = "1.2.1"
 googleServices = "4.3.15"
 junit = "4.13.2"

From f723f133ec17457a101d97339de74a690b89384a Mon Sep 17 00:00:00 2001
From: Deneath <lyazgindenis@gmail.com>
Date: Mon, 22 Jan 2024 17:34:54 +0700
Subject: [PATCH 10/35] WIP

---
 .../runtime/multiNetwork/runtime/RuntimeProvider.kt        | 7 +++++++
 .../runtime/multiNetwork/runtime/RuntimeSyncService.kt     | 4 +++-
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/runtime/RuntimeProvider.kt b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/runtime/RuntimeProvider.kt
index c10acd556e..2acc77de8e 100644
--- a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/runtime/RuntimeProvider.kt
+++ b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/runtime/RuntimeProvider.kt
@@ -1,5 +1,6 @@
 package jp.co.soramitsu.runtime.multiNetwork.runtime
 
+import android.util.Log
 import jp.co.soramitsu.common.mixin.api.NetworkStateMixin
 import jp.co.soramitsu.core.runtime.ConstructedRuntime
 import jp.co.soramitsu.core.runtime.RuntimeFactory
@@ -128,9 +129,15 @@ class RuntimeProvider(
 
                 val runtime =
                     runtimeFactory.constructRuntime(metadataRaw, ownTypesRaw, runtimeVersion)
+                if(chainId == "7834781d38e4798d548e34ec947d19deea29df148a7bf32484b7b24dacf8d4b7"){
+                    Log.d("&&&", "reef runtime construction: ${runtime.runtime}")
+                }
                 runtimeFlow.emit(runtime)
                 networkStateMixin.notifyChainSyncSuccess(chainId)
             }.onFailure {
+                if(chainId == "7834781d38e4798d548e34ec947d19deea29df148a7bf32484b7b24dacf8d4b7"){
+                    Log.d("&&&", "reef runtime construction failure: $it ${it.message}")
+                }
                 networkStateMixin.notifyChainSyncProblem(chain.toSyncIssue())
                 when (it) {
                     ChainInfoNotInCacheException -> runtimeSyncService.cacheNotFound(chainId)
diff --git a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/runtime/RuntimeSyncService.kt b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/runtime/RuntimeSyncService.kt
index abcea704dc..0e95d5881f 100644
--- a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/runtime/RuntimeSyncService.kt
+++ b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/runtime/RuntimeSyncService.kt
@@ -109,7 +109,9 @@ class RuntimeSyncService(
                     GetMetadataRequest,
                     mapper = pojo<String>().nonNull()
                 ).getOrNull()
-
+            if(chainId == "7834781d38e4798d548e34ec947d19deea29df148a7bf32484b7b24dacf8d4b7"){
+                Log.d("&&&", "reef metadata length: ${runtimeMetadata?.length}")
+            }
             runtimeMetadata?.let {
 
                 runtimeFilesCache.saveChainMetadata(chainId, runtimeMetadata)

From 0be294312e716ac7c566855094b7a7a9eb2d6083 Mon Sep 17 00:00:00 2001
From: Deneath <lyazgindenis@gmail.com>
Date: Tue, 23 Jan 2024 13:13:34 +0700
Subject: [PATCH 11/35] add default types loading, add v13 runtime construction
 method for reef, add balance update for reef

---
 .../updaters/BalancesUpdateSystem.kt          | 20 ++++++--
 .../network/model/SubstrateBalancesUtils.kt   | 50 ++++++++++++++++++-
 runtime/build.gradle                          |  1 +
 .../multiNetwork/chain/ChainSpecificUtils.kt  | 20 ++++++++
 .../multiNetwork/runtime/RuntimeProvider.kt   | 16 +++---
 .../runtime/RuntimeSyncService.kt             |  6 +--
 6 files changed, 97 insertions(+), 16 deletions(-)
 create mode 100644 runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/ChainSpecificUtils.kt

diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/blockchain/updaters/BalancesUpdateSystem.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/blockchain/updaters/BalancesUpdateSystem.kt
index a1b7ff2dbc..8826796a75 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/blockchain/updaters/BalancesUpdateSystem.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/blockchain/updaters/BalancesUpdateSystem.kt
@@ -1,21 +1,30 @@
 package jp.co.soramitsu.wallet.impl.data.network.blockchain.updaters
 
 import android.util.Log
+import io.emeraldpay.polkaj.scale.ScaleCodecReader
 import it.airgap.beaconsdk.core.internal.utils.failure
 import it.airgap.beaconsdk.core.internal.utils.onEachFailure
+import java.math.BigInteger
+import java.nio.ByteOrder
 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
 import jp.co.soramitsu.account.api.domain.model.address
 import jp.co.soramitsu.common.data.network.rpc.BulkRetriever
+import jp.co.soramitsu.common.data.network.runtime.binding.AccountData
+import jp.co.soramitsu.common.data.network.runtime.binding.AccountInfo
 import jp.co.soramitsu.common.data.network.runtime.binding.ExtrinsicStatusEvent
 import jp.co.soramitsu.common.data.network.runtime.binding.SimpleBalanceData
+import jp.co.soramitsu.common.data.network.runtime.binding.bindNonce
+import jp.co.soramitsu.common.data.network.runtime.binding.cast
 import jp.co.soramitsu.common.mixin.api.NetworkStateMixin
 import jp.co.soramitsu.common.utils.orZero
 import jp.co.soramitsu.common.utils.requireException
 import jp.co.soramitsu.common.utils.requireValue
+import jp.co.soramitsu.common.utils.system
 import jp.co.soramitsu.core.models.Asset
 import jp.co.soramitsu.core.models.ChainAssetType
+import jp.co.soramitsu.core.runtime.storage.returnType
 import jp.co.soramitsu.core.updater.UpdateSystem
 import jp.co.soramitsu.core.updater.Updater
 import jp.co.soramitsu.core.utils.utilityAsset
@@ -28,8 +37,14 @@ import jp.co.soramitsu.runtime.multiNetwork.getSocket
 import jp.co.soramitsu.runtime.multiNetwork.getSocketOrNull
 import jp.co.soramitsu.runtime.multiNetwork.toSyncIssue
 import jp.co.soramitsu.runtime.network.subscriptionFlowCatching
+import jp.co.soramitsu.shared_utils.extensions.fromUnsignedBytes
 import jp.co.soramitsu.shared_utils.runtime.AccountId
 import jp.co.soramitsu.shared_utils.runtime.RuntimeSnapshot
+import jp.co.soramitsu.shared_utils.runtime.definitions.types.composite.Struct
+import jp.co.soramitsu.shared_utils.runtime.definitions.types.fromHexOrNull
+import jp.co.soramitsu.shared_utils.runtime.metadata.storage
+import jp.co.soramitsu.shared_utils.scale.dataType.uint128
+import jp.co.soramitsu.shared_utils.scale.utils.toUnsignedBytes
 import jp.co.soramitsu.shared_utils.wsrpc.request.runtime.storage.SubscribeStorageRequest
 import jp.co.soramitsu.shared_utils.wsrpc.request.runtime.storage.storageChange
 import jp.co.soramitsu.wallet.api.data.cache.AssetCache
@@ -175,10 +190,9 @@ class BalancesUpdateSystem(
                             storageKeyToHex.mapNotNull { (key, hexRaw) ->
                                 val metadata = storageKeys.firstOrNull { it.key == key }
                                     ?: return@mapNotNull null
-
                                 val balanceData = handleBalanceResponse(
                                     runtime,
-                                    metadata.asset.typeExtra,
+                                    metadata.asset,
                                     hexRaw
                                 ).onFailure { logError(chain, it) }
 
@@ -240,7 +254,7 @@ class BalancesUpdateSystem(
 
                     val balanceData = handleBalanceResponse(
                         runtime,
-                        keyWithMetadata.asset.typeExtra,
+                        keyWithMetadata.asset,
                         hexRaw
                     ).onFailure { logError(chain, it) }
 
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/SubstrateBalancesUtils.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/SubstrateBalancesUtils.kt
index 73800a34a7..d667fb410d 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/SubstrateBalancesUtils.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/SubstrateBalancesUtils.kt
@@ -1,14 +1,26 @@
 package jp.co.soramitsu.wallet.impl.data.network.model
 
 import android.util.Log
+import java.math.BigInteger
+import jp.co.soramitsu.common.data.network.runtime.binding.AccountData
+import jp.co.soramitsu.common.data.network.runtime.binding.AccountInfo
 import jp.co.soramitsu.common.data.network.runtime.binding.AssetBalanceData
 import jp.co.soramitsu.common.data.network.runtime.binding.EmptyBalance
+import jp.co.soramitsu.common.data.network.runtime.binding.bindNonce
+import jp.co.soramitsu.common.data.network.runtime.binding.cast
 import jp.co.soramitsu.common.utils.Modules
+import jp.co.soramitsu.common.utils.failure
+import jp.co.soramitsu.common.utils.orZero
 import jp.co.soramitsu.common.utils.system
 import jp.co.soramitsu.common.utils.tokens
 import jp.co.soramitsu.core.models.Asset
 import jp.co.soramitsu.core.models.ChainAssetType
+import jp.co.soramitsu.core.runtime.storage.returnType
+import jp.co.soramitsu.runtime.multiNetwork.chain.ReefBalance
+import jp.co.soramitsu.runtime.multiNetwork.chain.model.reefChainId
 import jp.co.soramitsu.shared_utils.runtime.RuntimeSnapshot
+import jp.co.soramitsu.shared_utils.runtime.definitions.types.composite.Struct
+import jp.co.soramitsu.shared_utils.runtime.definitions.types.fromHexOrNull
 import jp.co.soramitsu.shared_utils.runtime.metadata.module
 import jp.co.soramitsu.shared_utils.runtime.metadata.storage
 import jp.co.soramitsu.shared_utils.runtime.metadata.storageKey
@@ -65,11 +77,14 @@ fun constructBalanceKey(
 
 fun handleBalanceResponse(
     runtime: RuntimeSnapshot,
-    assetType: ChainAssetType?,
+    asset: Asset,
     scale: String?
 ): Result<AssetBalanceData> {
     return runCatching {
-        when (assetType) {
+        if (asset.chainId == reefChainId) {
+            return bindReefAccountInfo(runtime, scale)
+        }
+        when (asset.typeExtra) {
             null,
             ChainAssetType.Normal,
             ChainAssetType.SoraUtilityAsset -> {
@@ -103,3 +118,34 @@ fun handleBalanceResponse(
         }
     }
 }
+
+private fun bindReefAccountInfo(runtime: RuntimeSnapshot, scale: String?): Result<AccountInfo> {
+    return runCatching {
+        val type = runtime.metadata.system().storage("Account")
+            .returnType()
+
+        val dynamicInstance = type.fromHexOrNull(
+            runtime,
+            scale ?: return Result.failure("Reef system.Account returned null hex result")
+        ).cast<Struct.Instance>()
+
+        AccountInfo(
+            nonce = bindNonce(dynamicInstance["nonce"]),
+            data = dynamicInstance.get<Struct.Instance?>("data")
+                .let {
+                    val freeBalance = ReefBalance((it?.get("free") as? BigInteger).orZero())
+                    val reservedBalance = ReefBalance((it?.get("reserved") as? BigInteger).orZero())
+                    val miscFrozenBalance =
+                        ReefBalance((it?.get("miscFrozen") as? BigInteger).orZero())
+                    val feeFrozenBalance =
+                        ReefBalance((it?.get("feeFrozen") as? BigInteger).orZero())
+                    AccountData(
+                        free = freeBalance.planks,
+                        reserved = reservedBalance.planks,
+                        miscFrozen = miscFrozenBalance.planks,
+                        feeFrozen = feeFrozenBalance.planks
+                    )
+                }
+        )
+    }
+}
\ No newline at end of file
diff --git a/runtime/build.gradle b/runtime/build.gradle
index c10fa10dd9..8ac37469a6 100644
--- a/runtime/build.gradle
+++ b/runtime/build.gradle
@@ -14,6 +14,7 @@ android {
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
         buildConfigField "String", "TYPES_URL", "\"https://raw.githubusercontent.com/soramitsu/shared-features-utils/master/chains/all_chains_types_android.json\""
         buildConfigField "String", "APP_VERSION_NAME", "\"${rootProject.versionName}\""
+        buildConfigField("String", "DEFAULT_V13_TYPES_URL", "\"https://raw.githubusercontent.com/soramitsu/shared-features-utils/reef/chains/default_v13_types.json\"")
     }
 
     buildTypes {
diff --git a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/ChainSpecificUtils.kt b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/ChainSpecificUtils.kt
new file mode 100644
index 0000000000..a0618b24a8
--- /dev/null
+++ b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/ChainSpecificUtils.kt
@@ -0,0 +1,20 @@
+package jp.co.soramitsu.runtime.multiNetwork.chain
+
+import io.emeraldpay.polkaj.scale.ScaleCodecReader
+import java.math.BigInteger
+import java.nio.ByteOrder
+import jp.co.soramitsu.shared_utils.extensions.fromUnsignedBytes
+import jp.co.soramitsu.shared_utils.scale.dataType.uint128
+import jp.co.soramitsu.shared_utils.scale.utils.toUnsignedBytes
+
+@JvmInline
+value class ReefBalance(val value: BigInteger) {
+    val planks: BigInteger
+        get() {
+            val bytes = value.toUnsignedBytes().fromUnsignedBytes(ByteOrder.LITTLE_ENDIAN).toByteArray()
+            val newArray = ByteArray(16)
+            bytes.copyInto(newArray)
+            val reader = ScaleCodecReader(newArray)
+            return uint128.read(reader)
+        }
+}
\ No newline at end of file
diff --git a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/runtime/RuntimeProvider.kt b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/runtime/RuntimeProvider.kt
index 2acc77de8e..bcc9cf0ae8 100644
--- a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/runtime/RuntimeProvider.kt
+++ b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/runtime/RuntimeProvider.kt
@@ -1,11 +1,11 @@
 package jp.co.soramitsu.runtime.multiNetwork.runtime
 
-import android.util.Log
 import jp.co.soramitsu.common.mixin.api.NetworkStateMixin
 import jp.co.soramitsu.core.runtime.ConstructedRuntime
 import jp.co.soramitsu.core.runtime.RuntimeFactory
 import jp.co.soramitsu.coredb.dao.ChainDao
 import jp.co.soramitsu.runtime.multiNetwork.chain.model.Chain
+import jp.co.soramitsu.runtime.multiNetwork.chain.model.reefChainId
 import jp.co.soramitsu.runtime.multiNetwork.toSyncIssue
 import jp.co.soramitsu.shared_utils.runtime.RuntimeSnapshot
 import kotlinx.coroutines.CoroutineScope
@@ -127,17 +127,19 @@ class RuntimeProvider(
                     runCatching { chainDao.getTypes(chainId) ?: throw ChainInfoNotInCacheException }
                         .getOrElse { throw ChainInfoNotInCacheException }
 
-                val runtime =
+                val runtime = if (chainId == reefChainId) {
+                    val defaultTypes =
+                        runCatching {
+                            chainDao.getTypes("default") ?: throw ChainInfoNotInCacheException
+                        }
+                            .getOrElse { throw ChainInfoNotInCacheException }
+                    runtimeFactory.constructRuntimeV13(metadataRaw, ownTypesRaw, defaultTypes)
+                } else {
                     runtimeFactory.constructRuntime(metadataRaw, ownTypesRaw, runtimeVersion)
-                if(chainId == "7834781d38e4798d548e34ec947d19deea29df148a7bf32484b7b24dacf8d4b7"){
-                    Log.d("&&&", "reef runtime construction: ${runtime.runtime}")
                 }
                 runtimeFlow.emit(runtime)
                 networkStateMixin.notifyChainSyncSuccess(chainId)
             }.onFailure {
-                if(chainId == "7834781d38e4798d548e34ec947d19deea29df148a7bf32484b7b24dacf8d4b7"){
-                    Log.d("&&&", "reef runtime construction failure: $it ${it.message}")
-                }
                 networkStateMixin.notifyChainSyncProblem(chain.toSyncIssue())
                 when (it) {
                     ChainInfoNotInCacheException -> runtimeSyncService.cacheNotFound(chainId)
diff --git a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/runtime/RuntimeSyncService.kt b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/runtime/RuntimeSyncService.kt
index 0e95d5881f..bed5f4e901 100644
--- a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/runtime/RuntimeSyncService.kt
+++ b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/runtime/RuntimeSyncService.kt
@@ -109,9 +109,6 @@ class RuntimeSyncService(
                     GetMetadataRequest,
                     mapper = pojo<String>().nonNull()
                 ).getOrNull()
-            if(chainId == "7834781d38e4798d548e34ec947d19deea29df148a7bf32484b7b24dacf8d4b7"){
-                Log.d("&&&", "reef metadata length: ${runtimeMetadata?.length}")
-            }
             runtimeMetadata?.let {
 
                 runtimeFilesCache.saveChainMetadata(chainId, runtimeMetadata)
@@ -140,13 +137,14 @@ class RuntimeSyncService(
 
     suspend fun syncTypes() {
         val types = typesFetcher.getTypes(BuildConfig.TYPES_URL)
+        val defaultTypes = typesFetcher.getTypes(BuildConfig.DEFAULT_V13_TYPES_URL)
         val array = Json.decodeFromString<JsonArray>(types)
         val chainIdToTypes =
             array.mapNotNull { element ->
                 val chainId =
                     element.jsonObject["chainId"]?.jsonPrimitive?.content ?: return@mapNotNull null
                 ChainTypesLocal(chainId, element.toString())
-            }
+            }.toMutableList().apply { add(ChainTypesLocal("default", defaultTypes)) }
         chainDao.insertTypes(chainIdToTypes)
     }
 

From 7f01ad63595ae4a66c4a6fb9d472af2431fc37a6 Mon Sep 17 00:00:00 2001
From: Deneath <lyazgindenis@gmail.com>
Date: Wed, 24 Jan 2024 18:07:45 +0700
Subject: [PATCH 12/35] clean code, add reef operations history

---
 .../historySource/HistorySourceProvider.kt    |  1 +
 .../data/historySource/ReefHistorySource.kt   | 93 +++++++++++++++++++
 .../network/model/SubstrateBalancesUtils.kt   | 46 ---------
 .../model/request/ReefHistoryRequest.kt       | 39 ++++++++
 .../model/response/ReefHistoryResponse.kt     | 30 ++++++
 .../network/subquery/OperationsHistoryApi.kt  |  8 ++
 .../multiNetwork/chain/ChainSpecificUtils.kt  | 20 ----
 .../runtime/multiNetwork/chain/Mappers.kt     |  2 +
 .../runtime/multiNetwork/chain/model/Chain.kt |  6 +-
 .../multiNetwork/runtime/RuntimeProvider.kt   |  2 +-
 10 files changed, 177 insertions(+), 70 deletions(-)
 create mode 100644 feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/historySource/ReefHistorySource.kt
 create mode 100644 feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/request/ReefHistoryRequest.kt
 create mode 100644 feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/response/ReefHistoryResponse.kt
 delete mode 100644 runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/ChainSpecificUtils.kt

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 ef2ad5a3a4..c560d874a7 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
@@ -26,6 +26,7 @@ class HistorySourceProvider(
             Chain.ExternalApi.Section.Type.ETHERSCAN -> EtherscanHistorySource(walletOperationsApi, historyUrl)
             Chain.ExternalApi.Section.Type.OKLINK -> OkLinkHistorySource(walletOperationsApi, historyUrl)
             Chain.ExternalApi.Section.Type.ZETA -> ZetaHistorySource(walletOperationsApi, historyUrl)
+            Chain.ExternalApi.Section.Type.REEF -> ReefHistorySource(walletOperationsApi, historyUrl)
             else -> null
         }
     }
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/historySource/ReefHistorySource.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/historySource/ReefHistorySource.kt
new file mode 100644
index 0000000000..d6494b7e70
--- /dev/null
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/historySource/ReefHistorySource.kt
@@ -0,0 +1,93 @@
+package jp.co.soramitsu.wallet.impl.data.historySource
+
+import android.os.Build
+import java.text.SimpleDateFormat
+import java.time.Instant
+import java.util.Locale
+import jp.co.soramitsu.common.data.model.CursorPage
+import jp.co.soramitsu.core.models.Asset
+import jp.co.soramitsu.runtime.multiNetwork.chain.model.Chain
+import jp.co.soramitsu.shared_utils.runtime.AccountId
+import jp.co.soramitsu.wallet.impl.data.network.model.request.ReefHistoryRequest
+import jp.co.soramitsu.wallet.impl.data.network.subquery.OperationsHistoryApi
+import jp.co.soramitsu.wallet.impl.domain.interfaces.TransactionFilter
+import jp.co.soramitsu.wallet.impl.domain.model.Operation
+
+class ReefHistorySource(
+    private val walletOperationsApi: OperationsHistoryApi,
+    private val url: String
+) : HistorySource {
+    override suspend fun getOperations(
+        pageSize: Int,
+        cursor: String?,
+        filters: Set<TransactionFilter>,
+        accountId: AccountId,
+        chain: Chain,
+        chainAsset: Asset,
+        accountAddress: String
+    ): CursorPage<Operation> {
+        val overridePageSize = 50
+        val offset = cursor?.toIntOrNull().takeIf { it != 0 }
+        val response = walletOperationsApi.getReefOperationsHistory(
+            url = url,
+            ReefHistoryRequest(
+                accountAddress = accountAddress,
+                overridePageSize,
+                offset.toString()
+            )
+        )
+        if (!filters.contains(TransactionFilter.TRANSFER)) {
+            return CursorPage(null, emptyList())
+        }
+        val operations = response.data.transfersConnection.edges.map { it.node }.map {
+            Operation(
+                id = it.extrinsic?.hash ?: it.id,
+                address = accountAddress,
+                time = parseTimeToMillis(it.timestamp),
+                chainAsset = chainAsset,
+                type = Operation.Type.Transfer(
+                    hash = it.extrinsic?.hash,
+                    myAddress = accountAddress,
+                    amount = it.amount,
+                    receiver = it.to.id,
+                    sender = it.from.id,
+                    status = Operation.Status.fromSuccess(it.success),
+                    fee = it.feeAmount
+                )
+            )
+        }
+        val pageInfo = response.data.transfersConnection.pageInfo
+        val nextCursor = if (pageInfo.hasNextPage && (pageInfo.endCursor.toIntOrNull()
+                ?: 0) >= overridePageSize
+        ) {
+            pageInfo.endCursor
+        } else {
+            null
+        }
+        return CursorPage(nextCursor, operations)
+    }
+
+    private fun TransactionFilter.isAppliedOrNull(filters: Collection<TransactionFilter>) = when {
+        this in filters -> true
+        else -> null
+    }
+
+    private val reefDateFormat by lazy {
+        SimpleDateFormat(
+            "yyyy-MM-dd'T'HH:mm:ss.SSSSSSZ",
+            Locale.getDefault()
+        )
+    }
+
+    private fun parseTimeToMillis(timestamp: String): Long {
+        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            Instant.parse(timestamp).toEpochMilli()
+        } else {
+            try {
+                reefDateFormat.parse(timestamp)?.time ?: 0
+            } catch (e: Exception) {
+                0
+            }
+        }
+    }
+}
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/SubstrateBalancesUtils.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/SubstrateBalancesUtils.kt
index d667fb410d..ebc8e194f3 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/SubstrateBalancesUtils.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/SubstrateBalancesUtils.kt
@@ -1,26 +1,14 @@
 package jp.co.soramitsu.wallet.impl.data.network.model
 
 import android.util.Log
-import java.math.BigInteger
-import jp.co.soramitsu.common.data.network.runtime.binding.AccountData
-import jp.co.soramitsu.common.data.network.runtime.binding.AccountInfo
 import jp.co.soramitsu.common.data.network.runtime.binding.AssetBalanceData
 import jp.co.soramitsu.common.data.network.runtime.binding.EmptyBalance
-import jp.co.soramitsu.common.data.network.runtime.binding.bindNonce
-import jp.co.soramitsu.common.data.network.runtime.binding.cast
 import jp.co.soramitsu.common.utils.Modules
-import jp.co.soramitsu.common.utils.failure
-import jp.co.soramitsu.common.utils.orZero
 import jp.co.soramitsu.common.utils.system
 import jp.co.soramitsu.common.utils.tokens
 import jp.co.soramitsu.core.models.Asset
 import jp.co.soramitsu.core.models.ChainAssetType
-import jp.co.soramitsu.core.runtime.storage.returnType
-import jp.co.soramitsu.runtime.multiNetwork.chain.ReefBalance
-import jp.co.soramitsu.runtime.multiNetwork.chain.model.reefChainId
 import jp.co.soramitsu.shared_utils.runtime.RuntimeSnapshot
-import jp.co.soramitsu.shared_utils.runtime.definitions.types.composite.Struct
-import jp.co.soramitsu.shared_utils.runtime.definitions.types.fromHexOrNull
 import jp.co.soramitsu.shared_utils.runtime.metadata.module
 import jp.co.soramitsu.shared_utils.runtime.metadata.storage
 import jp.co.soramitsu.shared_utils.runtime.metadata.storageKey
@@ -81,9 +69,6 @@ fun handleBalanceResponse(
     scale: String?
 ): Result<AssetBalanceData> {
     return runCatching {
-        if (asset.chainId == reefChainId) {
-            return bindReefAccountInfo(runtime, scale)
-        }
         when (asset.typeExtra) {
             null,
             ChainAssetType.Normal,
@@ -118,34 +103,3 @@ fun handleBalanceResponse(
         }
     }
 }
-
-private fun bindReefAccountInfo(runtime: RuntimeSnapshot, scale: String?): Result<AccountInfo> {
-    return runCatching {
-        val type = runtime.metadata.system().storage("Account")
-            .returnType()
-
-        val dynamicInstance = type.fromHexOrNull(
-            runtime,
-            scale ?: return Result.failure("Reef system.Account returned null hex result")
-        ).cast<Struct.Instance>()
-
-        AccountInfo(
-            nonce = bindNonce(dynamicInstance["nonce"]),
-            data = dynamicInstance.get<Struct.Instance?>("data")
-                .let {
-                    val freeBalance = ReefBalance((it?.get("free") as? BigInteger).orZero())
-                    val reservedBalance = ReefBalance((it?.get("reserved") as? BigInteger).orZero())
-                    val miscFrozenBalance =
-                        ReefBalance((it?.get("miscFrozen") as? BigInteger).orZero())
-                    val feeFrozenBalance =
-                        ReefBalance((it?.get("feeFrozen") as? BigInteger).orZero())
-                    AccountData(
-                        free = freeBalance.planks,
-                        reserved = reservedBalance.planks,
-                        miscFrozen = miscFrozenBalance.planks,
-                        feeFrozen = feeFrozenBalance.planks
-                    )
-                }
-        )
-    }
-}
\ No newline at end of file
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/request/ReefHistoryRequest.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/request/ReefHistoryRequest.kt
new file mode 100644
index 0000000000..64a5883ae4
--- /dev/null
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/request/ReefHistoryRequest.kt
@@ -0,0 +1,39 @@
+package jp.co.soramitsu.wallet.impl.data.network.model.request
+
+class ReefHistoryRequest(
+    accountAddress: String,
+    limit: Int = 50,
+    offset: String? = null
+) {
+    val query = """
+query MyQuery {
+  transfersConnection(where: {AND: [{type_eq: Native}, {OR: [{from: {id_eq: "$accountAddress"}}, {to: {id_eq: "$accountAddress"}}]}]}, orderBy: timestamp_DESC, first: $limit, after: $offset) {
+    edges {
+      node {
+        id
+        amount
+        feeAmount
+        type
+        timestamp
+        success
+        denom
+        to {
+          id
+        }
+        from {
+          id
+        }
+        extrinsic {
+          hash
+        }
+      }
+    }
+    pageInfo {
+      endCursor
+      hasNextPage
+      startCursor
+    }
+  }
+}
+""".trimIndent()
+}
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/response/ReefHistoryResponse.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/response/ReefHistoryResponse.kt
new file mode 100644
index 0000000000..ae6a33066b
--- /dev/null
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/response/ReefHistoryResponse.kt
@@ -0,0 +1,30 @@
+package jp.co.soramitsu.wallet.impl.data.network.model.response
+
+import java.math.BigInteger
+
+data class ReefHistoryResponse(val transfersConnection: ReefElementsConnection)
+
+class ReefElementsConnection(
+    val pageInfo: SubsquidPageInfo,
+    val edges: List<ReefHistoryEdge>
+)
+
+class ReefHistoryEdge(val node: ReefHistoryNode)
+class ReefHistoryNode(
+    val id: String,
+    val amount: BigInteger,
+    val feeAmount: BigInteger,
+    val type: String,
+    val timestamp: String,
+    val success: Boolean,
+    val denom: String,
+    val to: ReefAddress,
+    val from: ReefAddress,
+    val extrinsic: ReefExtrinsic?
+)
+
+class ReefExtrinsic(val hash: String)
+
+class ReefAddress(
+    val id: String
+)
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/subquery/OperationsHistoryApi.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/subquery/OperationsHistoryApi.kt
index 407c3d627d..fada86b5dd 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/subquery/OperationsHistoryApi.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/subquery/OperationsHistoryApi.kt
@@ -5,11 +5,13 @@ import jp.co.soramitsu.common.data.network.subquery.GiantsquidResponse
 import jp.co.soramitsu.common.data.network.subquery.SubQueryResponse
 import jp.co.soramitsu.common.data.network.subquery.SubsquidResponse
 import jp.co.soramitsu.wallet.impl.data.network.model.request.GiantsquidHistoryRequest
+import jp.co.soramitsu.wallet.impl.data.network.model.request.ReefHistoryRequest
 import jp.co.soramitsu.wallet.impl.data.network.model.request.SubqueryHistoryRequest
 import jp.co.soramitsu.wallet.impl.data.network.model.request.SubsquidHistoryRequest
 import jp.co.soramitsu.wallet.impl.data.network.model.response.EtherscanHistoryResponse
 import jp.co.soramitsu.wallet.impl.data.network.model.response.GiantsquidHistoryResponse
 import jp.co.soramitsu.wallet.impl.data.network.model.response.OkLinkHistoryResponse
+import jp.co.soramitsu.wallet.impl.data.network.model.response.ReefHistoryResponse
 import jp.co.soramitsu.wallet.impl.data.network.model.response.SubqueryHistoryElementResponse
 import jp.co.soramitsu.wallet.impl.data.network.model.response.SubsquidHistoryElementsConnectionResponse
 import jp.co.soramitsu.wallet.impl.data.network.model.response.ZetaHistoryResponse
@@ -65,4 +67,10 @@ interface OperationsHistoryApi {
     suspend fun getZetaOperationsHistory(
         @Url url: String
     ): ZetaHistoryResponse
+
+    @POST
+    suspend fun getReefOperationsHistory(
+        @Url url: String,
+        @Body body: ReefHistoryRequest
+    ): SubsquidResponse<ReefHistoryResponse>
 }
\ No newline at end of file
diff --git a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/ChainSpecificUtils.kt b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/ChainSpecificUtils.kt
deleted file mode 100644
index a0618b24a8..0000000000
--- a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/ChainSpecificUtils.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-package jp.co.soramitsu.runtime.multiNetwork.chain
-
-import io.emeraldpay.polkaj.scale.ScaleCodecReader
-import java.math.BigInteger
-import java.nio.ByteOrder
-import jp.co.soramitsu.shared_utils.extensions.fromUnsignedBytes
-import jp.co.soramitsu.shared_utils.scale.dataType.uint128
-import jp.co.soramitsu.shared_utils.scale.utils.toUnsignedBytes
-
-@JvmInline
-value class ReefBalance(val value: BigInteger) {
-    val planks: BigInteger
-        get() {
-            val bytes = value.toUnsignedBytes().fromUnsignedBytes(ByteOrder.LITTLE_ENDIAN).toByteArray()
-            val newArray = ByteArray(16)
-            bytes.copyInto(newArray)
-            val reader = ScaleCodecReader(newArray)
-            return uint128.read(reader)
-        }
-}
\ No newline at end of file
diff --git a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/Mappers.kt b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/Mappers.kt
index 3a45f66853..7c11dcae54 100644
--- a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/Mappers.kt
+++ b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/Mappers.kt
@@ -31,6 +31,7 @@ private fun mapSectionTypeRemoteToSectionType(section: String) = when (section)
     "etherscan" -> Chain.ExternalApi.Section.Type.ETHERSCAN
     "oklink" -> Chain.ExternalApi.Section.Type.OKLINK
     "zeta" -> Chain.ExternalApi.Section.Type.ZETA
+    "reef" -> Chain.ExternalApi.Section.Type.REEF
     else -> Chain.ExternalApi.Section.Type.UNKNOWN
 }
 
@@ -40,6 +41,7 @@ private fun mapExplorerTypeRemoteToExplorerType(explorer: String) = when (explor
     "etherscan" -> Chain.Explorer.Type.ETHERSCAN
     "oklink" -> Chain.Explorer.Type.OKLINK
     "zeta" -> Chain.Explorer.Type.ZETA
+    "reef" -> Chain.Explorer.Type.REEF
     else -> Chain.Explorer.Type.UNKNOWN
 }
 
diff --git a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/model/Chain.kt b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/model/Chain.kt
index 2525a91b85..f1a16f545a 100644
--- a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/model/Chain.kt
+++ b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/model/Chain.kt
@@ -64,16 +64,16 @@ data class Chain(
     ) {
         data class Section(val type: Type, val url: String) {
             enum class Type {
-                SUBQUERY, SORA, SUBSQUID, GIANTSQUID, ETHERSCAN, OKLINK, ZETA, UNKNOWN, GITHUB;
+                SUBQUERY, SORA, SUBSQUID, GIANTSQUID, ETHERSCAN, OKLINK, ZETA, REEF, UNKNOWN, GITHUB;
 
-                fun isHistory() = this in listOf(SUBQUERY, SORA, SUBSQUID, GIANTSQUID, ETHERSCAN, OKLINK, ZETA)
+                fun isHistory() = this in listOf(SUBQUERY, SORA, SUBSQUID, GIANTSQUID, ETHERSCAN, OKLINK, ZETA, REEF)
             }
         }
     }
 
     data class Explorer(val type: Type, val types: List<String>, val url: String) {
         enum class Type {
-            POLKASCAN, SUBSCAN, ETHERSCAN, OKLINK, ZETA, UNKNOWN;
+            POLKASCAN, SUBSCAN, ETHERSCAN, OKLINK, ZETA, REEF, UNKNOWN;
 
             val capitalizedName: String = name.lowercase().replaceFirstChar { it.titlecase() }
         }
diff --git a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/runtime/RuntimeProvider.kt b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/runtime/RuntimeProvider.kt
index bcc9cf0ae8..799235418c 100644
--- a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/runtime/RuntimeProvider.kt
+++ b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/runtime/RuntimeProvider.kt
@@ -133,7 +133,7 @@ class RuntimeProvider(
                             chainDao.getTypes("default") ?: throw ChainInfoNotInCacheException
                         }
                             .getOrElse { throw ChainInfoNotInCacheException }
-                    runtimeFactory.constructRuntimeV13(metadataRaw, ownTypesRaw, defaultTypes)
+                    runtimeFactory.constructRuntimeV13(metadataRaw, ownTypesRaw, defaultTypes, runtimeVersion)
                 } else {
                     runtimeFactory.constructRuntime(metadataRaw, ownTypesRaw, runtimeVersion)
                 }

From 62d7f69e8f7f737ce46c89c698baf840dae4e411 Mon Sep 17 00:00:00 2001
From: Deneath <lyazgindenis@gmail.com>
Date: Thu, 25 Jan 2024 17:23:49 +0700
Subject: [PATCH 13/35] add reef staking rewards

---
 .../subquery/ReefStakingRewardsResponse.kt    | 96 +++++++++++++++++++
 .../impl/data/network/subquery/StakingApi.kt  |  8 ++
 .../request/ReefStakingRewardsRequest.kt      | 26 +++++
 .../SubqueryStakingRewardsDataSource.kt       | 22 +++++
 4 files changed, 152 insertions(+)
 create mode 100644 common/src/main/java/jp/co/soramitsu/common/data/network/subquery/ReefStakingRewardsResponse.kt
 create mode 100644 feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/data/network/subquery/request/ReefStakingRewardsRequest.kt

diff --git a/common/src/main/java/jp/co/soramitsu/common/data/network/subquery/ReefStakingRewardsResponse.kt b/common/src/main/java/jp/co/soramitsu/common/data/network/subquery/ReefStakingRewardsResponse.kt
new file mode 100644
index 0000000000..64cc9d51c7
--- /dev/null
+++ b/common/src/main/java/jp/co/soramitsu/common/data/network/subquery/ReefStakingRewardsResponse.kt
@@ -0,0 +1,96 @@
+package jp.co.soramitsu.common.data.network.subquery
+
+import java.math.BigInteger
+
+class ReefStakingRewardsResponse (
+    val stakingsConnection: ReefRewardsConnection
+)
+
+class SubsquidPageInfo(
+    val hasNextPage: Boolean,
+    val endCursor: String
+)
+
+class ReefRewardsConnection(
+    val edges: List<ReefRewardsEdge>,
+    val pageInfo: SubsquidPageInfo
+)
+class ReefRewardsEdge(
+    val node: ReefRewardsNode
+)
+class ReefRewardsNode(
+    val id: String,
+    val type: String,
+    val amount: BigInteger,
+    val timestamp: String,
+    val signer: ReefAddress
+)
+
+class ReefAddress(
+    val id: String
+)
+//"stakingsConnection": {
+//            "edges": [
+//                {
+//                    "node": {
+//                        "id": "0008435587-000012-2d7db",
+//                        "type": "Reward",
+//                        "amount": "0",
+//                        "timestamp": "2024-01-24T13:36:30.000000Z",
+//                        "signer": {
+//                            "id": "5GecoStYi2bHzKz6LwE2LWa8MWJxaZYAGjx2WeH8r4RTnQ6e"
+//                        }
+//                    }
+//                },
+//                {
+//                    "node": {
+//                        "id": "0008435117-000011-2e965",
+//                        "type": "Reward",
+//                        "amount": "306857767686205",
+//                        "timestamp": "2024-01-24T12:18:10.000000Z",
+//                        "signer": {
+//                            "id": "5GecoStYi2bHzKz6LwE2LWa8MWJxaZYAGjx2WeH8r4RTnQ6e"
+//                        }
+//                    }
+//                },
+//                {
+//                    "node": {
+//                        "id": "0008427594-000032-42e47",
+//                        "type": "Reward",
+//                        "amount": "0",
+//                        "timestamp": "2024-01-23T15:24:20.000000Z",
+//                        "signer": {
+//                            "id": "5GecoStYi2bHzKz6LwE2LWa8MWJxaZYAGjx2WeH8r4RTnQ6e"
+//                        }
+//                    }
+//                },
+//                {
+//                    "node": {
+//                        "id": "0008427594-000015-42e47",
+//                        "type": "Reward",
+//                        "amount": "0",
+//                        "timestamp": "2024-01-23T15:24:20.000000Z",
+//                        "signer": {
+//                            "id": "5GecoStYi2bHzKz6LwE2LWa8MWJxaZYAGjx2WeH8r4RTnQ6e"
+//                        }
+//                    }
+//                },
+//                {
+//                    "node": {
+//                        "id": "0008427594-000024-42e47",
+//                        "type": "Reward",
+//                        "amount": "0",
+//                        "timestamp": "2024-01-23T15:24:20.000000Z",
+//                        "signer": {
+//                            "id": "5GecoStYi2bHzKz6LwE2LWa8MWJxaZYAGjx2WeH8r4RTnQ6e"
+//                        }
+//                    }
+//                }
+//            ],
+//            "totalCount": 198,
+//            "pageInfo": {
+//                "endCursor": "5",
+//                "hasNextPage": true
+//            }
+//        }
+//    }
diff --git a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/data/network/subquery/StakingApi.kt b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/data/network/subquery/StakingApi.kt
index c0074d3ded..32678b0eb1 100644
--- a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/data/network/subquery/StakingApi.kt
+++ b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/data/network/subquery/StakingApi.kt
@@ -2,6 +2,7 @@ package jp.co.soramitsu.staking.impl.data.network.subquery
 
 import jp.co.soramitsu.common.data.network.subquery.EraValidatorInfoQueryResponse
 import jp.co.soramitsu.common.data.network.subquery.GiantsquidRewardAmountResponse
+import jp.co.soramitsu.common.data.network.subquery.ReefStakingRewardsResponse
 import jp.co.soramitsu.common.data.network.subquery.SoraEraInfoValidatorResponse
 import jp.co.soramitsu.common.data.network.subquery.StakingCollatorsApyResponse
 import jp.co.soramitsu.common.data.network.subquery.StakingHistoryRemote
@@ -16,6 +17,7 @@ import jp.co.soramitsu.common.data.network.subquery.SubsquidRewardResponse
 import jp.co.soramitsu.common.data.network.subquery.SubsquidSoraStakingRewards
 import jp.co.soramitsu.common.data.network.subquery.TransactionHistoryRemote
 import jp.co.soramitsu.staking.impl.data.network.subquery.request.GiantsquidRewardAmountRequest
+import jp.co.soramitsu.staking.impl.data.network.subquery.request.ReefStakingRewardsRequest
 import jp.co.soramitsu.staking.impl.data.network.subquery.request.StakingAllCollatorsApyRequest
 import jp.co.soramitsu.staking.impl.data.network.subquery.request.StakingCollatorsApyRequest
 import jp.co.soramitsu.staking.impl.data.network.subquery.request.StakingDelegatorHistoryRequest
@@ -118,4 +120,10 @@ interface StakingApi {
         @Url url: String,
         @Body body: SubsquidSoraStakingRewardsRequest
     ): SubsquidResponse<SubsquidSoraStakingRewards>
+
+    @POST
+    suspend fun getReefRewards(
+        @Url url: String,
+        @Body body: ReefStakingRewardsRequest
+    ): SubsquidResponse<ReefStakingRewardsResponse>
 }
diff --git a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/data/network/subquery/request/ReefStakingRewardsRequest.kt b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/data/network/subquery/request/ReefStakingRewardsRequest.kt
new file mode 100644
index 0000000000..adfeb278ba
--- /dev/null
+++ b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/data/network/subquery/request/ReefStakingRewardsRequest.kt
@@ -0,0 +1,26 @@
+package jp.co.soramitsu.staking.impl.data.network.subquery.request
+
+class ReefStakingRewardsRequest(address: String, pageSize: Int = 100, offset: String? = null) {
+    val query = """
+        query MyQuery {
+          stakingsConnection(orderBy: timestamp_DESC, where: {signer: {id_eq: "$address"}}, first: $pageSize, after: $offset) {
+                edges {
+                  node {
+                    id
+                    type
+                    amount
+                    timestamp
+                    signer {
+                      id
+                    }
+                  }
+                }
+                totalCount
+                pageInfo {
+                  endCursor
+                  hasNextPage
+                }
+    }
+  }
+    """.trimIndent()
+}
\ No newline at end of file
diff --git a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/data/repository/datasource/SubqueryStakingRewardsDataSource.kt b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/data/repository/datasource/SubqueryStakingRewardsDataSource.kt
index 2cfdad56d5..e3d0059eb0 100644
--- a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/data/repository/datasource/SubqueryStakingRewardsDataSource.kt
+++ b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/data/repository/datasource/SubqueryStakingRewardsDataSource.kt
@@ -1,6 +1,8 @@
 package jp.co.soramitsu.staking.impl.data.repository.datasource
 
+import java.math.BigInteger
 import jp.co.soramitsu.common.base.errors.RewardsNotSupportedWarning
+import jp.co.soramitsu.common.data.network.subquery.ReefRewardsNode
 import jp.co.soramitsu.common.utils.orZero
 import jp.co.soramitsu.common.utils.sumByBigDecimal
 import jp.co.soramitsu.common.utils.sumByBigInteger
@@ -19,6 +21,7 @@ import jp.co.soramitsu.staking.impl.data.mappers.mapSubqueryHistoryToTotalReward
 import jp.co.soramitsu.staking.impl.data.mappers.mapTotalRewardLocalToTotalReward
 import jp.co.soramitsu.staking.impl.data.network.subquery.StakingApi
 import jp.co.soramitsu.staking.impl.data.network.subquery.request.GiantsquidRewardAmountRequest
+import jp.co.soramitsu.staking.impl.data.network.subquery.request.ReefStakingRewardsRequest
 import jp.co.soramitsu.staking.impl.data.network.subquery.request.StakingSumRewardRequest
 import jp.co.soramitsu.staking.impl.data.network.subquery.request.SubsquidEthRewardAmountRequest
 import jp.co.soramitsu.staking.impl.data.network.subquery.request.SubsquidRelayRewardAmountRequest
@@ -73,6 +76,10 @@ class SubqueryStakingRewardsDataSource(
                 syncGiantsquidRelay(stakingUrl, accountAddress)
             }
 
+            stakingType == Chain.ExternalApi.Section.Type.REEF -> {
+                syncReefRewards(stakingUrl, accountAddress)
+            }
+
             else -> throw RewardsNotSupportedWarning()
         }
     }
@@ -106,6 +113,21 @@ class SubqueryStakingRewardsDataSource(
         stakingTotalRewardDao.insert(TotalRewardLocal(accountAddress, totalInPlanks))
     }
 
+    private suspend fun syncReefRewards(stakingUrl: String, accountAddress: String) {
+        var hasNextPage = true
+        var nextCursor: String? = null
+        var rewardsTotal = BigInteger.ZERO
+
+        while (hasNextPage) {
+            val response = stakingApi.getReefRewards(stakingUrl, ReefStakingRewardsRequest(accountAddress, offset = nextCursor?.let { "\"$it\"" }))
+            hasNextPage = response.data.stakingsConnection.pageInfo.hasNextPage
+            nextCursor = response.data.stakingsConnection.pageInfo.endCursor
+            rewardsTotal += response.data.stakingsConnection.edges.map { it.node }.sumByBigInteger { it.amount }
+        }
+
+        stakingTotalRewardDao.insert(TotalRewardLocal(accountAddress, rewardsTotal))
+    }
+
     private suspend fun syncSubquery(stakingUrl: String, accountAddress: String) = withContext(Dispatchers.IO) {
         val r = stakingApi.getSumReward(
             stakingUrl,

From c3efae82e7ddd976f7e092a23f6b9a18cc615b7c Mon Sep 17 00:00:00 2001
From: Deneath <lyazgindenis@gmail.com>
Date: Thu, 25 Jan 2024 18:47:25 +0700
Subject: [PATCH 14/35] load reef staking rewards with transfers

---
 .../subquery/ReefStakingRewardsResponse.kt    |  67 +----------
 .../request/ReefStakingRewardsRequest.kt      |   2 +-
 .../data/historySource/ReefHistorySource.kt   |  79 ++++++++-----
 .../model/request/ReefHistoryRequest.kt       | 106 +++++++++++++-----
 .../model/response/ReefHistoryResponse.kt     |   7 +-
 .../network/subquery/OperationsHistoryApi.kt  |   1 +
 6 files changed, 136 insertions(+), 126 deletions(-)

diff --git a/common/src/main/java/jp/co/soramitsu/common/data/network/subquery/ReefStakingRewardsResponse.kt b/common/src/main/java/jp/co/soramitsu/common/data/network/subquery/ReefStakingRewardsResponse.kt
index 64cc9d51c7..5d76f8c587 100644
--- a/common/src/main/java/jp/co/soramitsu/common/data/network/subquery/ReefStakingRewardsResponse.kt
+++ b/common/src/main/java/jp/co/soramitsu/common/data/network/subquery/ReefStakingRewardsResponse.kt
@@ -28,69 +28,4 @@ class ReefRewardsNode(
 
 class ReefAddress(
     val id: String
-)
-//"stakingsConnection": {
-//            "edges": [
-//                {
-//                    "node": {
-//                        "id": "0008435587-000012-2d7db",
-//                        "type": "Reward",
-//                        "amount": "0",
-//                        "timestamp": "2024-01-24T13:36:30.000000Z",
-//                        "signer": {
-//                            "id": "5GecoStYi2bHzKz6LwE2LWa8MWJxaZYAGjx2WeH8r4RTnQ6e"
-//                        }
-//                    }
-//                },
-//                {
-//                    "node": {
-//                        "id": "0008435117-000011-2e965",
-//                        "type": "Reward",
-//                        "amount": "306857767686205",
-//                        "timestamp": "2024-01-24T12:18:10.000000Z",
-//                        "signer": {
-//                            "id": "5GecoStYi2bHzKz6LwE2LWa8MWJxaZYAGjx2WeH8r4RTnQ6e"
-//                        }
-//                    }
-//                },
-//                {
-//                    "node": {
-//                        "id": "0008427594-000032-42e47",
-//                        "type": "Reward",
-//                        "amount": "0",
-//                        "timestamp": "2024-01-23T15:24:20.000000Z",
-//                        "signer": {
-//                            "id": "5GecoStYi2bHzKz6LwE2LWa8MWJxaZYAGjx2WeH8r4RTnQ6e"
-//                        }
-//                    }
-//                },
-//                {
-//                    "node": {
-//                        "id": "0008427594-000015-42e47",
-//                        "type": "Reward",
-//                        "amount": "0",
-//                        "timestamp": "2024-01-23T15:24:20.000000Z",
-//                        "signer": {
-//                            "id": "5GecoStYi2bHzKz6LwE2LWa8MWJxaZYAGjx2WeH8r4RTnQ6e"
-//                        }
-//                    }
-//                },
-//                {
-//                    "node": {
-//                        "id": "0008427594-000024-42e47",
-//                        "type": "Reward",
-//                        "amount": "0",
-//                        "timestamp": "2024-01-23T15:24:20.000000Z",
-//                        "signer": {
-//                            "id": "5GecoStYi2bHzKz6LwE2LWa8MWJxaZYAGjx2WeH8r4RTnQ6e"
-//                        }
-//                    }
-//                }
-//            ],
-//            "totalCount": 198,
-//            "pageInfo": {
-//                "endCursor": "5",
-//                "hasNextPage": true
-//            }
-//        }
-//    }
+)
\ No newline at end of file
diff --git a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/data/network/subquery/request/ReefStakingRewardsRequest.kt b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/data/network/subquery/request/ReefStakingRewardsRequest.kt
index adfeb278ba..883ec80c14 100644
--- a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/data/network/subquery/request/ReefStakingRewardsRequest.kt
+++ b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/data/network/subquery/request/ReefStakingRewardsRequest.kt
@@ -3,7 +3,7 @@ package jp.co.soramitsu.staking.impl.data.network.subquery.request
 class ReefStakingRewardsRequest(address: String, pageSize: Int = 100, offset: String? = null) {
     val query = """
         query MyQuery {
-          stakingsConnection(orderBy: timestamp_DESC, where: {signer: {id_eq: "$address"}}, first: $pageSize, after: $offset) {
+          stakingsConnection(orderBy: timestamp_DESC, where: {AND: {signer: {id_eq: "$address"}, amount_gt: "0"}}, first: $pageSize, after: $offset) {
                 edges {
                   node {
                     id
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/historySource/ReefHistorySource.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/historySource/ReefHistorySource.kt
index d6494b7e70..9b49ba872b 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/historySource/ReefHistorySource.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/historySource/ReefHistorySource.kt
@@ -9,6 +9,7 @@ import jp.co.soramitsu.core.models.Asset
 import jp.co.soramitsu.runtime.multiNetwork.chain.model.Chain
 import jp.co.soramitsu.shared_utils.runtime.AccountId
 import jp.co.soramitsu.wallet.impl.data.network.model.request.ReefHistoryRequest
+import jp.co.soramitsu.wallet.impl.data.network.model.request.ReefRequestBuilder
 import jp.co.soramitsu.wallet.impl.data.network.subquery.OperationsHistoryApi
 import jp.co.soramitsu.wallet.impl.domain.interfaces.TransactionFilter
 import jp.co.soramitsu.wallet.impl.domain.model.Operation
@@ -28,43 +29,71 @@ class ReefHistorySource(
     ): CursorPage<Operation> {
         val overridePageSize = 50
         val offset = cursor?.toIntOrNull().takeIf { it != 0 }
+
         val response = walletOperationsApi.getReefOperationsHistory(
             url = url,
-            ReefHistoryRequest(
+            ReefRequestBuilder(
+                filters,
                 accountAddress = accountAddress,
                 overridePageSize,
                 offset.toString()
-            )
+            ).buildRequest()
         )
-        if (!filters.contains(TransactionFilter.TRANSFER)) {
-            return CursorPage(null, emptyList())
+        val operations = mutableListOf<Operation>()
+        if(filters.contains(TransactionFilter.TRANSFER)) {
+            operations.addAll(response.data.transfersConnection.edges.map { it.node }.map {
+                Operation(
+                    id = it.extrinsic?.hash ?: it.id,
+                    address = accountAddress,
+                    time = parseTimeToMillis(it.timestamp),
+                    chainAsset = chainAsset,
+                    type = Operation.Type.Transfer(
+                        hash = it.extrinsic?.hash,
+                        myAddress = accountAddress,
+                        amount = it.amount,
+                        receiver = it.to.id,
+                        sender = it.from.id,
+                        status = Operation.Status.fromSuccess(it.success),
+                        fee = it.feeAmount
+                    )
+                )
+            })
         }
-        val operations = response.data.transfersConnection.edges.map { it.node }.map {
-            Operation(
-                id = it.extrinsic?.hash ?: it.id,
-                address = accountAddress,
-                time = parseTimeToMillis(it.timestamp),
-                chainAsset = chainAsset,
-                type = Operation.Type.Transfer(
-                    hash = it.extrinsic?.hash,
-                    myAddress = accountAddress,
-                    amount = it.amount,
-                    receiver = it.to.id,
-                    sender = it.from.id,
-                    status = Operation.Status.fromSuccess(it.success),
-                    fee = it.feeAmount
+        if(filters.contains(TransactionFilter.REWARD)) {
+            operations.addAll(response.data.stakingsConnection.edges.map { it.node }.map {
+                Operation(
+                    id = it.id,
+                    address = accountAddress,
+                    time = parseTimeToMillis(it.timestamp),
+                    chainAsset = chainAsset,
+                    type = Operation.Type.Reward(
+                        amount = it.amount,
+                        isReward = true,
+                        era = 0,
+                        validator = null
+                    )
                 )
-            )
+            })
         }
-        val pageInfo = response.data.transfersConnection.pageInfo
-        val nextCursor = if (pageInfo.hasNextPage && (pageInfo.endCursor.toIntOrNull()
-                ?: 0) >= overridePageSize
-        ) {
-            pageInfo.endCursor
+
+        val transfersPageInfo = response.data.transfersConnection.pageInfo
+        val rewardsPageInfo = response.data.stakingsConnection.pageInfo
+
+        val shouldLoadTransfersNextPage = transfersPageInfo.hasNextPage
+        val shouldLoadRewardsNextPage = rewardsPageInfo.hasNextPage
+
+        val hasNextPage = shouldLoadTransfersNextPage || shouldLoadRewardsNextPage
+
+        val nextCursor = if(hasNextPage) {
+            val transfersOffset = transfersPageInfo.endCursor.toIntOrNull() ?: 0
+            val rewardsOffset = rewardsPageInfo.endCursor.toIntOrNull() ?: 0
+            val nextOffset = maxOf(transfersOffset, rewardsOffset)
+            if(nextOffset >= overridePageSize) nextOffset.toString() else null
         } else {
             null
         }
-        return CursorPage(nextCursor, operations)
+
+        return CursorPage(nextCursor, operations.sortedByDescending { it.time })
     }
 
     private fun TransactionFilter.isAppliedOrNull(filters: Collection<TransactionFilter>) = when {
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/request/ReefHistoryRequest.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/request/ReefHistoryRequest.kt
index 64a5883ae4..2c8f1fd63c 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/request/ReefHistoryRequest.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/request/ReefHistoryRequest.kt
@@ -1,39 +1,85 @@
 package jp.co.soramitsu.wallet.impl.data.network.model.request
 
-class ReefHistoryRequest(
-    accountAddress: String,
-    limit: Int = 50,
-    offset: String? = null
+import jp.co.soramitsu.wallet.impl.domain.interfaces.TransactionFilter
+
+class ReefRequestBuilder(
+    private val filters: Set<TransactionFilter>,
+    private val accountAddress: String,
+    private val limit: Int = 50,
+    private val transfersOffset: String? = null,
+    private val rewardsOffset: String? = null
 ) {
-    val query = """
-query MyQuery {
-  transfersConnection(where: {AND: [{type_eq: Native}, {OR: [{from: {id_eq: "$accountAddress"}}, {to: {id_eq: "$accountAddress"}}]}]}, orderBy: timestamp_DESC, first: $limit, after: $offset) {
-    edges {
-      node {
-        id
-        amount
-        feeAmount
-        type
-        timestamp
-        success
-        denom
-        to {
-          id
+    fun buildRequest(): ReefHistoryRequest {
+        val query = StringBuilder()
+        if (filters.contains(TransactionFilter.TRANSFER)) {
+            query.append(
+                """
+                transfersConnection(where: {AND: [{type_eq: Native}, {OR: [{from: {id_eq: "$accountAddress"}}, {to: {id_eq: "$accountAddress"}}]}]}, orderBy: timestamp_DESC, first: $limit, after: $transfersOffset) {
+                    edges {
+                      node {
+                        id
+                        amount
+                        feeAmount
+                        type
+                        timestamp
+                        success
+                        denom
+                        to {
+                          id
+                        }
+                        from {
+                          id
+                        }
+                        extrinsic {
+                          hash
+                        }
+                      }
+                    }
+                    pageInfo {
+                      endCursor
+                      hasNextPage
+                      startCursor
+                    }
+                  }
+            """.trimIndent()
+            )
         }
-        from {
-          id
+        if (filters.contains(TransactionFilter.REWARD)) {
+            query.append(
+                """
+                stakingsConnection(orderBy: timestamp_DESC, where: {AND: {signer: {id_eq: "$accountAddress"}, amount_gt: "0"}}, first: $limit, after: $rewardsOffset) {
+                    edges {
+                      node {
+                        id
+                        type
+                        amount
+                        timestamp
+                        signer {
+                          id
+                        }
+                      }
+                    }
+                    totalCount
+                    pageInfo {
+                      endCursor
+                      hasNextPage
+                    }
+                }
+            """.trimIndent()
+            )
         }
-        extrinsic {
-          hash
-        }
-      }
-    }
-    pageInfo {
-      endCursor
-      hasNextPage
-      startCursor
+
+        return ReefHistoryRequest(query.toString())
     }
-  }
+
+}
+
+class ReefHistoryRequest(
+    query: String
+) {
+    val query = """
+query MyQuery {
+  $query
 }
 """.trimIndent()
 }
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/response/ReefHistoryResponse.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/response/ReefHistoryResponse.kt
index ae6a33066b..8947fc4b09 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/response/ReefHistoryResponse.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/response/ReefHistoryResponse.kt
@@ -1,8 +1,10 @@
 package jp.co.soramitsu.wallet.impl.data.network.model.response
 
 import java.math.BigInteger
+import jp.co.soramitsu.common.data.network.subquery.ReefAddress
+import jp.co.soramitsu.common.data.network.subquery.ReefRewardsConnection
 
-data class ReefHistoryResponse(val transfersConnection: ReefElementsConnection)
+data class ReefHistoryResponse(val transfersConnection: ReefElementsConnection, val stakingsConnection: ReefRewardsConnection)
 
 class ReefElementsConnection(
     val pageInfo: SubsquidPageInfo,
@@ -25,6 +27,3 @@ class ReefHistoryNode(
 
 class ReefExtrinsic(val hash: String)
 
-class ReefAddress(
-    val id: String
-)
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/subquery/OperationsHistoryApi.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/subquery/OperationsHistoryApi.kt
index fada86b5dd..bca81368f3 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/subquery/OperationsHistoryApi.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/subquery/OperationsHistoryApi.kt
@@ -2,6 +2,7 @@ package jp.co.soramitsu.wallet.impl.data.network.subquery
 
 import jp.co.soramitsu.common.BuildConfig
 import jp.co.soramitsu.common.data.network.subquery.GiantsquidResponse
+import jp.co.soramitsu.common.data.network.subquery.ReefStakingRewardsResponse
 import jp.co.soramitsu.common.data.network.subquery.SubQueryResponse
 import jp.co.soramitsu.common.data.network.subquery.SubsquidResponse
 import jp.co.soramitsu.wallet.impl.data.network.model.request.GiantsquidHistoryRequest

From 7bc87dd9c2ec4f38249902f13293b1759a774627 Mon Sep 17 00:00:00 2001
From: Deneath <lyazgindenis@gmail.com>
Date: Fri, 26 Jan 2024 16:14:15 +0700
Subject: [PATCH 15/35] switch configs to master

---
 runtime/build.gradle | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/runtime/build.gradle b/runtime/build.gradle
index 8ac37469a6..1a8b4ef3e3 100644
--- a/runtime/build.gradle
+++ b/runtime/build.gradle
@@ -14,7 +14,7 @@ android {
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
         buildConfigField "String", "TYPES_URL", "\"https://raw.githubusercontent.com/soramitsu/shared-features-utils/master/chains/all_chains_types_android.json\""
         buildConfigField "String", "APP_VERSION_NAME", "\"${rootProject.versionName}\""
-        buildConfigField("String", "DEFAULT_V13_TYPES_URL", "\"https://raw.githubusercontent.com/soramitsu/shared-features-utils/reef/chains/default_v13_types.json\"")
+        buildConfigField("String", "DEFAULT_V13_TYPES_URL", "\"https://raw.githubusercontent.com/soramitsu/shared-features-utils/master/chains/default_v13_types.json\"")
     }
 
     buildTypes {

From fc5ae1ed0783b3c901e9d0860c17bea0fcdef3a5 Mon Sep 17 00:00:00 2001
From: Deneath <lyazgindenis@gmail.com>
Date: Fri, 2 Feb 2024 15:56:17 +0700
Subject: [PATCH 16/35] Fixed transactions history for reef

---
 .../data/historySource/ReefHistorySource.kt   | 32 +++++++++----------
 .../model/request/ReefHistoryRequest.kt       | 16 +++-------
 .../model/response/ReefHistoryResponse.kt     |  7 ++--
 3 files changed, 23 insertions(+), 32 deletions(-)

diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/historySource/ReefHistorySource.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/historySource/ReefHistorySource.kt
index 9b49ba872b..fce01a0de6 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/historySource/ReefHistorySource.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/historySource/ReefHistorySource.kt
@@ -8,7 +8,6 @@ import jp.co.soramitsu.common.data.model.CursorPage
 import jp.co.soramitsu.core.models.Asset
 import jp.co.soramitsu.runtime.multiNetwork.chain.model.Chain
 import jp.co.soramitsu.shared_utils.runtime.AccountId
-import jp.co.soramitsu.wallet.impl.data.network.model.request.ReefHistoryRequest
 import jp.co.soramitsu.wallet.impl.data.network.model.request.ReefRequestBuilder
 import jp.co.soramitsu.wallet.impl.data.network.subquery.OperationsHistoryApi
 import jp.co.soramitsu.wallet.impl.domain.interfaces.TransactionFilter
@@ -36,19 +35,20 @@ class ReefHistorySource(
                 filters,
                 accountAddress = accountAddress,
                 overridePageSize,
-                offset.toString()
+                offset?.toString()
             ).buildRequest()
         )
+
         val operations = mutableListOf<Operation>()
-        if(filters.contains(TransactionFilter.TRANSFER)) {
-            operations.addAll(response.data.transfersConnection.edges.map { it.node }.map {
+        if(filters.contains(TransactionFilter.TRANSFER) && response.data.transfersConnection != null) {
+            operations.addAll(response.data.transfersConnection?.edges?.map { it.node }?.map {
                 Operation(
-                    id = it.extrinsic?.hash ?: it.id,
+                    id = it.extrinsicHash ?: it.id,
                     address = accountAddress,
                     time = parseTimeToMillis(it.timestamp),
                     chainAsset = chainAsset,
                     type = Operation.Type.Transfer(
-                        hash = it.extrinsic?.hash,
+                        hash = it.extrinsicHash,
                         myAddress = accountAddress,
                         amount = it.amount,
                         receiver = it.to.id,
@@ -57,10 +57,10 @@ class ReefHistorySource(
                         fee = it.feeAmount
                     )
                 )
-            })
+            }.orEmpty())
         }
-        if(filters.contains(TransactionFilter.REWARD)) {
-            operations.addAll(response.data.stakingsConnection.edges.map { it.node }.map {
+        if(filters.contains(TransactionFilter.REWARD) && response.data.stakingsConnection != null) {
+            operations.addAll(response.data.stakingsConnection?.edges?.map { it.node }?.map {
                 Operation(
                     id = it.id,
                     address = accountAddress,
@@ -73,20 +73,20 @@ class ReefHistorySource(
                         validator = null
                     )
                 )
-            })
+            }.orEmpty())
         }
 
-        val transfersPageInfo = response.data.transfersConnection.pageInfo
-        val rewardsPageInfo = response.data.stakingsConnection.pageInfo
+        val transfersPageInfo = response.data.transfersConnection?.pageInfo
+        val rewardsPageInfo = response.data.stakingsConnection?.pageInfo
 
-        val shouldLoadTransfersNextPage = transfersPageInfo.hasNextPage
-        val shouldLoadRewardsNextPage = rewardsPageInfo.hasNextPage
+        val shouldLoadTransfersNextPage = transfersPageInfo?.hasNextPage ?: false
+        val shouldLoadRewardsNextPage = rewardsPageInfo?.hasNextPage ?: false
 
         val hasNextPage = shouldLoadTransfersNextPage || shouldLoadRewardsNextPage
 
         val nextCursor = if(hasNextPage) {
-            val transfersOffset = transfersPageInfo.endCursor.toIntOrNull() ?: 0
-            val rewardsOffset = rewardsPageInfo.endCursor.toIntOrNull() ?: 0
+            val transfersOffset = transfersPageInfo?.endCursor?.toIntOrNull() ?: 0
+            val rewardsOffset = rewardsPageInfo?.endCursor?.toIntOrNull() ?: 0
             val nextOffset = maxOf(transfersOffset, rewardsOffset)
             if(nextOffset >= overridePageSize) nextOffset.toString() else null
         } else {
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/request/ReefHistoryRequest.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/request/ReefHistoryRequest.kt
index 2c8f1fd63c..fd8233d152 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/request/ReefHistoryRequest.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/request/ReefHistoryRequest.kt
@@ -6,33 +6,28 @@ class ReefRequestBuilder(
     private val filters: Set<TransactionFilter>,
     private val accountAddress: String,
     private val limit: Int = 50,
-    private val transfersOffset: String? = null,
-    private val rewardsOffset: String? = null
+    private val transfersOffset: String? = null
 ) {
     fun buildRequest(): ReefHistoryRequest {
+        val offset = transfersOffset?.let { "\"$it\"" }
         val query = StringBuilder()
         if (filters.contains(TransactionFilter.TRANSFER)) {
             query.append(
                 """
-                transfersConnection(where: {AND: [{type_eq: Native}, {OR: [{from: {id_eq: "$accountAddress"}}, {to: {id_eq: "$accountAddress"}}]}]}, orderBy: timestamp_DESC, first: $limit, after: $transfersOffset) {
+                transfersConnection(where: {AND: [{type_eq: Native}, {OR: [{from: {id_eq: "$accountAddress"}}, {to: {id_eq: "$accountAddress"}}]}]}, orderBy: timestamp_DESC, first: $limit, after: $offset) {
                     edges {
                       node {
                         id
                         amount
-                        feeAmount
-                        type
                         timestamp
                         success
-                        denom
                         to {
                           id
                         }
                         from {
                           id
                         }
-                        extrinsic {
-                          hash
-                        }
+                        extrinsicHash
                       }
                     }
                     pageInfo {
@@ -47,11 +42,10 @@ class ReefRequestBuilder(
         if (filters.contains(TransactionFilter.REWARD)) {
             query.append(
                 """
-                stakingsConnection(orderBy: timestamp_DESC, where: {AND: {signer: {id_eq: "$accountAddress"}, amount_gt: "0"}}, first: $limit, after: $rewardsOffset) {
+                stakingsConnection(orderBy: timestamp_DESC, where: {AND: {signer: {id_eq: "$accountAddress"}, amount_gt: "0"}}, first: ${limit * 2}, after: $offset) {
                     edges {
                       node {
                         id
-                        type
                         amount
                         timestamp
                         signer {
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/response/ReefHistoryResponse.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/response/ReefHistoryResponse.kt
index 8947fc4b09..d13334ec0e 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/response/ReefHistoryResponse.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/response/ReefHistoryResponse.kt
@@ -4,7 +4,7 @@ import java.math.BigInteger
 import jp.co.soramitsu.common.data.network.subquery.ReefAddress
 import jp.co.soramitsu.common.data.network.subquery.ReefRewardsConnection
 
-data class ReefHistoryResponse(val transfersConnection: ReefElementsConnection, val stakingsConnection: ReefRewardsConnection)
+data class ReefHistoryResponse(val transfersConnection: ReefElementsConnection? = null, val stakingsConnection: ReefRewardsConnection? = null)
 
 class ReefElementsConnection(
     val pageInfo: SubsquidPageInfo,
@@ -19,11 +19,8 @@ class ReefHistoryNode(
     val type: String,
     val timestamp: String,
     val success: Boolean,
-    val denom: String,
     val to: ReefAddress,
     val from: ReefAddress,
-    val extrinsic: ReefExtrinsic?
+    val extrinsicHash: String?
 )
 
-class ReefExtrinsic(val hash: String)
-

From cf8750dad49c9d68b33daafbcb1425e8e4710b94 Mon Sep 17 00:00:00 2001
From: Deneath <lyazgindenis@gmail.com>
Date: Fri, 2 Feb 2024 16:43:18 +0700
Subject: [PATCH 17/35] rebase fixes

---
 .../jp/co/soramitsu/success/presentation/SuccessViewModel.kt    | 1 +
 .../co/soramitsu/runtime/multiNetwork/chain/ChainSyncService.kt | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/feature-success-impl/src/main/kotlin/jp/co/soramitsu/success/presentation/SuccessViewModel.kt b/feature-success-impl/src/main/kotlin/jp/co/soramitsu/success/presentation/SuccessViewModel.kt
index 875d57ece0..eb2bab41ff 100644
--- a/feature-success-impl/src/main/kotlin/jp/co/soramitsu/success/presentation/SuccessViewModel.kt
+++ b/feature-success-impl/src/main/kotlin/jp/co/soramitsu/success/presentation/SuccessViewModel.kt
@@ -74,6 +74,7 @@ class SuccessViewModel @Inject constructor(
                     BlockExplorerUrlBuilder(explorerItem.url, explorerItem.types).build(BlockExplorerUrlBuilder.Type.TX, operationHash)
                 }
 
+                Chain.Explorer.Type.REEF -> BlockExplorerUrlBuilder(explorerItem.url, explorerItem.types).build(BlockExplorerUrlBuilder.Type.EXTRINSIC, operationHash)
                 Chain.Explorer.Type.UNKNOWN -> null
             }?.let { url ->
                 explorerItem.type to url
diff --git a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/ChainSyncService.kt b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/ChainSyncService.kt
index c9f207ef4d..80f3f21d99 100644
--- a/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/ChainSyncService.kt
+++ b/runtime/src/main/java/jp/co/soramitsu/runtime/multiNetwork/chain/ChainSyncService.kt
@@ -19,7 +19,7 @@ class ChainSyncService(
 
         val remoteChains = chainFetcher.getChains()
             .filter {
-                !it.disabled && (it.assets?.isNotEmpty() == true) && it.chainId != reefChainId // todo reef
+                !it.disabled && (it.assets?.isNotEmpty() == true)
             }
             .map {
                 it.toChain()

From bc0e953c8c29325144f168ee2122798a8f828fd2 Mon Sep 17 00:00:00 2001
From: Deneath <lyazgindenis@gmail.com>
Date: Fri, 2 Feb 2024 17:37:14 +0700
Subject: [PATCH 18/35] Fix transactions history fee

---
 .../impl/data/historySource/ReefHistorySource.kt      |  4 ++--
 .../data/network/model/request/ReefHistoryRequest.kt  |  2 +-
 .../network/model/response/ReefHistoryResponse.kt     | 11 ++++++++---
 3 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/historySource/ReefHistorySource.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/historySource/ReefHistorySource.kt
index fce01a0de6..46b53d82a4 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/historySource/ReefHistorySource.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/historySource/ReefHistorySource.kt
@@ -43,7 +43,7 @@ class ReefHistorySource(
         if(filters.contains(TransactionFilter.TRANSFER) && response.data.transfersConnection != null) {
             operations.addAll(response.data.transfersConnection?.edges?.map { it.node }?.map {
                 Operation(
-                    id = it.extrinsicHash ?: it.id,
+                    id = it.extrinsicHash ?: it.id ?: it.hashCode().toString(),
                     address = accountAddress,
                     time = parseTimeToMillis(it.timestamp),
                     chainAsset = chainAsset,
@@ -54,7 +54,7 @@ class ReefHistorySource(
                         receiver = it.to.id,
                         sender = it.from.id,
                         status = Operation.Status.fromSuccess(it.success),
-                        fee = it.feeAmount
+                        fee = it.signedData?.fee?.partialFee
                     )
                 )
             }.orEmpty())
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/request/ReefHistoryRequest.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/request/ReefHistoryRequest.kt
index fd8233d152..aaee312017 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/request/ReefHistoryRequest.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/request/ReefHistoryRequest.kt
@@ -17,7 +17,6 @@ class ReefRequestBuilder(
                 transfersConnection(where: {AND: [{type_eq: Native}, {OR: [{from: {id_eq: "$accountAddress"}}, {to: {id_eq: "$accountAddress"}}]}]}, orderBy: timestamp_DESC, first: $limit, after: $offset) {
                     edges {
                       node {
-                        id
                         amount
                         timestamp
                         success
@@ -27,6 +26,7 @@ class ReefRequestBuilder(
                         from {
                           id
                         }
+                        signedData
                         extrinsicHash
                       }
                     }
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/response/ReefHistoryResponse.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/response/ReefHistoryResponse.kt
index d13334ec0e..d8816a6bba 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/response/ReefHistoryResponse.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/model/response/ReefHistoryResponse.kt
@@ -13,14 +13,19 @@ class ReefElementsConnection(
 
 class ReefHistoryEdge(val node: ReefHistoryNode)
 class ReefHistoryNode(
-    val id: String,
+    val id: String? = null,
     val amount: BigInteger,
-    val feeAmount: BigInteger,
     val type: String,
     val timestamp: String,
     val success: Boolean,
     val to: ReefAddress,
     val from: ReefAddress,
-    val extrinsicHash: String?
+    val extrinsicHash: String?,
+    val signedData: ReefSignedData?
 )
 
+class ReefSignedData(val fee: ReefFeeData?)
+
+class ReefFeeData(
+    val partialFee: BigInteger?
+)
\ No newline at end of file

From 10ce0274e90ce29d697780f92ed38ee2e7b5cc74 Mon Sep 17 00:00:00 2001
From: Deneath <lyazgindenis@gmail.com>
Date: Tue, 6 Feb 2024 00:58:51 +0700
Subject: [PATCH 19/35] Added oversubscribed validators alert

---
 .../staking/impl/domain/alerts/Alert.kt       |  1 +
 .../impl/domain/alerts/AlertsInteractor.kt    | 25 +++++++++++++------
 .../StakingRelaychainScenarioViewModel.kt     | 13 ++++++++--
 3 files changed, 30 insertions(+), 9 deletions(-)

diff --git a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/domain/alerts/Alert.kt b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/domain/alerts/Alert.kt
index 44d79777fc..7fe0a2a0d0 100644
--- a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/domain/alerts/Alert.kt
+++ b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/domain/alerts/Alert.kt
@@ -12,6 +12,7 @@ sealed class Alert {
     class BondMoreTokens(val minimalStake: BigDecimal, val token: Token) : Alert()
 
     object ChangeValidators : Alert()
+    object AllValidatorsAreOversubscribed : Alert()
 
     object WaitingForNextEra : Alert()
 
diff --git a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/domain/alerts/AlertsInteractor.kt b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/domain/alerts/AlertsInteractor.kt
index ace9cabba1..db7bde09f9 100644
--- a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/domain/alerts/AlertsInteractor.kt
+++ b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/domain/alerts/AlertsInteractor.kt
@@ -20,6 +20,7 @@ import kotlinx.coroutines.flow.flatMapLatest
 import kotlinx.coroutines.flow.flowOf
 import java.math.BigDecimal
 import java.math.BigInteger
+import jp.co.soramitsu.shared_utils.extensions.toHexString
 import jp.co.soramitsu.core.models.Asset as CoreAsset
 
 private const val NOMINATIONS_ACTIVE_MEMO = "NOMINATIONS_ACTIVE_MEMO"
@@ -38,7 +39,8 @@ class AlertsInteractor(
         val maxRewardedNominatorsPerValidator: Int,
         val minimumNominatorBond: BigInteger,
         val activeEra: BigInteger,
-        val asset: Asset
+        val asset: Asset,
+        val maxNominators: Int
     ) {
 
         val memo = mutableMapOf<Any, Any?>()
@@ -63,11 +65,17 @@ class AlertsInteractor(
 
     private fun produceChangeValidatorsAlert(context: AlertContext): Alert? {
         return requireState(context.stakingState) { nominatorState: StakingState.Stash.Nominator ->
-            Alert.ChangeValidators.takeIf {
-                // staking is inactive
-                context.isStakingActive(nominatorState.stashId).not() &&
-                    // there is no pending change
-                    nominatorState.nominations.isWaiting(context.activeEra).not()
+            val allValidatorsAreOversubscribed = nominatorState.nominations.targets.mapNotNull { context.exposures[it.toHexString()] }.all { it.others.size > context.maxNominators }
+            val stakingIsNotActive = context.isStakingActive(nominatorState.stashId).not()
+
+            if (stakingIsNotActive.not()) return null
+
+            return@requireState when {
+                stakingIsNotActive && allValidatorsAreOversubscribed -> Alert.AllValidatorsAreOversubscribed
+                stakingIsNotActive && nominatorState.nominations.isWaiting(context.activeEra)
+                    .not() -> Alert.ChangeValidators
+
+                else -> null
             }
         }
     }
@@ -124,6 +132,8 @@ class AlertsInteractor(
         val minimumNominatorBond = stakingRepository.minimumNominatorBond(chainAsset)
         val meta = accountRepository.getSelectedMetaAccount()
 
+        val maxNominators = stakingConstantsRepository.maxRewardedNominatorPerValidator(chain.id)
+
         val alertsFlow = combine(
             stakingRepository.electedExposuresInActiveEra(chain.id),
             walletRepository.assetFlow(meta.id, stakingState.accountId, chainAsset, chain.minSupportedVersion),
@@ -136,7 +146,8 @@ class AlertsInteractor(
                 maxRewardedNominatorsPerValidator = maxRewardedNominatorsPerValidator,
                 minimumNominatorBond = minimumNominatorBond,
                 asset = asset,
-                activeEra = activeEra
+                activeEra = activeEra,
+                maxNominators = maxNominators
             )
 
             alertProducers.mapNotNull { it.invoke(context) }
diff --git a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/main/scenarios/StakingRelaychainScenarioViewModel.kt b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/main/scenarios/StakingRelaychainScenarioViewModel.kt
index 9234f9e4b5..e1f9f43c7b 100644
--- a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/main/scenarios/StakingRelaychainScenarioViewModel.kt
+++ b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/main/scenarios/StakingRelaychainScenarioViewModel.kt
@@ -194,7 +194,7 @@ class StakingRelaychainScenarioViewModel(
 
     private fun mapAlertToAlertModel(alert: Alert): AlertModel {
         return when (alert) {
-            Alert.ChangeValidators -> {
+            is Alert.ChangeValidators -> {
                 AlertModel(
                     WARNING_ICON,
                     resourceManager.getString(R.string.staking_alert_change_validators),
@@ -203,6 +203,15 @@ class StakingRelaychainScenarioViewModel(
                 )
             }
 
+            is Alert.AllValidatorsAreOversubscribed -> {
+                AlertModel(
+                    WARNING_ICON,
+                    resourceManager.getString(R.string.staking_alert_change_validators),
+                    resourceManager.getString(R.string.staking_your_oversubscribed_message),
+                    AlertModel.Type.CallToAction { baseViewModel.openCurrentValidators() }
+                )
+            }
+
             is Alert.RedeemTokens -> {
                 AlertModel(
                     WARNING_ICON,
@@ -230,7 +239,7 @@ class StakingRelaychainScenarioViewModel(
                 AlertModel.Type.Info
             )
 
-            Alert.SetValidators -> AlertModel(
+            is Alert.SetValidators -> AlertModel(
                 WARNING_ICON,
                 resourceManager.getString(R.string.staking_set_validators_title),
                 resourceManager.getString(R.string.staking_set_validators_message),

From a21e53447dc022519002fbdba888575648db0d4b Mon Sep 17 00:00:00 2001
From: Deneath <lyazgindenis@gmail.com>
Date: Thu, 8 Feb 2024 17:06:58 +0700
Subject: [PATCH 20/35] fix reef bugs

---
 .../staking/bond/confirm/ConfirmBondMoreViewModel.kt            | 1 +
 feature-staking-impl/src/main/res/layout/view_stake_summary.xml | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/bond/confirm/ConfirmBondMoreViewModel.kt b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/bond/confirm/ConfirmBondMoreViewModel.kt
index 8c5fd9f862..4291f43531 100644
--- a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/bond/confirm/ConfirmBondMoreViewModel.kt
+++ b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/bond/confirm/ConfirmBondMoreViewModel.kt
@@ -150,6 +150,7 @@ class ConfirmBondMoreViewModel @Inject constructor(
             showMessage(resourceManager.getString(R.string.common_transaction_submitted))
 
             finishFlow()
+            result.getOrNull()?.let { router.openOperationSuccess(it, token.configuration.chainId) }
         } else {
             showError(result.requireException())
         }
diff --git a/feature-staking-impl/src/main/res/layout/view_stake_summary.xml b/feature-staking-impl/src/main/res/layout/view_stake_summary.xml
index abafac7e25..940a398bff 100644
--- a/feature-staking-impl/src/main/res/layout/view_stake_summary.xml
+++ b/feature-staking-impl/src/main/res/layout/view_stake_summary.xml
@@ -62,7 +62,7 @@
             android:layout_marginEnd="16dp"
             android:layout_weight="1"
             app:startWithLoading="true"
-            app:titleText="@string/staking_rewards_apr" />
+            app:titleText="@string/staking_total_rewards_v1.9.0" />
     </LinearLayout>
 
     <View

From f911539187458bdf03cc2aec3fdedc11fd7ecba9 Mon Sep 17 00:00:00 2001
From: Sergey Pankratov <pankratov@soramitsu.co.jp>
Date: Thu, 8 Feb 2024 17:41:53 +0500
Subject: [PATCH 21/35] fix crash

---
 .../pool/join/SetupStakingPoolViewModel.kt    | 66 ++++++++++---------
 1 file changed, 35 insertions(+), 31 deletions(-)

diff --git a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/setup/pool/join/SetupStakingPoolViewModel.kt b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/setup/pool/join/SetupStakingPoolViewModel.kt
index 00ce7c0f11..2ff591a674 100644
--- a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/setup/pool/join/SetupStakingPoolViewModel.kt
+++ b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/setup/pool/join/SetupStakingPoolViewModel.kt
@@ -22,7 +22,6 @@ import jp.co.soramitsu.common.utils.formatCrypto
 import jp.co.soramitsu.common.utils.formatCryptoDetail
 import jp.co.soramitsu.common.utils.formatFiat
 import jp.co.soramitsu.common.utils.inBackground
-import jp.co.soramitsu.common.utils.isNotZero
 import jp.co.soramitsu.common.utils.orZero
 import jp.co.soramitsu.common.validation.AmountTooLowToStakeException
 import jp.co.soramitsu.common.validation.ExistentialDepositCrossedException
@@ -155,43 +154,48 @@ class SetupStakingPoolViewModel @Inject constructor(
         val amount = enteredAmountFlow.value
 
         viewModelScope.launch {
-            isValid(amount).fold({
-                stakingPoolSharedStateProvider.joinFlowState.set(setupFlow.copy(amount = amount))
-                router.openSelectPool()
-            }, { throwable ->
-                val message =
-                    throwable.localizedMessage ?: throwable.message ?: resourceManager.getString(R.string.common_undefined_error_message)
-                val errorAlertViewState = (throwable as? ValidationException)?.let { (title, message) ->
-                    AlertViewState(
-                        title = title,
+            isValid(amount).fold(
+                onSuccess = {
+                    stakingPoolSharedStateProvider.joinFlowState.set(setupFlow.copy(amount = amount))
+                    router.openSelectPool()
+                },
+                onFailure = { throwable ->
+                    val message =
+                        throwable.localizedMessage ?: throwable.message ?: resourceManager.getString(R.string.common_undefined_error_message)
+                    val errorAlertViewState = (throwable as? ValidationException)?.let { (title, message) ->
+                        AlertViewState(
+                            title = title,
+                            message = message,
+                            buttonText = resourceManager.getString(R.string.common_ok),
+                            iconRes = R.drawable.ic_status_warning_16
+                        )
+                    } ?: AlertViewState(
+                        title = resourceManager.getString(R.string.common_error_general_title),
                         message = message,
-                        buttonText = resourceManager.getString(R.string.common_ok),
+                        buttonText = resourceManager.getString(R.string.common_got_it),
                         iconRes = R.drawable.ic_status_warning_16
                     )
-                } ?: AlertViewState(
-                    title = resourceManager.getString(R.string.common_error_general_title),
-                    message = message,
-                    buttonText = resourceManager.getString(R.string.common_got_it),
-                    iconRes = R.drawable.ic_status_warning_16
-                )
-                router.openAlert(errorAlertViewState)
-            })
+                    router.openAlert(errorAlertViewState)
+                })
         }
     }
 
     private suspend fun isValid(amount: BigDecimal): Result<Any> {
-        val amountInPlanks = asset.token.planksFromAmount(amount)
-        val transferableInPlanks = asset.token.planksFromAmount(asset.transferable)
-        val minToJoinInPlanks = stakingPoolInteractor.getMinToJoinPool(chain.id)
-        val minToJoinFormatted = minToJoinInPlanks.formatCryptoDetailFromPlanks(asset.token.configuration)
-        val existentialDeposit = existentialDepositUseCase(asset.token.configuration)
-        val feeInPlanks = feeInPlanksFlow.value ?: return Result.failure(WaitForFeeCalculationException(resourceManager))
-
-        return when {
-            amountInPlanks + feeInPlanks >= transferableInPlanks -> Result.failure(StakeInsufficientBalanceException(resourceManager))
-            transferableInPlanks - amountInPlanks - feeInPlanks <= existentialDeposit -> Result.failure(ExistentialDepositCrossedException(resourceManager, existentialDeposit.formatCryptoDetailFromPlanks(asset.token.configuration)))
-            amountInPlanks < minToJoinInPlanks -> Result.failure(AmountTooLowToStakeException(resourceManager, minToJoinFormatted))
-            else -> Result.success(Unit)
+        return runCatching {
+            val amountInPlanks = asset.token.planksFromAmount(amount)
+            val transferableInPlanks = asset.token.planksFromAmount(asset.transferable)
+            val minToJoinInPlanks = stakingPoolInteractor.getMinToJoinPool(chain.id)
+            val minToJoinFormatted = minToJoinInPlanks.formatCryptoDetailFromPlanks(asset.token.configuration)
+            val existentialDeposit = existentialDepositUseCase(asset.token.configuration)
+            val feeInPlanks = feeInPlanksFlow.value
+
+            when {
+                feeInPlanks == null -> throw WaitForFeeCalculationException(resourceManager)
+                amountInPlanks + feeInPlanks >= transferableInPlanks -> throw StakeInsufficientBalanceException(resourceManager)
+                transferableInPlanks - amountInPlanks - feeInPlanks <= existentialDeposit -> throw ExistentialDepositCrossedException(resourceManager, existentialDeposit.formatCryptoDetailFromPlanks(asset.token.configuration))
+                amountInPlanks < minToJoinInPlanks -> throw AmountTooLowToStakeException(resourceManager, minToJoinFormatted)
+                else -> Unit
+            }
         }
     }
 

From f220a5cf1bc97b86a74305e540aea339c6f9e991 Mon Sep 17 00:00:00 2001
From: Sergey Pankratov <pankratov@soramitsu.co.jp>
Date: Thu, 8 Feb 2024 18:06:06 +0500
Subject: [PATCH 22/35] fix crash

---
 .../pool/create/CreatePoolSetupViewModel.kt   | 13 ++--
 .../main/scenarios/StakingPoolViewModel.kt    | 64 ++++++++++---------
 .../staking/unbond/PoolUnstakeViewModel.kt    | 22 ++++---
 3 files changed, 55 insertions(+), 44 deletions(-)

diff --git a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/setup/pool/create/CreatePoolSetupViewModel.kt b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/setup/pool/create/CreatePoolSetupViewModel.kt
index 20703c03d7..c3cb02380f 100644
--- a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/setup/pool/create/CreatePoolSetupViewModel.kt
+++ b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/setup/pool/create/CreatePoolSetupViewModel.kt
@@ -218,10 +218,15 @@ class CreatePoolSetupViewModel @Inject constructor(
             val fee = feeInPlanksFlow.value
             val transferableInPlanks = asset.token.planksFromAmount(asset.transferable)
 
-            val minToCreate = poolInteractor.getMinToCreate(chain.id)
-            if (amountInPlanks < minToCreate) {
-                val minToCreateFormatted = minToCreate.formatCryptoDetailFromPlanks(asset.token.configuration)
-                showError(MinPoolCreationThresholdException(resourceManager, minToCreateFormatted))
+            try {
+                val minToCreate = poolInteractor.getMinToCreate(chain.id)
+                if (amountInPlanks < minToCreate) {
+                    val minToCreateFormatted = minToCreate.formatCryptoDetailFromPlanks(asset.token.configuration)
+                    showError(MinPoolCreationThresholdException(resourceManager, minToCreateFormatted))
+                    return@launch
+                }
+            } catch (e: NullPointerException) {
+                showError(e.message.orEmpty())
                 return@launch
             }
 
diff --git a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/main/scenarios/StakingPoolViewModel.kt b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/main/scenarios/StakingPoolViewModel.kt
index 897d081a9d..2285e60d88 100644
--- a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/main/scenarios/StakingPoolViewModel.kt
+++ b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/main/scenarios/StakingPoolViewModel.kt
@@ -43,7 +43,7 @@ import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.emptyFlow
 import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.first
-import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.mapNotNull
 import kotlinx.coroutines.flow.stateIn
 
 class StakingPoolViewModel(
@@ -148,35 +148,39 @@ class StakingPoolViewModel(
     }
 
     override suspend fun networkInfo(): Flow<LoadingState<StakingNetworkInfoModel>> {
-        return stakingInteractor.currentAssetFlow().filter { it.token.configuration.supportStakingPool }.map { asset ->
-            val config = asset.token.configuration
-            val chainId = config.chainId
-
-            val minToJoinPoolInPlanks = stakingPoolInteractor.getMinToJoinPool(chainId)
-            val minToJoinPool = asset.token.configuration.amountFromPlanks(minToJoinPoolInPlanks)
-            val minToJoinPoolFormatted = minToJoinPool.formatCryptoDetail(config.symbol)
-            val minToJoinPoolFiat = asset.token.fiatAmount(minToJoinPool)?.formatFiat(asset.token.fiatSymbol)
-
-            val minToCreatePoolInPlanks = stakingPoolInteractor.getMinToCreate(chainId)
-            val minToCreatePool = asset.token.configuration.amountFromPlanks(minToCreatePoolInPlanks)
-            val minToCreatePoolFormatted = minToCreatePool.formatCryptoDetail(config.symbol)
-            val minToCreatePoolFiat = asset.token.fiatAmount(minToCreatePool)?.formatFiat(asset.token.fiatSymbol)
-
-            val existingPools = stakingPoolInteractor.getExistingPools(chainId).toString()
-            val possiblePools = stakingPoolInteractor.getPossiblePools(chainId).toString()
-            val maxMembersInPool = stakingPoolInteractor.getMaxMembersInPool(chainId).toString()
-            val maxPoolsMembers = stakingPoolInteractor.getMaxPoolsMembers(chainId).toString()
-
-            StakingNetworkInfoModel.Pool(
-                minToJoinPoolFormatted,
-                minToJoinPoolFiat,
-                minToCreatePoolFormatted,
-                minToCreatePoolFiat,
-                existingPools,
-                possiblePools,
-                maxMembersInPool,
-                maxPoolsMembers
-            )
+        return stakingInteractor.currentAssetFlow().filter { it.token.configuration.supportStakingPool }.mapNotNull { asset ->
+            try {
+                val config = asset.token.configuration
+                val chainId = config.chainId
+
+                val minToJoinPoolInPlanks = stakingPoolInteractor.getMinToJoinPool(chainId)
+                val minToJoinPool = asset.token.configuration.amountFromPlanks(minToJoinPoolInPlanks)
+                val minToJoinPoolFormatted = minToJoinPool.formatCryptoDetail(config.symbol)
+                val minToJoinPoolFiat = asset.token.fiatAmount(minToJoinPool)?.formatFiat(asset.token.fiatSymbol)
+
+                val minToCreatePoolInPlanks = stakingPoolInteractor.getMinToCreate(chainId)
+                val minToCreatePool = asset.token.configuration.amountFromPlanks(minToCreatePoolInPlanks)
+                val minToCreatePoolFormatted = minToCreatePool.formatCryptoDetail(config.symbol)
+                val minToCreatePoolFiat = asset.token.fiatAmount(minToCreatePool)?.formatFiat(asset.token.fiatSymbol)
+
+                val existingPools = stakingPoolInteractor.getExistingPools(chainId).toString()
+                val possiblePools = stakingPoolInteractor.getPossiblePools(chainId).toString()
+                val maxMembersInPool = stakingPoolInteractor.getMaxMembersInPool(chainId).toString()
+                val maxPoolsMembers = stakingPoolInteractor.getMaxPoolsMembers(chainId).toString()
+
+                StakingNetworkInfoModel.Pool(
+                    minToJoinPoolFormatted,
+                    minToJoinPoolFiat,
+                    minToCreatePoolFormatted,
+                    minToCreatePoolFiat,
+                    existingPools,
+                    possiblePools,
+                    maxMembersInPool,
+                    maxPoolsMembers
+                )
+            } catch (e: NullPointerException) {
+                null
+            }
         }.withLoading()
     }
 
diff --git a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/unbond/PoolUnstakeViewModel.kt b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/unbond/PoolUnstakeViewModel.kt
index ff5c1a6850..eb73c1b382 100644
--- a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/unbond/PoolUnstakeViewModel.kt
+++ b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/unbond/PoolUnstakeViewModel.kt
@@ -36,17 +36,19 @@ class PoolUnstakeViewModel @Inject constructor(
         )
     },
     onNextStep = { amount ->
-        val minToCreate = stakingPoolInteractor.getMinToCreate(stakingPoolSharedStateProvider.requireMainState.requireChain.id)
+        try {
+            val minToCreate = stakingPoolInteractor.getMinToCreate(stakingPoolSharedStateProvider.requireMainState.requireChain.id)
 
-        val isDepositor = stakingPoolSharedStateProvider.requireManageState.userRole == RoleInPool.Depositor
-        if (isDepositor && (stakingPoolSharedStateProvider.requireManageState.stakedInPlanks - amount) < minToCreate) {
-            val asset = stakingPoolSharedStateProvider.requireMainState.requireAsset
-            val minToCreateFormatted = minToCreate.formatCryptoDetailFromPlanks(asset.token.configuration)
-            router.openPoolFullUnstakeDepositorAlertFragment(minToCreateFormatted)
-        } else {
-            stakingPoolSharedStateProvider.manageState.get()?.copy(amountInPlanks = amount)?.let { stakingPoolSharedStateProvider.manageState.set(it) }
-            router.openPoolConfirmUnstake()
-        }
+            val isDepositor = stakingPoolSharedStateProvider.requireManageState.userRole == RoleInPool.Depositor
+            if (isDepositor && (stakingPoolSharedStateProvider.requireManageState.stakedInPlanks - amount) < minToCreate) {
+                val asset = stakingPoolSharedStateProvider.requireMainState.requireAsset
+                val minToCreateFormatted = minToCreate.formatCryptoDetailFromPlanks(asset.token.configuration)
+                router.openPoolFullUnstakeDepositorAlertFragment(minToCreateFormatted)
+            } else {
+                stakingPoolSharedStateProvider.manageState.get()?.copy(amountInPlanks = amount)?.let { stakingPoolSharedStateProvider.manageState.set(it) }
+                router.openPoolConfirmUnstake()
+            }
+        } catch (_: NullPointerException) {}
     },
     validations = arrayOf(
         Validation(

From 16173174c61e9fcb677b348fa6c04a8c0287a3be Mon Sep 17 00:00:00 2001
From: Sergey Pankratov <pankratov@soramitsu.co.jp>
Date: Thu, 8 Feb 2024 18:37:34 +0500
Subject: [PATCH 23/35] fix crash

---
 .../staking/balance/StakingBalanceFragment.kt |  2 +-
 .../balance/StakingBalanceViewModel.kt        | 20 ++++++++++++-------
 2 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/balance/StakingBalanceFragment.kt b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/balance/StakingBalanceFragment.kt
index 68899dc038..5f513c2ec0 100644
--- a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/balance/StakingBalanceFragment.kt
+++ b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/balance/StakingBalanceFragment.kt
@@ -61,7 +61,7 @@ class StakingBalanceFragment : BaseFragment<StakingBalanceViewModel>(R.layout.fr
 
         viewModel.redeemTitle?.let { binding.stakingBalanceActions.redeem.setText(it) }
 
-        viewModel.stakingBalanceModelLiveData.observe {
+        viewModel.stakingBalanceModelFlow.observe {
             binding.stakingBalanceSwipeRefresh.isRefreshing = false
 
             with(binding.stakingBalanceInfo) {
diff --git a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/balance/StakingBalanceViewModel.kt b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/balance/StakingBalanceViewModel.kt
index c1e359447f..232f8117f7 100644
--- a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/balance/StakingBalanceViewModel.kt
+++ b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/balance/StakingBalanceViewModel.kt
@@ -3,7 +3,11 @@ package jp.co.soramitsu.staking.impl.presentation.staking.balance
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.SavedStateHandle
+import androidx.lifecycle.viewModelScope
 import dagger.hilt.android.lifecycle.HiltViewModel
+import java.math.BigDecimal
+import java.math.BigInteger
+import javax.inject.Inject
 import jp.co.soramitsu.common.base.BaseViewModel
 import jp.co.soramitsu.common.mixin.api.Validatable
 import jp.co.soramitsu.common.resources.ResourceManager
@@ -32,18 +36,19 @@ import jp.co.soramitsu.staking.impl.scenarios.StakingScenarioInteractor
 import jp.co.soramitsu.wallet.api.presentation.model.mapAmountToAmountModel
 import jp.co.soramitsu.wallet.impl.domain.model.amountFromPlanks
 import jp.co.soramitsu.wallet.impl.domain.model.planksFromAmount
+import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.catch
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.first
 import kotlinx.coroutines.flow.flatMapLatest
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.onStart
 import kotlinx.coroutines.launch
-import java.math.BigDecimal
-import java.math.BigInteger
-import javax.inject.Inject
 
+@OptIn(ExperimentalCoroutinesApi::class)
 @HiltViewModel
 class StakingBalanceViewModel @Inject constructor(
     private val router: StakingRouter,
@@ -62,8 +67,9 @@ class StakingBalanceViewModel @Inject constructor(
     private val assetFlow = interactor.currentAssetFlow()
         .share()
 
-    val stakingBalanceModelLiveData: Flow<StakingBalanceModel> = refresh.flatMapLatest {
+    val stakingBalanceModelFlow: Flow<StakingBalanceModel> = refresh.flatMapLatest {
         stakingScenarioInteractor.getStakingBalanceFlow(collatorAddress?.fromHex())
+            .catch { }
     }.share()
 
     private val unbondingsFlow: Flow<List<Unbonding>> = refresh.flatMapLatest {
@@ -72,13 +78,13 @@ class StakingBalanceViewModel @Inject constructor(
 
     val redeemTitle = stakingScenarioInteractor.overrideRedeemActionTitle()
 
-    val redeemEnabledLiveData = stakingBalanceModelLiveData.map {
+    val redeemEnabledLiveData = stakingBalanceModelFlow.map {
         it.redeemable.amount > BigDecimal.ZERO
     }.asLiveData()
 
     val pendingAction = MutableLiveData(false)
 
-    val shouldBlockStakeMore = stakingBalanceModelLiveData.map {
+    val shouldBlockStakeMore = stakingBalanceModelFlow.map {
         val isParachain = assetFlow.first().token.configuration.staking == Asset.StakingType.PARACHAIN
         val isUnstakingFullAmount = (it.staked.amount - it.unstaking.amount).isZero()
         val isReadyForUnlockFullAmount = (it.staked.amount - it.redeemable.amount).isZero()
@@ -88,7 +94,7 @@ class StakingBalanceViewModel @Inject constructor(
         isFullUnstake.and(isParachain)
     }.onStart { emit(true) }.asLiveData()
 
-    val shouldBlockUnstake = stakingBalanceModelLiveData.map {
+    val shouldBlockUnstake = stakingBalanceModelFlow.map {
         val asset = assetFlow.first()
         val isParachain = asset.token.configuration.staking == Asset.StakingType.PARACHAIN
         val stakedAmountIsZero = asset.token.planksFromAmount(it.staked.amount) == BigInteger.ZERO

From 805cd3014b43a1b925c777db27e44649f178f8eb Mon Sep 17 00:00:00 2001
From: Sergey Pankratov <pankratov@soramitsu.co.jp>
Date: Thu, 8 Feb 2024 21:26:52 +0500
Subject: [PATCH 24/35] fix crash

---
 .../balance/detail/BalanceDetailViewModel.kt  | 45 ++++++++++---------
 1 file changed, 24 insertions(+), 21 deletions(-)

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 2cc49758b1..06cea90e58 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
@@ -65,7 +65,7 @@ import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.first
 import kotlinx.coroutines.flow.firstOrNull
 import kotlinx.coroutines.flow.flatMapLatest
-import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.mapNotNull
 import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.flow.stateIn
 import kotlinx.coroutines.launch
@@ -112,20 +112,22 @@ class BalanceDetailViewModel @Inject constructor(
     private val chainsItemStateFlow = chainsFlow.mapList { it.toChainItemState() }
 
     @OptIn(ExperimentalCoroutinesApi::class)
-    private val assetModelFlow = selectedChainId.map { selectedChainId ->
-        val chains = chainsFlow.first()
-        val selectedChain = chains.first { it.id == selectedChainId }
-        val initialSelectedChain = chains.first { it.id == assetPayloadInitial.chainId }
+    private val assetModelFlow = selectedChainId.mapNotNull { selectedChainId ->
+        val chains = chainsFlow.firstOrNull()
+        val selectedChain = chains?.firstOrNull { it.id == selectedChainId }
+        val initialSelectedChain = chains?.firstOrNull { it.id == assetPayloadInitial.chainId }
 
         val initialSelectedAssetSymbol =
-            initialSelectedChain.assets.first { it.id == assetPayloadInitial.chainAssetId }.symbol
+            initialSelectedChain?.assets?.firstOrNull { it.id == assetPayloadInitial.chainAssetId }?.symbol
         val newSelectedAsset =
-            selectedChain.assets.first { it.symbol == initialSelectedAssetSymbol }
+            selectedChain?.assets?.firstOrNull { it.symbol == initialSelectedAssetSymbol }
 
-        AssetPayload(
-            chainId = selectedChainId,
-            chainAssetId = newSelectedAsset.id
-        )
+        newSelectedAsset?.id?.let {
+            AssetPayload(
+                chainId = selectedChainId,
+                chainAssetId = it
+            )
+        }
     }
         .flatMapLatest {
             interactor.assetFlow(it.chainId, it.chainAssetId)
@@ -170,14 +172,14 @@ class BalanceDetailViewModel @Inject constructor(
         selectedChainId,
         chainsItemStateFlow
     ) { chainId, chainItems ->
-        val selectedChain = chainItems.first {
+        val selectedChain = chainItems.firstOrNull {
             it.id == chainId
         }
         LoadingState.Loaded(
             MainToolbarViewState(
                 title = interactor.getSelectedMetaAccount().name,
                 homeIconState = ToolbarHomeIconState(navigationIcon = R.drawable.ic_arrow_back_24dp),
-                selectorViewState = ChainSelectorViewState(selectedChain.title, selectedChain.id)
+                selectorViewState = ChainSelectorViewState(selectedChain?.title, selectedChain?.id)
             )
         )
     }.stateIn(scope = this, started = SharingStarted.Eagerly, initialValue = LoadingState.Loading())
@@ -492,15 +494,16 @@ class BalanceDetailViewModel @Inject constructor(
 
     private fun openBalanceDetails() {
         launch {
-            val assetModel = assetModelFlow.first()
-            router.openFrozenTokens(
-                FrozenAssetPayload(
-                    assetSymbol = assetModel.token.configuration.symbol,
-                    locked = assetModel.locked,
-                    reserved = assetModel.reserved,
-                    redeemable = assetModel.redeemable
+            assetModelFlow.firstOrNull()?.let { assetModel ->
+                router.openFrozenTokens(
+                    FrozenAssetPayload(
+                        assetSymbol = assetModel.token.configuration.symbol,
+                        locked = assetModel.locked,
+                        reserved = assetModel.reserved,
+                        redeemable = assetModel.redeemable
+                    )
                 )
-            )
+            }
         }
     }
 }

From 730b9d396ec51c0b7c5a63f7aed3c077623d4606 Mon Sep 17 00:00:00 2001
From: Deneath <lyazgindenis@gmail.com>
Date: Fri, 9 Feb 2024 13:32:36 +0700
Subject: [PATCH 25/35] fix lint

---
 .../SubqueryStakingRewardsDataSource.kt           |  1 -
 .../impl/data/historySource/ReefHistorySource.kt  |  5 -----
 .../blockchain/updaters/BalancesUpdateSystem.kt   | 15 ---------------
 .../data/network/subquery/OperationsHistoryApi.kt |  1 -
 4 files changed, 22 deletions(-)

diff --git a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/data/repository/datasource/SubqueryStakingRewardsDataSource.kt b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/data/repository/datasource/SubqueryStakingRewardsDataSource.kt
index e3d0059eb0..dddcf43e1c 100644
--- a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/data/repository/datasource/SubqueryStakingRewardsDataSource.kt
+++ b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/data/repository/datasource/SubqueryStakingRewardsDataSource.kt
@@ -2,7 +2,6 @@ package jp.co.soramitsu.staking.impl.data.repository.datasource
 
 import java.math.BigInteger
 import jp.co.soramitsu.common.base.errors.RewardsNotSupportedWarning
-import jp.co.soramitsu.common.data.network.subquery.ReefRewardsNode
 import jp.co.soramitsu.common.utils.orZero
 import jp.co.soramitsu.common.utils.sumByBigDecimal
 import jp.co.soramitsu.common.utils.sumByBigInteger
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/historySource/ReefHistorySource.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/historySource/ReefHistorySource.kt
index 46b53d82a4..5d1af7333d 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/historySource/ReefHistorySource.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/historySource/ReefHistorySource.kt
@@ -96,11 +96,6 @@ class ReefHistorySource(
         return CursorPage(nextCursor, operations.sortedByDescending { it.time })
     }
 
-    private fun TransactionFilter.isAppliedOrNull(filters: Collection<TransactionFilter>) = when {
-        this in filters -> true
-        else -> null
-    }
-
     private val reefDateFormat by lazy {
         SimpleDateFormat(
             "yyyy-MM-dd'T'HH:mm:ss.SSSSSSZ",
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/blockchain/updaters/BalancesUpdateSystem.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/blockchain/updaters/BalancesUpdateSystem.kt
index 8826796a75..1eae78846e 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/blockchain/updaters/BalancesUpdateSystem.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/blockchain/updaters/BalancesUpdateSystem.kt
@@ -1,30 +1,21 @@
 package jp.co.soramitsu.wallet.impl.data.network.blockchain.updaters
 
 import android.util.Log
-import io.emeraldpay.polkaj.scale.ScaleCodecReader
 import it.airgap.beaconsdk.core.internal.utils.failure
 import it.airgap.beaconsdk.core.internal.utils.onEachFailure
-import java.math.BigInteger
-import java.nio.ByteOrder
 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
 import jp.co.soramitsu.account.api.domain.model.address
 import jp.co.soramitsu.common.data.network.rpc.BulkRetriever
-import jp.co.soramitsu.common.data.network.runtime.binding.AccountData
-import jp.co.soramitsu.common.data.network.runtime.binding.AccountInfo
 import jp.co.soramitsu.common.data.network.runtime.binding.ExtrinsicStatusEvent
 import jp.co.soramitsu.common.data.network.runtime.binding.SimpleBalanceData
-import jp.co.soramitsu.common.data.network.runtime.binding.bindNonce
-import jp.co.soramitsu.common.data.network.runtime.binding.cast
 import jp.co.soramitsu.common.mixin.api.NetworkStateMixin
 import jp.co.soramitsu.common.utils.orZero
 import jp.co.soramitsu.common.utils.requireException
 import jp.co.soramitsu.common.utils.requireValue
-import jp.co.soramitsu.common.utils.system
 import jp.co.soramitsu.core.models.Asset
 import jp.co.soramitsu.core.models.ChainAssetType
-import jp.co.soramitsu.core.runtime.storage.returnType
 import jp.co.soramitsu.core.updater.UpdateSystem
 import jp.co.soramitsu.core.updater.Updater
 import jp.co.soramitsu.core.utils.utilityAsset
@@ -37,14 +28,8 @@ import jp.co.soramitsu.runtime.multiNetwork.getSocket
 import jp.co.soramitsu.runtime.multiNetwork.getSocketOrNull
 import jp.co.soramitsu.runtime.multiNetwork.toSyncIssue
 import jp.co.soramitsu.runtime.network.subscriptionFlowCatching
-import jp.co.soramitsu.shared_utils.extensions.fromUnsignedBytes
 import jp.co.soramitsu.shared_utils.runtime.AccountId
 import jp.co.soramitsu.shared_utils.runtime.RuntimeSnapshot
-import jp.co.soramitsu.shared_utils.runtime.definitions.types.composite.Struct
-import jp.co.soramitsu.shared_utils.runtime.definitions.types.fromHexOrNull
-import jp.co.soramitsu.shared_utils.runtime.metadata.storage
-import jp.co.soramitsu.shared_utils.scale.dataType.uint128
-import jp.co.soramitsu.shared_utils.scale.utils.toUnsignedBytes
 import jp.co.soramitsu.shared_utils.wsrpc.request.runtime.storage.SubscribeStorageRequest
 import jp.co.soramitsu.shared_utils.wsrpc.request.runtime.storage.storageChange
 import jp.co.soramitsu.wallet.api.data.cache.AssetCache
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/subquery/OperationsHistoryApi.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/subquery/OperationsHistoryApi.kt
index bca81368f3..fada86b5dd 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/subquery/OperationsHistoryApi.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/data/network/subquery/OperationsHistoryApi.kt
@@ -2,7 +2,6 @@ package jp.co.soramitsu.wallet.impl.data.network.subquery
 
 import jp.co.soramitsu.common.BuildConfig
 import jp.co.soramitsu.common.data.network.subquery.GiantsquidResponse
-import jp.co.soramitsu.common.data.network.subquery.ReefStakingRewardsResponse
 import jp.co.soramitsu.common.data.network.subquery.SubQueryResponse
 import jp.co.soramitsu.common.data.network.subquery.SubsquidResponse
 import jp.co.soramitsu.wallet.impl.data.network.model.request.GiantsquidHistoryRequest

From 3c11dd58048fd7b0ae5152994ce224901bb2ded6 Mon Sep 17 00:00:00 2001
From: Deneath <lyazgindenis@gmail.com>
Date: Fri, 9 Feb 2024 16:31:59 +0700
Subject: [PATCH 26/35] staking pools fee exception catching

---
 .../impl/presentation/swap_tokens/SwapTokensViewModel.kt     | 4 +++-
 .../confirm/pool/join/ConfirmJoinPoolViewModel.kt            | 5 ++++-
 .../wallet/api/presentation/BaseConfirmViewModel.kt          | 5 ++++-
 3 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/feature-polkaswap-impl/src/main/kotlin/jp/co/soramitsu/polkaswap/impl/presentation/swap_tokens/SwapTokensViewModel.kt b/feature-polkaswap-impl/src/main/kotlin/jp/co/soramitsu/polkaswap/impl/presentation/swap_tokens/SwapTokensViewModel.kt
index 9426d63a14..163b4f209e 100644
--- a/feature-polkaswap-impl/src/main/kotlin/jp/co/soramitsu/polkaswap/impl/presentation/swap_tokens/SwapTokensViewModel.kt
+++ b/feature-polkaswap-impl/src/main/kotlin/jp/co/soramitsu/polkaswap/impl/presentation/swap_tokens/SwapTokensViewModel.kt
@@ -207,7 +207,9 @@ class SwapTokensViewModel @Inject constructor(
         )
         val fee = desiredAsset.token.amountFromPlanks(feeInPlanks)
         emit(LoadingState.Loaded(fee))
-    }.stateIn(viewModelScope, SharingStarted.Eagerly, LoadingState.Loaded(null))
+    }
+        .catch { emit(LoadingState.Loaded(null)) }
+        .stateIn(viewModelScope, SharingStarted.Eagerly, LoadingState.Loaded(null))
 
     private val networkFeeViewStateFlow = networkFeeFlow.map { amountLoading ->
         amountLoading.map {
diff --git a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/confirm/pool/join/ConfirmJoinPoolViewModel.kt b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/confirm/pool/join/ConfirmJoinPoolViewModel.kt
index 5ca854e842..154d671e80 100644
--- a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/confirm/pool/join/ConfirmJoinPoolViewModel.kt
+++ b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/confirm/pool/join/ConfirmJoinPoolViewModel.kt
@@ -22,6 +22,7 @@ import jp.co.soramitsu.wallet.impl.domain.model.amountFromPlanks
 import jp.co.soramitsu.wallet.impl.domain.model.planksFromAmount
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.catch
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.stateIn
 import kotlinx.coroutines.launch
@@ -77,7 +78,9 @@ class ConfirmJoinPoolViewModel @Inject constructor(
             feeFormatted,
             feeFiat
         )
-    }.stateIn(
+    }
+        .catch { emit(defaultFeeState) }
+        .stateIn(
         viewModelScope,
         SharingStarted.Eagerly,
         defaultFeeState
diff --git a/feature-wallet-api/src/main/java/jp/co/soramitsu/wallet/api/presentation/BaseConfirmViewModel.kt b/feature-wallet-api/src/main/java/jp/co/soramitsu/wallet/api/presentation/BaseConfirmViewModel.kt
index d7e028b39e..44f7c761b4 100644
--- a/feature-wallet-api/src/main/java/jp/co/soramitsu/wallet/api/presentation/BaseConfirmViewModel.kt
+++ b/feature-wallet-api/src/main/java/jp/co/soramitsu/wallet/api/presentation/BaseConfirmViewModel.kt
@@ -29,6 +29,7 @@ import jp.co.soramitsu.wallet.impl.domain.model.planksFromAmount
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.catch
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.filterNotNull
 import kotlinx.coroutines.flow.map
@@ -99,7 +100,9 @@ abstract class BaseConfirmViewModel(
             feeFormatted,
             feeFiat
         )
-    }.stateIn(
+    }
+        .catch { emit(defaultFeeState) }
+        .stateIn(
         viewModelScope,
         SharingStarted.Eagerly,
         defaultFeeState

From a929d66a53fa8e222fdeec19bd73d41f9e80b608 Mon Sep 17 00:00:00 2001
From: Deneath <lyazgindenis@gmail.com>
Date: Fri, 9 Feb 2024 16:36:02 +0700
Subject: [PATCH 27/35] request executor

---
 build.gradle                                                  | 2 +-
 .../java/jp/co/soramitsu/common/di/modules/NetworkModule.kt   | 3 ++-
 gradle/libs.versions.toml                                     | 2 +-
 .../main/java/jp/co/soramitsu/testshared/CreateTestSocket.kt  | 4 ++--
 4 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/build.gradle b/build.gradle
index 855d13af62..737b4794ed 100644
--- a/build.gradle
+++ b/build.gradle
@@ -83,7 +83,7 @@ buildscript {
         minifyRelease = true
         beaconVersion = "3.2.4"
 
-        sharedFeaturesVersion = "1.1.1.22-FLW"
+        sharedFeaturesVersion = "1.1.1.23-FLW"
 
         coilDep = "io.coil-kt:coil:$coilVersion"
         coilSvg = "io.coil-kt:coil-svg:$coilVersion"
diff --git a/common/src/main/java/jp/co/soramitsu/common/di/modules/NetworkModule.kt b/common/src/main/java/jp/co/soramitsu/common/di/modules/NetworkModule.kt
index c3e3fc083d..4af739ce87 100644
--- a/common/src/main/java/jp/co/soramitsu/common/di/modules/NetworkModule.kt
+++ b/common/src/main/java/jp/co/soramitsu/common/di/modules/NetworkModule.kt
@@ -20,6 +20,7 @@ import jp.co.soramitsu.common.resources.ResourceManager
 import jp.co.soramitsu.shared_utils.wsrpc.SocketService
 import jp.co.soramitsu.shared_utils.wsrpc.logging.Logger
 import jp.co.soramitsu.shared_utils.wsrpc.recovery.Reconnector
+import jp.co.soramitsu.shared_utils.wsrpc.request.CoroutinesRequestExecutor
 import jp.co.soramitsu.shared_utils.wsrpc.request.RequestExecutor
 import okhttp3.Cache
 import okhttp3.OkHttpClient
@@ -93,7 +94,7 @@ class NetworkModule {
 
     @Provides
     @Singleton
-    fun provideRequestExecutor() = RequestExecutor()
+    fun provideRequestExecutor(): RequestExecutor = CoroutinesRequestExecutor()
 
     @Provides
     fun provideSocketService(
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index fc76b1436c..936fa4203c 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -16,7 +16,7 @@ detekt = "1.23.0"
 kotlin = "1.8.10"
 dagger = "2.47"
 android_plugin = "7.4.2"
-sharedFeaturesVersion = "1.1.1.22-FLW"
+sharedFeaturesVersion = "1.1.1.23-FLW"
 web3j = "4.8.8-android"
 walletconnectBom = "1.18.0"
 coilVersion = "2.2.2"
diff --git a/test-shared/src/main/java/jp/co/soramitsu/testshared/CreateTestSocket.kt b/test-shared/src/main/java/jp/co/soramitsu/testshared/CreateTestSocket.kt
index 2f1441bc93..66a920f71b 100644
--- a/test-shared/src/main/java/jp/co/soramitsu/testshared/CreateTestSocket.kt
+++ b/test-shared/src/main/java/jp/co/soramitsu/testshared/CreateTestSocket.kt
@@ -4,6 +4,6 @@ import com.google.gson.Gson
 import com.neovisionaries.ws.client.WebSocketFactory
 import jp.co.soramitsu.shared_utils.wsrpc.SocketService
 import jp.co.soramitsu.shared_utils.wsrpc.recovery.Reconnector
-import jp.co.soramitsu.shared_utils.wsrpc.request.RequestExecutor
+import jp.co.soramitsu.shared_utils.wsrpc.request.CoroutinesRequestExecutor
 
-fun createTestSocket() = SocketService(Gson(), NoOpLogger, WebSocketFactory(), Reconnector(), RequestExecutor())
+fun createTestSocket() = SocketService(Gson(), NoOpLogger, WebSocketFactory(), Reconnector(), CoroutinesRequestExecutor())

From 54beaa4b2ea7345e0c9f112bb2a8158f57fd9b81 Mon Sep 17 00:00:00 2001
From: Sergey Pankratov <pankratov@soramitsu.co.jp>
Date: Fri, 9 Feb 2024 21:17:57 +0500
Subject: [PATCH 28/35] FLW-4270 XOR. SWAP. History. There is no wallet name
 and no full address

---
 .../account/api/domain/model/MetaAccount.kt   |  7 ++++++
 .../detail/swap/SwapDetailContent.kt          |  5 +++-
 .../detail/swap/SwapDetailViewModel.kt        | 24 +++++++++++++++++--
 3 files changed, 33 insertions(+), 3 deletions(-)

diff --git a/feature-account-api/src/main/java/jp/co/soramitsu/account/api/domain/model/MetaAccount.kt b/feature-account-api/src/main/java/jp/co/soramitsu/account/api/domain/model/MetaAccount.kt
index 986d1c3080..e372d12c6a 100644
--- a/feature-account-api/src/main/java/jp/co/soramitsu/account/api/domain/model/MetaAccount.kt
+++ b/feature-account-api/src/main/java/jp/co/soramitsu/account/api/domain/model/MetaAccount.kt
@@ -135,6 +135,13 @@ fun MetaAccount.address(chain: Chain): String? {
     }
 }
 
+fun LightMetaAccount.address(chain: Chain): String? {
+    return when {
+        chain.isEthereumBased -> ethereumAddress?.ethereumAddressToHex()
+        else -> substrateAccountId.toAddress(chain.addressPrefix.toShort())
+    }
+}
+
 fun MetaAccount.chainAddress(chain: Chain): String? {
     return when {
         hasChainAccount(chain.id) -> chain.addressOf(chainAccounts.getValue(chain.id).accountId)
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/transaction/detail/swap/SwapDetailContent.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/transaction/detail/swap/SwapDetailContent.kt
index a229f3dd16..2dc36db556 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/transaction/detail/swap/SwapDetailContent.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/transaction/detail/swap/SwapDetailContent.kt
@@ -39,6 +39,7 @@ data class SwapDetailState(
     val toTokenName: String,
     val statusAppearance: SwapStatusAppearance,
     val address: String,
+    val addressName: String?,
     val hash: String,
     val fromTokenOnToToken: String,
     val liquidityProviderFee: String,
@@ -110,7 +111,8 @@ fun SwapPreviewContent(
                     ),
                     TitleValueViewState(
                         title = stringResource(R.string.polkaswap_from),
-                        value = state.address
+                        value = state.addressName ?: state.address,
+                        additionalValue = state.address.takeIf { state.addressName != null }
                     ),
                     TitleValueViewState(
                         title = stringResource(R.string.common_date),
@@ -175,6 +177,7 @@ fun SwapDetailContentPreview() {
             fromTokenOnToToken = "0",
             networkFee = "0.0007",
             address = "asdfqwaefgqwef2fr",
+            addressName = "Contact addressbook name",
             hash = "asdfqwaefgqwef2fr",
             statusAppearance = SwapStatusAppearance.COMPLETED,
             time = 1675834923575L,
diff --git a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/transaction/detail/swap/SwapDetailViewModel.kt b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/transaction/detail/swap/SwapDetailViewModel.kt
index e9f368e640..bb2b5bf7b7 100644
--- a/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/transaction/detail/swap/SwapDetailViewModel.kt
+++ b/feature-wallet-impl/src/main/java/jp/co/soramitsu/wallet/impl/presentation/transaction/detail/swap/SwapDetailViewModel.kt
@@ -7,6 +7,8 @@ import androidx.lifecycle.SavedStateHandle
 import dagger.hilt.android.lifecycle.HiltViewModel
 import java.math.BigDecimal
 import javax.inject.Inject
+import jp.co.soramitsu.account.api.domain.interfaces.AccountRepository
+import jp.co.soramitsu.account.api.domain.model.address
 import jp.co.soramitsu.common.base.BaseViewModel
 import jp.co.soramitsu.common.compose.component.GradientIconState
 import jp.co.soramitsu.common.compose.theme.greenText
@@ -16,6 +18,7 @@ import jp.co.soramitsu.common.mixin.api.Browserable
 import jp.co.soramitsu.common.resources.ClipboardManager
 import jp.co.soramitsu.common.resources.ResourceManager
 import jp.co.soramitsu.common.utils.Event
+import jp.co.soramitsu.common.utils.flowOf
 import jp.co.soramitsu.common.utils.formatCryptoDetail
 import jp.co.soramitsu.common.utils.orZero
 import jp.co.soramitsu.feature_wallet_impl.R
@@ -30,6 +33,7 @@ import jp.co.soramitsu.wallet.impl.domain.model.amountFromPlanks
 import jp.co.soramitsu.wallet.impl.presentation.WalletRouter
 import jp.co.soramitsu.wallet.impl.presentation.model.OperationParcelizeModel
 import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.first
 import kotlinx.coroutines.flow.flow
 import kotlinx.coroutines.flow.map
@@ -42,6 +46,7 @@ class SwapDetailViewModel @Inject constructor(
     private val chainRegistry: ChainRegistry,
     private val resourceManager: ResourceManager,
     private val clipboardManager: ClipboardManager,
+    private val accountRepository: AccountRepository,
     savedStateHandle: SavedStateHandle
 ) : BaseViewModel(), SwapDetailCallbacks, Browserable {
 
@@ -78,6 +83,7 @@ class SwapDetailViewModel @Inject constructor(
         toTokenName = swap.targetAsset?.symbol?.uppercase() ?: "???",
         statusAppearance = swap.status.mapToStatusAppearance(),
         address = swap.address,
+        addressName = null,
         hash = swap.hash,
         fromTokenOnToToken = swapRate.formatCryptoDetail(),
         liquidityProviderFee = swap.liquidityProviderFee.formatCryptoDetailFromPlanks(swap.chainAsset),
@@ -87,8 +93,22 @@ class SwapDetailViewModel @Inject constructor(
         isShowSubscanButtons = false
     )
 
-    val state = subscanUrlFlow.map { url ->
-        initialState.copy(isShowSubscanButtons = url.isNullOrEmpty().not())
+    // swaps are only for selected account
+    private val addressNameFlow = flowOf { swap.address }.map {
+        val selectedLightMetaAccount = accountRepository.getSelectedLightMetaAccount()
+        val chain = chainRegistry.getChain(swap.chainAsset.chainId)
+        if (selectedLightMetaAccount.address(chain) == swap.address) {
+            selectedLightMetaAccount.name
+        } else {
+            null
+        }
+    }
+
+    val state = combine(
+        subscanUrlFlow,
+        addressNameFlow
+    ) { url, name ->
+        initialState.copy(isShowSubscanButtons = url.isNullOrEmpty().not(), addressName = name)
     }.stateIn(this, SharingStarted.Eagerly, initialState)
 
     override fun onBackClick() {

From 47b16abd94ec8a9c6ecd0ca275f5df6718c3ff93 Mon Sep 17 00:00:00 2001
From: Deneath <lyazgindenis@gmail.com>
Date: Mon, 12 Feb 2024 14:41:29 +0700
Subject: [PATCH 29/35] increase version

---
 build.gradle | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/build.gradle b/build.gradle
index 737b4794ed..eab9498c3a 100644
--- a/build.gradle
+++ b/build.gradle
@@ -5,8 +5,8 @@ apply plugin: "org.sonarqube"
 buildscript {
     ext {
         // App version
-        versionName = '3.2.2'
-        versionCode = 152
+        versionName = '3.3.1'
+        versionCode = 153
 
         // SDK and tools
         compileSdkVersion = 34

From 978f586a8a30bbf9061dae3aa7a6ba80fc2cca94 Mon Sep 17 00:00:00 2001
From: Deneath <lyazgindenis@gmail.com>
Date: Mon, 12 Feb 2024 18:16:42 +0700
Subject: [PATCH 30/35] Show hash after successfully extrinsics on staking

---
 .../staking/redeem/RedeemConsequences.kt      |  3 ++-
 .../domain/staking/redeem/RedeemInteractor.kt |  3 ++-
 .../rebond/confirm/ConfirmRebondViewModel.kt  | 26 ++++++++++++++-----
 .../staking/redeem/RedeemViewModel.kt         |  1 +
 .../unbond/confirm/ConfirmUnbondViewModel.kt  |  1 +
 5 files changed, 26 insertions(+), 8 deletions(-)

diff --git a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/domain/staking/redeem/RedeemConsequences.kt b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/domain/staking/redeem/RedeemConsequences.kt
index 37e68a3316..e7951c06a9 100644
--- a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/domain/staking/redeem/RedeemConsequences.kt
+++ b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/domain/staking/redeem/RedeemConsequences.kt
@@ -1,5 +1,6 @@
 package jp.co.soramitsu.staking.impl.domain.staking.redeem
 
 class RedeemConsequences(
-    val willKillStash: Boolean
+    val willKillStash: Boolean,
+    val hash: String
 )
diff --git a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/domain/staking/redeem/RedeemInteractor.kt b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/domain/staking/redeem/RedeemInteractor.kt
index c9bd343aac..0f9d2bd527 100644
--- a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/domain/staking/redeem/RedeemInteractor.kt
+++ b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/domain/staking/redeem/RedeemInteractor.kt
@@ -33,7 +33,8 @@ class RedeemInteractor(
                 formExtrinsic.invoke(this)
             }.map {
                 RedeemConsequences(
-                    willKillStash = asset.redeemable == asset.locked
+                    willKillStash = asset.redeemable == asset.locked,
+                    hash = it
                 )
             }
         }
diff --git a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/rebond/confirm/ConfirmRebondViewModel.kt b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/rebond/confirm/ConfirmRebondViewModel.kt
index 3615f59cf0..864cfd4fbd 100644
--- a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/rebond/confirm/ConfirmRebondViewModel.kt
+++ b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/rebond/confirm/ConfirmRebondViewModel.kt
@@ -5,6 +5,8 @@ import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.SavedStateHandle
 import androidx.lifecycle.viewModelScope
 import dagger.hilt.android.lifecycle.HiltViewModel
+import javax.inject.Inject
+import javax.inject.Named
 import jp.co.soramitsu.account.api.presentation.actions.ExternalAccountActions
 import jp.co.soramitsu.common.address.AddressIconGenerator
 import jp.co.soramitsu.common.address.createAddressModel
@@ -34,8 +36,6 @@ import jp.co.soramitsu.wallet.impl.domain.model.planksFromAmount
 import kotlinx.coroutines.flow.first
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.launch
-import javax.inject.Inject
-import javax.inject.Named
 
 @HiltViewModel
 class ConfirmRebondViewModel @Inject constructor(
@@ -68,8 +68,14 @@ class ConfirmRebondViewModel @Inject constructor(
 
     val assetModelFlow = assetFlow
         .map {
-            val retrieveAmount = stakingScenarioInteractor.getRebondAvailableAmount(it, payload.amount)
-            mapAssetToAssetModel(it, resourceManager, { retrieveAmount }, R.string.staking_unbonding_format)
+            val retrieveAmount =
+                stakingScenarioInteractor.getRebondAvailableAmount(it, payload.amount)
+            mapAssetToAssetModel(
+                it,
+                resourceManager,
+                { retrieveAmount },
+                R.string.staking_unbonding_format
+            )
         }
         .inBackground()
         .asLiveData()
@@ -86,7 +92,8 @@ class ConfirmRebondViewModel @Inject constructor(
         val address = it.executionAddress
         val account = interactor.getProjectedAccount(address)
 
-        val addressModel = iconGenerator.createAddressModel(address, AddressIconGenerator.SIZE_SMALL, account.name)
+        val addressModel =
+            iconGenerator.createAddressModel(address, AddressIconGenerator.SIZE_SMALL, account.name)
 
         addressModel
     }
@@ -109,7 +116,10 @@ class ConfirmRebondViewModel @Inject constructor(
         val originAddressModel = originAddressModelLiveData.value ?: return@launch
         val chainId = assetFlow.first().token.configuration.chainId
         val chain = chainRegistry.getChain(chainId)
-        val supportedExplorers = chain.explorers.getSupportedExplorers(BlockExplorerUrlBuilder.Type.ACCOUNT, originAddressModel.address)
+        val supportedExplorers = chain.explorers.getSupportedExplorers(
+            BlockExplorerUrlBuilder.Type.ACCOUNT,
+            originAddressModel.address
+        )
         val externalActionsPayload = ExternalAccountActions.Payload(
             value = originAddressModel.address,
             chainId = chainId,
@@ -166,6 +176,10 @@ class ConfirmRebondViewModel @Inject constructor(
                 showMessage(resourceManager.getString(R.string.common_transaction_submitted))
 
                 router.returnToStakingBalance()
+                router.openOperationSuccess(
+                    it,
+                    validPayload.controllerAsset.token.configuration.chainId
+                )
             }
             .onFailure(::showError)
 
diff --git a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/redeem/RedeemViewModel.kt b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/redeem/RedeemViewModel.kt
index c375d7ad75..7b699a6aa3 100644
--- a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/redeem/RedeemViewModel.kt
+++ b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/redeem/RedeemViewModel.kt
@@ -211,6 +211,7 @@ class RedeemViewModel @Inject constructor(
                 result.requireValue().willKillStash -> router.returnToMain()
                 else -> router.returnToStakingBalance()
             }
+            result.getOrNull()?.let { router.openOperationSuccess(it.hash, redeemValidationPayload.asset.token.configuration.chainId) }
         } else {
             showError(result.requireException())
         }
diff --git a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/unbond/confirm/ConfirmUnbondViewModel.kt b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/unbond/confirm/ConfirmUnbondViewModel.kt
index 9585bc4fd2..c894b74bf4 100644
--- a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/unbond/confirm/ConfirmUnbondViewModel.kt
+++ b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/unbond/confirm/ConfirmUnbondViewModel.kt
@@ -154,6 +154,7 @@ class ConfirmUnbondViewModel @Inject constructor(
             showMessage(resourceManager.getString(R.string.common_transaction_submitted))
 
             router.returnToStakingBalance()
+            result.getOrNull()?.let { router.openOperationSuccess(it, validPayload.asset.token.configuration.chainId) }
         } else {
             showError(result.requireException())
         }

From 5e9a23c50d3dcf3160c7f2a2184dd7bf49e72c6a Mon Sep 17 00:00:00 2001
From: Deneath <lyazgindenis@gmail.com>
Date: Mon, 12 Feb 2024 19:14:04 +0700
Subject: [PATCH 31/35] catch the possible staking states exception in era
 calculator. This will never happen in usual work.

---
 .../impl/data/network/blockhain/bindings/Era.kt      | 12 ++++++------
 .../StakingRelayChainScenarioRepository.kt           |  8 ++++----
 runtime/build.gradle                                 |  2 +-
 3 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/data/network/blockhain/bindings/Era.kt b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/data/network/blockhain/bindings/Era.kt
index 55d5e7344f..f89f494f2b 100644
--- a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/data/network/blockhain/bindings/Era.kt
+++ b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/data/network/blockhain/bindings/Era.kt
@@ -53,31 +53,31 @@ fun bindCurrentEra(
 
 @UseCaseBinding
 fun bindCurrentIndex(
-    scale: String,
+    scale: String?,
     runtime: RuntimeSnapshot
 ): BigInteger {
     val returnType = runtime.metadata.storageReturnType("Session", "CurrentIndex")
 
-    return bindSessionIndex(returnType.fromHexOrNull(runtime, scale))
+    return scale ?. let { bindSessionIndex(returnType.fromHexOrNull(runtime, scale)) } ?: BigInteger.ZERO
 }
 
 @UseCaseBinding
 fun bindCurrentSlot(
-    scale: String,
+    scale: String?,
     runtime: RuntimeSnapshot
 ): BigInteger {
     val returnType = runtime.metadata.storageReturnType("Babe", "CurrentSlot")
 
-    return bindSlot(returnType.fromHexOrNull(runtime, scale))
+    return scale?.let { bindSlot(returnType.fromHexOrNull(runtime, scale)) } ?: BigInteger.ZERO
 }
 
 @UseCaseBinding
 fun bindErasStartSessionIndex(
-    scale: String,
+    scale: String?,
     runtime: RuntimeSnapshot
 ): BigInteger {
     val returnType = runtime.metadata.storageReturnType("Staking", "ErasStartSessionIndex")
-    val decoded = returnType.fromHexOrNull(runtime, scale)
+    val decoded = scale?.let { returnType.fromHexOrNull(runtime, scale) }
 
     return bindSessionIndex(decoded)
 }
diff --git a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/scenarios/relaychain/StakingRelayChainScenarioRepository.kt b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/scenarios/relaychain/StakingRelayChainScenarioRepository.kt
index 5936c3dc48..c51d0758f0 100644
--- a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/scenarios/relaychain/StakingRelayChainScenarioRepository.kt
+++ b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/scenarios/relaychain/StakingRelayChainScenarioRepository.kt
@@ -99,20 +99,20 @@ class StakingRelayChainScenarioRepository(
         return runtime.metadata.babe().numberConstant("EpochDuration", runtime) // How many blocks per session
     }
 
-    suspend fun currentSessionIndex(chainId: ChainId) = remoteStorage.queryNonNull(
+    suspend fun currentSessionIndex(chainId: ChainId) = remoteStorage.query(
         // Current session index
         keyBuilder = { it.metadata.session().storage("CurrentIndex").storageKey() },
         binding = ::bindCurrentIndex,
         chainId = chainId
     )
 
-    suspend fun currentSlot(chainId: ChainId) = remoteStorage.queryNonNull(
+    suspend fun currentSlot(chainId: ChainId) = remoteStorage.query(
         keyBuilder = { it.metadata.babe().storage("CurrentSlot").storageKey() },
         binding = ::bindCurrentSlot,
         chainId = chainId
     )
 
-    suspend fun genesisSlot(chainId: ChainId) = remoteStorage.queryNonNull(
+    suspend fun genesisSlot(chainId: ChainId) = remoteStorage.query(
         keyBuilder = { it.metadata.babe().storage("GenesisSlot").storageKey() },
         binding = ::bindCurrentSlot,
         chainId = chainId
@@ -120,7 +120,7 @@ class StakingRelayChainScenarioRepository(
 
     suspend fun eraStartSessionIndex(chainId: ChainId, currentEra: BigInteger): EraIndex {
         val runtime = runtimeFor(chainId)
-        return remoteStorage.queryNonNull( // Index of session from with the era started
+        return remoteStorage.query( // Index of session from with the era started
             keyBuilder = { it.metadata.staking().storage("ErasStartSessionIndex").storageKey(runtime, currentEra) },
             binding = ::bindErasStartSessionIndex,
             chainId = chainId
diff --git a/runtime/build.gradle b/runtime/build.gradle
index 1a8b4ef3e3..d39de13bc1 100644
--- a/runtime/build.gradle
+++ b/runtime/build.gradle
@@ -23,7 +23,7 @@ android {
         }
 
         release {
-            buildConfigField "String", "CHAINS_URL", "\"https://raw.githubusercontent.com/soramitsu/shared-features-utils/master/chains/v7/chains.json\""
+            buildConfigField "String", "CHAINS_URL", "\"https://raw.githubusercontent.com/soramitsu/shared-features-utils/develop-free/chains/v7/chains_dev.json\""
         }
     }
 

From 1cf7a1ed9fc5830e3a1763142d97931e406d944a Mon Sep 17 00:00:00 2001
From: Deneath <lyazgindenis@gmail.com>
Date: Mon, 12 Feb 2024 19:18:21 +0700
Subject: [PATCH 32/35] fix staked value formatting

---
 .../impl/presentation/staking/main/StakingViewStateOld.kt       | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/main/StakingViewStateOld.kt b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/main/StakingViewStateOld.kt
index f019ef0f73..6b8dfdbe3e 100644
--- a/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/main/StakingViewStateOld.kt
+++ b/feature-staking-impl/src/main/java/jp/co/soramitsu/staking/impl/presentation/staking/main/StakingViewStateOld.kt
@@ -206,7 +206,7 @@ sealed class StakeViewState<S>(
 
         return StakeSummaryModel(
             status = summary.status,
-            totalStaked = summary.totalStaked.formatCrypto(tokenType.symbol),
+            totalStaked = summary.totalStaked.formatCryptoDetail(tokenType.symbol),
             totalStakedFiat = token.fiatAmount(summary.totalStaked)?.formatFiat(token.fiatSymbol),
             totalRewards = summary.totalReward.formatCryptoDetail(tokenType.symbol),
             totalRewardsFiat = token.fiatAmount(summary.totalReward)?.formatFiat(token.fiatSymbol),

From d4486c98606fc6ab1153932c25f7519136b28f22 Mon Sep 17 00:00:00 2001
From: Deneath <lyazgindenis@gmail.com>
Date: Mon, 12 Feb 2024 19:19:08 +0700
Subject: [PATCH 33/35] switch release chains.json back to master

---
 runtime/build.gradle | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/runtime/build.gradle b/runtime/build.gradle
index d39de13bc1..1a8b4ef3e3 100644
--- a/runtime/build.gradle
+++ b/runtime/build.gradle
@@ -23,7 +23,7 @@ android {
         }
 
         release {
-            buildConfigField "String", "CHAINS_URL", "\"https://raw.githubusercontent.com/soramitsu/shared-features-utils/develop-free/chains/v7/chains_dev.json\""
+            buildConfigField "String", "CHAINS_URL", "\"https://raw.githubusercontent.com/soramitsu/shared-features-utils/master/chains/v7/chains.json\""
         }
     }
 

From bf7ca0d458df1cf8c6413c82a7c23f3d09557f9a Mon Sep 17 00:00:00 2001
From: Deneath <lyazgindenis@gmail.com>
Date: Tue, 13 Feb 2024 15:32:20 +0700
Subject: [PATCH 34/35] increase versionCode

---
 build.gradle | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/build.gradle b/build.gradle
index eab9498c3a..8403fd1dce 100644
--- a/build.gradle
+++ b/build.gradle
@@ -6,7 +6,7 @@ buildscript {
     ext {
         // App version
         versionName = '3.3.1'
-        versionCode = 153
+        versionCode = 154
 
         // SDK and tools
         compileSdkVersion = 34

From b37ce6fc6b277bb428b84bba4d8e70a3338576dc Mon Sep 17 00:00:00 2001
From: Deneath <lyazgindenis@gmail.com>
Date: Tue, 13 Feb 2024 18:43:22 +0700
Subject: [PATCH 35/35] switch to chains V8, increase version code

---
 build.gradle         | 2 +-
 runtime/build.gradle | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/build.gradle b/build.gradle
index 8403fd1dce..e7a1355985 100644
--- a/build.gradle
+++ b/build.gradle
@@ -6,7 +6,7 @@ buildscript {
     ext {
         // App version
         versionName = '3.3.1'
-        versionCode = 154
+        versionCode = 155
 
         // SDK and tools
         compileSdkVersion = 34
diff --git a/runtime/build.gradle b/runtime/build.gradle
index 1a8b4ef3e3..90fba27a5f 100644
--- a/runtime/build.gradle
+++ b/runtime/build.gradle
@@ -23,7 +23,7 @@ android {
         }
 
         release {
-            buildConfigField "String", "CHAINS_URL", "\"https://raw.githubusercontent.com/soramitsu/shared-features-utils/master/chains/v7/chains.json\""
+            buildConfigField "String", "CHAINS_URL", "\"https://raw.githubusercontent.com/soramitsu/shared-features-utils/master/chains/v8/chains.json\""
         }
     }