diff --git a/Podfile.lock b/Podfile.lock index 90f8a86a24..450eab24dc 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -99,7 +99,7 @@ DEPENDENCIES: - SwiftyBeaver SPEC REPOS: - https://github.com/CocoaPods/Specs.git: + https://github.com/cocoapods/Specs.git: - Charts - CocoaLumberjack - Cuckoo diff --git a/fearless.xcodeproj/project.pbxproj b/fearless.xcodeproj/project.pbxproj index e3983f2b79..caa0048c16 100644 --- a/fearless.xcodeproj/project.pbxproj +++ b/fearless.xcodeproj/project.pbxproj @@ -3,12 +3,13 @@ archiveVersion = 1; classes = { }; - objectVersion = 54; + objectVersion = 52; objects = { /* Begin PBXBuildFile section */ 002561414AF1F8F3B4B65538 /* WalletTransactionDetailsWireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7416F3AFA5F4D1130B1C410 /* WalletTransactionDetailsWireframe.swift */; }; 0077B6854FDCA7ECCD557B09 /* StakingPoolCreateViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D651E438F86F37CC07D6D3F /* StakingPoolCreateViewController.swift */; }; + 02EC6059AEE8C92B4EDD09C0 /* LiquidityPoolsOverviewViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC0B2D0A77F4B0F7CC9E7C1D /* LiquidityPoolsOverviewViewLayout.swift */; }; 02FA6FDF7212F1F8D056BC18 /* SwapTransactionDetailAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = C597BAB74DF23914B68FDC39 /* SwapTransactionDetailAssembly.swift */; }; 04A17615051F4A1AE0E63BF8 /* PolkaswapSwapConfirmationViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F67BB672040911E4A165446 /* PolkaswapSwapConfirmationViewLayout.swift */; }; 04F9CF04588676D79EFB8570 /* ClaimCrowdloanRewardsAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBAA28C551344F1457D76DD5 /* ClaimCrowdloanRewardsAssembly.swift */; }; @@ -16,20 +17,8 @@ 05A6BB4F8F0912404A4D8413 /* WalletTransactionDetailsPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82FD4E0BB1ABA364AFD2E891 /* WalletTransactionDetailsPresenter.swift */; }; 06197BBE4299DC971C42DB92 /* WalletSendConfirmPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A687FBDA0912F8727CE0D81 /* WalletSendConfirmPresenter.swift */; }; 0678271BE1BA5BBC084F478A /* RecommendedValidatorListWireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57C624E71FCE0FFF8EAD5BA9 /* RecommendedValidatorListWireframe.swift */; }; + 06826AA6DBAEA5BBF45BB5CA /* LiquidityPoolSupplyConfirmInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4594686D10DBB7627B8C9A12 /* LiquidityPoolSupplyConfirmInteractor.swift */; }; 069C7D4C9648112115B90234 /* NftSendConfirmProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20EB6F377A05C11850066B9F /* NftSendConfirmProtocols.swift */; }; - 070179612BC7F91600908C83 /* ChainAssetListViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 070179602BC7F91600908C83 /* ChainAssetListViewLayout.swift */; }; - 070179712BCA3D4F00908C83 /* AssetManagementViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 070179652BCA3D4F00908C83 /* AssetManagementViewModel.swift */; }; - 070179722BCA3D4F00908C83 /* AssetManagementViewModelFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 070179662BCA3D4F00908C83 /* AssetManagementViewModelFactory.swift */; }; - 070179732BCA3D4F00908C83 /* AssetManagementInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 070179672BCA3D4F00908C83 /* AssetManagementInteractor.swift */; }; - 070179742BCA3D4F00908C83 /* AssetManagementAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 070179682BCA3D4F00908C83 /* AssetManagementAssembly.swift */; }; - 070179752BCA3D4F00908C83 /* AssetManagementRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 070179692BCA3D4F00908C83 /* AssetManagementRouter.swift */; }; - 070179762BCA3D4F00908C83 /* AssetManagementPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0701796A2BCA3D4F00908C83 /* AssetManagementPresenter.swift */; }; - 070179772BCA3D4F00908C83 /* AssetManagementViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0701796B2BCA3D4F00908C83 /* AssetManagementViewController.swift */; }; - 070179782BCA3D4F00908C83 /* AssetManagementTableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0701796D2BCA3D4F00908C83 /* AssetManagementTableCell.swift */; }; - 070179792BCA3D4F00908C83 /* AssetManagementTableHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0701796E2BCA3D4F00908C83 /* AssetManagementTableHeaderView.swift */; }; - 0701797A2BCA3D4F00908C83 /* AssetManagementProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0701796F2BCA3D4F00908C83 /* AssetManagementProtocols.swift */; }; - 0701797B2BCA3D4F00908C83 /* AssetManagementViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 070179702BCA3D4F00908C83 /* AssetManagementViewLayout.swift */; }; - 0701797D2BCA3D6100908C83 /* WalletAssetsObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0701797C2BCA3D6100908C83 /* WalletAssetsObserver.swift */; }; 0702B31529701759003519F5 /* AmountInputViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0702B31429701759003519F5 /* AmountInputViewModel.swift */; }; 0702B31829701864003519F5 /* WalletViewModelObserverContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0702B31729701864003519F5 /* WalletViewModelObserverContainer.swift */; }; 0702B31A29701884003519F5 /* MoneyPresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0702B31929701884003519F5 /* MoneyPresentable.swift */; }; @@ -52,10 +41,6 @@ 070B2C5F289CE49700F78F82 /* SelectableListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 070B2C5D289CE49700F78F82 /* SelectableListViewController.swift */; }; 070B2C61289CFE0000F78F82 /* SelectedNetworkButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 070B2C60289CFE0000F78F82 /* SelectedNetworkButton.swift */; }; 070CDD6D2ACAACB900F3F20A /* EthereumRemoteBalanceFetching.swift in Sources */ = {isa = PBXBuildFile; fileRef = 070CDD6C2ACAACB900F3F20A /* EthereumRemoteBalanceFetching.swift */; }; - 070CDD702ACACEDA00F3F20A /* QRMatcherProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 070CDD6F2ACACEDA00F3F20A /* QRMatcherProtocol.swift */; }; - 070CDD752ACAE04100F3F20A /* SoraQRInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 070CDD742ACAE04100F3F20A /* SoraQRInfo.swift */; }; - 070CDD772ACAE05D00F3F20A /* CexQRInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 070CDD762ACAE05D00F3F20A /* CexQRInfo.swift */; }; - 070CDD792ACBE19100F3F20A /* BokoloCashQRInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 070CDD782ACBE19000F3F20A /* BokoloCashQRInfo.swift */; }; 070CDD842ACBE59700F3F20A /* ReceiveAssetViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 070CDD7B2ACBE59700F3F20A /* ReceiveAssetViewModel.swift */; }; 070CDD852ACBE59700F3F20A /* ReceiveAndRequestAssetRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 070CDD7C2ACBE59700F3F20A /* ReceiveAndRequestAssetRouter.swift */; }; 070CDD862ACBE59700F3F20A /* ReceiveAndRequestAssetViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 070CDD7D2ACBE59700F3F20A /* ReceiveAndRequestAssetViewLayout.swift */; }; @@ -84,30 +69,17 @@ 073417B3298BA28300104F41 /* EquilibriumTotalBalanceServiceFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 073417B0298BA28300104F41 /* EquilibriumTotalBalanceServiceFactory.swift */; }; 073417B4298BA28300104F41 /* EquilibriumTotalWalletService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 073417B1298BA28300104F41 /* EquilibriumTotalWalletService.swift */; }; 07349F3228FE5EEB00A802B9 /* SwipeCellButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07349F3128FE5EEB00A802B9 /* SwipeCellButton.swift */; }; - 0739FD2C2BFB4A71009ADD7C /* EraStakersFetching.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0739FD292BFB4A70009ADD7C /* EraStakersFetching.swift */; }; - 0739FD2D2BFB4A71009ADD7C /* DefaultEraStakersFetching.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0739FD2A2BFB4A70009ADD7C /* DefaultEraStakersFetching.swift */; }; - 0739FD2E2BFB4A71009ADD7C /* LegacyEraStakersFetching.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0739FD2B2BFB4A70009ADD7C /* LegacyEraStakersFetching.swift */; }; - 0739FD322BFB4B98009ADD7C /* ErasStakersOverviewKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0739FD2F2BFB4B98009ADD7C /* ErasStakersOverviewKey.swift */; }; - 0739FD332BFB4B98009ADD7C /* ErasStakersPagedKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0739FD302BFB4B98009ADD7C /* ErasStakersPagedKey.swift */; }; 073B34BC2AE8CC4500DC5106 /* WalletConnectDisconnectService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 073B34BB2AE8CC4500DC5106 /* WalletConnectDisconnectService.swift */; }; 073B34BF2AE91FE600DC5106 /* WalletConnectProposalDataValidating.swift in Sources */ = {isa = PBXBuildFile; fileRef = 073B34BE2AE91FE600DC5106 /* WalletConnectProposalDataValidating.swift */; }; - 074D832D2BCA490900AD1336 /* UIImage+Monochrome.swift in Sources */ = {isa = PBXBuildFile; fileRef = 074D832C2BCA490900AD1336 /* UIImage+Monochrome.swift */; }; - 074D832F2BCA496300AD1336 /* ChainAssetListBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 074D832E2BCA496300AD1336 /* ChainAssetListBuilder.swift */; }; - 074D83312BCA49BF00AD1336 /* UIImageView+Shimmered.swift in Sources */ = {isa = PBXBuildFile; fileRef = 074D83302BCA49BF00AD1336 /* UIImageView+Shimmered.swift */; }; - 074D83332BCA4A4200AD1336 /* AssetManagementMigrator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 074D83322BCA4A4200AD1336 /* AssetManagementMigrator.swift */; }; - 074D83382BCA946200AD1336 /* AccountInfoRemoteService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 074D83372BCA946200AD1336 /* AccountInfoRemoteService.swift */; }; - 074D833B2BCAAE7C00AD1336 /* Requests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 074D833A2BCAAE7C00AD1336 /* Requests.swift */; }; 074EB7AA290B9E20000A2A6A /* ApplicationStatusAlertEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 074EB7A9290B9E20000A2A6A /* ApplicationStatusAlertEvent.swift */; }; 074EB7AD290B9F64000A2A6A /* AddressCopiedEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 074EB7AC290B9F64000A2A6A /* AddressCopiedEvent.swift */; }; 074EB7AF290BA057000A2A6A /* ConnectionOfflineEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 074EB7AE290BA056000A2A6A /* ConnectionOfflineEvent.swift */; }; 074EB7B1290BA142000A2A6A /* ConnectionOnlineEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 074EB7B0290BA142000A2A6A /* ConnectionOnlineEvent.swift */; }; - 075A2F0A2BF722F300CE6F24 /* ExternalApiExplorerType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 075A2F092BF722F300CE6F24 /* ExternalApiExplorerType.swift */; }; 075C647028098AFB00A55094 /* EthereumConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 075C646F28098AFB00A55094 /* EthereumConstants.swift */; }; 075FC63528D9AB1600E25263 /* CommonInputViewV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 075FC63428D9AB1600E25263 /* CommonInputViewV2.swift */; }; 0761DEB228E1F54D00B90D2C /* StakingPoolCreateViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0761DEB128E1F54D00B90D2C /* StakingPoolCreateViewModel.swift */; }; 0761DEB428E1F57600B90D2C /* StakingPoolCreateViewModelFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0761DEB328E1F57600B90D2C /* StakingPoolCreateViewModelFactory.swift */; }; 0765296D2AD9517E00BA1D99 /* PolkaswapService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0765296C2AD9517E00BA1D99 /* PolkaswapService.swift */; }; - 0768FBBE2BDCEDC300FB126F /* ChainConnectionVisibilityHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0768FBBD2BDCEDC300FB126F /* ChainConnectionVisibilityHelper.swift */; }; 07696A2D28BDC81F00B17040 /* ReaderWriterLock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07696A2C28BDC81F00B17040 /* ReaderWriterLock.swift */; }; 076D9D2C29370C33002762E3 /* MarketButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 076D9D2B29370C33002762E3 /* MarketButton.swift */; }; 076D9D2E2939B780002762E3 /* PolkaswapOperationFactoryProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 076D9D2D2939B77F002762E3 /* PolkaswapOperationFactoryProtocol.swift */; }; @@ -217,15 +189,13 @@ 07DFA471289B8D8E0035A8AB /* EducationStoriesAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07DFA466289B8D8E0035A8AB /* EducationStoriesAssembly.swift */; }; 07DFA472289B8D8E0035A8AB /* EducationStoriesViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07DFA467289B8D8E0035A8AB /* EducationStoriesViewState.swift */; }; 07E346D4288E616E00A8FAEC /* WalletBalanceBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07E346D3288E616E00A8FAEC /* WalletBalanceBuilder.swift */; }; + 07ED2EB92C341A0100FF7500 /* NodeApiKeyInjector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07ED2EB82C341A0100FF7500 /* NodeApiKeyInjector.swift */; }; 07F2B75728A3A4B800280C38 /* ChainCollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07F2B75628A3A4B800280C38 /* ChainCollectionView.swift */; }; 07F2B75C28A6565500280C38 /* assets.json in Resources */ = {isa = PBXBuildFile; fileRef = 07F2B75A28A6533900280C38 /* assets.json */; }; 07F2B75D28A6565900280C38 /* chains.json in Resources */ = {isa = PBXBuildFile; fileRef = 07F2B75B28A6535B00280C38 /* chains.json */; }; 07F2B75F28AA183C00280C38 /* PrintTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07F2B75E28AA183C00280C38 /* PrintTimer.swift */; }; 07F2B76128AB806400280C38 /* SnapshotHotBootBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07F2B76028AB806400280C38 /* SnapshotHotBootBuilder.swift */; }; 07F2B76328ACDA7800280C38 /* RuntimeHotBootSnapshotFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07F2B76228ACDA7800280C38 /* RuntimeHotBootSnapshotFactory.swift */; }; - 07F44F032BE4C7FF00570143 /* Web3 in Frameworks */ = {isa = PBXBuildFile; productRef = 07F44F022BE4C7FF00570143 /* Web3 */; }; - 07F44F052BE4C7FF00570143 /* Web3ContractABI in Frameworks */ = {isa = PBXBuildFile; productRef = 07F44F042BE4C7FF00570143 /* Web3ContractABI */; }; - 07F44F072BE4C7FF00570143 /* Web3PromiseKit in Frameworks */ = {isa = PBXBuildFile; productRef = 07F44F062BE4C7FF00570143 /* Web3PromiseKit */; }; 07F67CA32ACFC4910044047D /* WalletConnectCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07F67CA22ACFC4910044047D /* WalletConnectCoordinator.swift */; }; 07F67CA52ACFEADB0044047D /* BigUInt+EthereumQuantity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07F67CA42ACFEADB0044047D /* BigUInt+EthereumQuantity.swift */; }; 07F817F72AD4051A00B87358 /* Interaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07F817F62AD4051A00B87358 /* Interaction.swift */; }; @@ -249,6 +219,7 @@ 0D02CBA6399C508D9F25AC8D /* PolkaswapAdjustmentAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FC428EB695A80397BDC621C /* PolkaswapAdjustmentAssembly.swift */; }; 0D05777212DFA8CFC5A692E3 /* WalletsManagmentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2970944BE4B937A39E07C608 /* WalletsManagmentViewController.swift */; }; 0D6C27413F73190438306EC1 /* NetworkInfoInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA8D61B74FE9C5199FD0AEBC /* NetworkInfoInteractor.swift */; }; + 0D7DDA00BBF1D0CFD9A26306 /* LiquidityPoolSupplyProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FB7091F743BBACC09553298 /* LiquidityPoolSupplyProtocols.swift */; }; 0DAA7B1B7DF576C761DEF046 /* WalletSendConfirmWireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A22A2EB487E282DCA93C676 /* WalletSendConfirmWireframe.swift */; }; 0DAEDA34F5BCECE5BD64DF26 /* WalletTransactionHistoryWireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B3B14C046584AAAF483715F /* WalletTransactionHistoryWireframe.swift */; }; 0E30EB59B860DE611FF0DC7D /* NftCollectionRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92E3687D398A32597A888B82 /* NftCollectionRouter.swift */; }; @@ -257,8 +228,10 @@ 0EFEBFB39CE4B0A61B6CD914 /* NftSendConfirmInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C542733CEFB871FCD23195E /* NftSendConfirmInteractor.swift */; }; 0F3E58FC800ED8722589F89E /* ReferralCrowdloanPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C503100478AB56E903598A78 /* ReferralCrowdloanPresenter.swift */; }; 0FB6781AB0186A1ED474CAD6 /* StakingUnbondConfirmProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADD348E749EC6A7E3BB069DE /* StakingUnbondConfirmProtocols.swift */; }; + 1029947E04F64B616E252949 /* LiquidityPoolSupplyConfirmPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06F6B892F62579DE761073CA /* LiquidityPoolSupplyConfirmPresenter.swift */; }; 1062C095BC566A1EA8DE1C06 /* CrowdloanContributionSetupViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C71DEF78B69F017DF460AB7 /* CrowdloanContributionSetupViewController.swift */; }; 10B4951F5E0C515EFBDBC32E /* StakingPoolCreateConfirmPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3837CE5CB2D48D8A694A7EE0 /* StakingPoolCreateConfirmPresenter.swift */; }; + 10DEF797CB3DC5BF0903EC4C /* LiquidityPoolRemoveLiquidityConfirmViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3459F610D6E5C782D8695A9 /* LiquidityPoolRemoveLiquidityConfirmViewLayout.swift */; }; 134AFD616BE52A1AE290EEF7 /* StakingBalanceFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = C67ACC943DA07FC529AE69B4 /* StakingBalanceFlow.swift */; }; 135CEEC5363BE34130958578 /* ControllerAccountConfirmationInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B8473AA386E1AD6F0F0C964 /* ControllerAccountConfirmationInteractor.swift */; }; 1496E87A7652C7D230A9BB46 /* AssetNetworksRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36A3D64FF58C40E5CC6A6E89 /* AssetNetworksRouter.swift */; }; @@ -277,6 +250,7 @@ 1BFC90E1D8646F7429FFD5E6 /* ExportMnemonicProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF3AD755B2B3DCFB3D14DF91 /* ExportMnemonicProtocols.swift */; }; 1CBFE5F285223EA5D5300C49 /* WalletMainContainerProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8312AF0B70350EE27DB5B4A /* WalletMainContainerProtocols.swift */; }; 1DE31955634007BAC3B63158 /* ChainAccountTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AEA7ECB8434DF494D2B25B9 /* ChainAccountTests.swift */; }; + 1E59CE2953F8835954A4E5A7 /* LiquidityPoolsOverviewPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BA8DC8007FC0A322C6DF00E /* LiquidityPoolsOverviewPresenter.swift */; }; 1E766A1656C2117F3F64769A /* NetworkManagementTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FFEB823BE0057CFB78CC033 /* NetworkManagementTests.swift */; }; 1EF031DB5316E1D180089C7B /* PolkaswapAdjustmentInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F9F3C33EF043B3EA5FFBC45 /* PolkaswapAdjustmentInteractor.swift */; }; 1F6A32CBF7B43390AF412B1A /* NodeSelectionWireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80809FE46E7B8EBDE3680706 /* NodeSelectionWireframe.swift */; }; @@ -284,8 +258,11 @@ 1F88F3DBFA0BD6D0FDF558F3 /* SelectValidatorsConfirmViewFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 975DECE71DE70DFD866B8E23 /* SelectValidatorsConfirmViewFactory.swift */; }; 20B2942A4241F6713A1C70D9 /* StakingRewardDetailsViewFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2377F8FB07B47637346249F5 /* StakingRewardDetailsViewFactory.swift */; }; 20F28EF4AD17FC56A5A6697B /* NftSendPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C62522E202A1C5EE60D25122 /* NftSendPresenter.swift */; }; + 225493AF467A54A56F74FFF5 /* LiquidityPoolsOverviewProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = A692D227372B24F922EFA058 /* LiquidityPoolsOverviewProtocols.swift */; }; 23398AEC756086FEEEE91E65 /* WalletsManagmentRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B55A4C7E8BD87A7C8634ADD /* WalletsManagmentRouter.swift */; }; 237AD34CD1C2778834D7B330 /* AnalyticsValidatorsViewFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6F8BBBA9EABA266B288333F /* AnalyticsValidatorsViewFactory.swift */; }; + 23E30A21620831C600CBC1D6 /* LiquidityPoolDetailsRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28E3B4BA1160B87C435C2AAF /* LiquidityPoolDetailsRouter.swift */; }; + 24E6794278FEC01DFFE7C69C /* LiquidityPoolSupplyConfirmViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D430E8B808864B281A62AB43 /* LiquidityPoolSupplyConfirmViewController.swift */; }; 2510425D74B7318818B57B0F /* PolkaswapTransaktionSettingsProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFC6DBA90336C1C8A40F3601 /* PolkaswapTransaktionSettingsProtocols.swift */; }; 2515863D26C9F862AB800C4C /* ContactsViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D39CEB720F336B3A400477E /* ContactsViewLayout.swift */; }; 25381484F16FB930B8A90CE3 /* SelectValidatorsConfirmProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7FE5F01FC9364788A91EFA5 /* SelectValidatorsConfirmProtocols.swift */; }; @@ -320,6 +297,7 @@ 2ED5B5FFD880BA1905051E89 /* StakingUnbondSetupFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD8B6213B00597B3F56F650D /* StakingUnbondSetupFlow.swift */; }; 2FCB062A2D873BD72B795DB3 /* AssetSelectionPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7A0A5EE9BE2862B085712A0 /* AssetSelectionPresenter.swift */; }; 306E249AD210DFAA8C03D435 /* AllDonePresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6A654294D46A966EE99764F /* AllDonePresenter.swift */; }; + 30C7FD6C58F1ED50AFB456FD /* LiquidityPoolRemoveLiquidityAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = C61BE0DFC48282DFDBB820C9 /* LiquidityPoolRemoveLiquidityAssembly.swift */; }; 3133215566E418F40844A60E /* ExportMnemonicWireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2ACA4A5B186EE6D40BFE9D66 /* ExportMnemonicWireframe.swift */; }; 31E260D462BF33CFCDFEBA6C /* AnalyticsRewardDetailsProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE294DDEAB7902D7CE1F1BA1 /* AnalyticsRewardDetailsProtocols.swift */; }; 3229E306230161AA99B14BDD /* StakingRewardPayoutsViewFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 336395FFC4B2104A9651A2DE /* StakingRewardPayoutsViewFactory.swift */; }; @@ -337,6 +315,7 @@ 38BFEDD4B9F31EF2532962BD /* NetworkIssuesNotificationAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DB89A1483E4601F427056B3 /* NetworkIssuesNotificationAssembly.swift */; }; 39218CF5AA701518BD3B0103 /* ExportMnemonicInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 200C6B2C85846AED8CA9451A /* ExportMnemonicInteractor.swift */; }; 39DA5795FB9DBF626B72B5C6 /* StakingPoolInfoAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC516FE0E7682210D0F07FB2 /* StakingPoolInfoAssembly.swift */; }; + 3A4026E96615A1D53DAF12D8 /* LiquidityPoolDetailsViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4900562AFFD45F29F4C5DEF /* LiquidityPoolDetailsViewLayout.swift */; }; 3A7BF8FD79B7130241222C35 /* WalletTransactionHistoryProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AEC13E6950006302AC51B96 /* WalletTransactionHistoryProtocols.swift */; }; 3B0F51B1D1590FAAE73CD36C /* SwapTransactionDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32FDB8843EB793C85B222FDB /* SwapTransactionDetailViewController.swift */; }; 3B9314DE6AFC01CA7EF0DAAA /* SelectValidatorsConfirmFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 364C90F7AD36FD6F6E690D7D /* SelectValidatorsConfirmFlow.swift */; }; @@ -365,6 +344,7 @@ 4470194B729475D683584A6C /* WalletTransactionHistoryInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 375E9A7A1206E366E862D81D /* WalletTransactionHistoryInteractor.swift */; }; 44B20C179522F7E38DAA2441 /* WalletTransactionDetailsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 916347CF697C30CD455F436E /* WalletTransactionDetailsViewController.swift */; }; 4641B3CABB5FE1DCFBEDA379 /* CreateContactPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23CF7E56EC624BDB60290387 /* CreateContactPresenter.swift */; }; + 466B1E0EEC6438F8835AAF2E /* LiquidityPoolRemoveLiquidityViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 835D5A5DD9258786D27BDC23 /* LiquidityPoolRemoveLiquidityViewController.swift */; }; 47995121910705DAE2967AF2 /* ChainSelectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C569B746953D3BA947ACEA8D /* ChainSelectionViewController.swift */; }; 4823ED3F25DD943928D102C9 /* NftSendInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B62896CD1DAB8E534C29C96 /* NftSendInteractor.swift */; }; 4838A35CE767AE1C6A198465 /* WalletsManagmentProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5126D2E4032D179A7D210552 /* WalletsManagmentProtocols.swift */; }; @@ -373,6 +353,7 @@ 496AC83B6434378501B657E0 /* StakingPoolCreateViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = D733A49D80BA2BF400AF23A6 /* StakingPoolCreateViewLayout.swift */; }; 4A520B7081BE2D7604B69354 /* AccountImportWireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85F45A5C6145F863760F4409 /* AccountImportWireframe.swift */; }; 4A63ECA587C601999AAEB974 /* StakingPoolCreateProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EBB77A32A59568B0DACFE5 /* StakingPoolCreateProtocols.swift */; }; + 4A957B3BAC231B70CBC00EC3 /* LiquidityPoolsOverviewViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD8B69E9E18C11EAEC9284B3 /* LiquidityPoolsOverviewViewController.swift */; }; 4C7AC4E214171478AC98A898 /* StakingRewardDestConfirmTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9403C5F9C88A4690C62A204B /* StakingRewardDestConfirmTests.swift */; }; 4D822D169784790EBF173EEE /* WalletMainContainerPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D738FE711DD760B47C0BA65 /* WalletMainContainerPresenter.swift */; }; 4E5CD7B8821FA5298EA1598E /* CrowdloanContributionSetupWireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3574BADE9CF77599048C7010 /* CrowdloanContributionSetupWireframe.swift */; }; @@ -384,6 +365,8 @@ 503DFF0EFCAD0A8B526FEC3A /* SelectMarketViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 320E2207FB549F7C31A80441 /* SelectMarketViewController.swift */; }; 506F0D372BCC8302E513637C /* CrowdloanContributionConfirmWireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA59CE2C7AE548ACA9D66FD7 /* CrowdloanContributionConfirmWireframe.swift */; }; 50758C9BBB27AE5732FF78BA /* StakingRewardPayoutsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFEBC03AB1841681427D38AF /* StakingRewardPayoutsViewController.swift */; }; + 5142E2C6609188D529BB558A /* LiquidityPoolRemoveLiquidityConfirmProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 882D47A501D9D6CCE7B99691 /* LiquidityPoolRemoveLiquidityConfirmProtocols.swift */; }; + 51876200A6B1EDC54609DF46 /* LiquidityPoolRemoveLiquidityProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D49CA5CB156C1EA38BEBE00 /* LiquidityPoolRemoveLiquidityProtocols.swift */; }; 51FC48FA6FD4D2FB1781424D /* ReferralCrowdloanWireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D51D60F19284936A6E9F47D /* ReferralCrowdloanWireframe.swift */; }; 525CCCA7CFD7BE570AD0FCCA /* WalletOptionProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73078ED3B2642FEAF348DB2A /* WalletOptionProtocols.swift */; }; 539340533D8383965751C6D8 /* NodeSelectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B0CF2F98779D3C18D0C0A29 /* NodeSelectionTests.swift */; }; @@ -399,12 +382,16 @@ 59745D3C9602745E1417D2F6 /* ChainSelectionInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83AB0AD3A7CECD061611F60C /* ChainSelectionInteractor.swift */; }; 5980BDE494C9E473E5959C71 /* NftCollectionProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD845193EDFC3A1D0BC73719 /* NftCollectionProtocols.swift */; }; 59838EECC194BB0E6E0AEAA2 /* PolkaswapAdjustmentPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B5D683E7DE3533CA418BD21 /* PolkaswapAdjustmentPresenter.swift */; }; + 5A7D43CA17B84C71E8EEF256 /* LiquidityPoolRemoveLiquidityPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B3E9CA265E5C0F3E83429CE /* LiquidityPoolRemoveLiquidityPresenter.swift */; }; 5C796EF8ED29F564B5D1126B /* CrowdloanContributionConfirmViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F75722D2F921FD1C2D4105D /* CrowdloanContributionConfirmViewController.swift */; }; 5D0665A581B9F8DFDBD0CF7B /* WalletChainAccountDashboardWireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 885A9E2D3619FEFC5ED0C093 /* WalletChainAccountDashboardWireframe.swift */; }; 5DDD2206DF795CF205610455 /* AccountExportPasswordPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31226053044986BC828AA912 /* AccountExportPasswordPresenter.swift */; }; + 5E8504507116E0177D70314B /* LiquidityPoolSupplyViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 438E01C5C877428168E9F3F8 /* LiquidityPoolSupplyViewLayout.swift */; }; 5E9402965D385607E04156DC /* NftDetailsPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32DEDC1A0ED429DD43EC621E /* NftDetailsPresenter.swift */; }; 5F5825D27863628412B672CA /* NftSendConfirmRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 803E71983CD61FFBFE98DA7A /* NftSendConfirmRouter.swift */; }; 607699C7CEEDA3598613DCA0 /* NetworkInfoViewFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EDA19BC3280F1838C687EC8 /* NetworkInfoViewFactory.swift */; }; + 60C22E112CA857A2EA5A129E /* LiquidityPoolsOverviewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC76E7D99A98423180BC572F /* LiquidityPoolsOverviewTests.swift */; }; + 61B5A91FBEF633FCC8D965B6 /* LiquidityPoolsOverviewAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC863A9CE29C63B740C6E4D9 /* LiquidityPoolsOverviewAssembly.swift */; }; 61B9688494251703A6373A1B /* StakingAmountWireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6216F6F1B91F798F07695FB6 /* StakingAmountWireframe.swift */; }; 61E0DC83C1D60D677274D7CE /* AccountExportPasswordViewFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = E11575D8B4F64C2E805372A5 /* AccountExportPasswordViewFactory.swift */; }; 62843B73F8616209F57A66FC /* AssetNetworksProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14611E105279789A149B3755 /* AssetNetworksProtocols.swift */; }; @@ -412,6 +399,7 @@ 64B7826F78B8AE649B1EF08F /* CrowdloanContributionSetupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C01DCD4DA014E8FB50B9F11 /* CrowdloanContributionSetupTests.swift */; }; 65909D701527D99837B439D9 /* StakingRewardDetailsWireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 638A65DAC86BAF9EB4D2F2F8 /* StakingRewardDetailsWireframe.swift */; }; 65E0BC7A96EDE5E52D32A11B /* AllDoneViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A5A7C701EF966BF48D6B9E /* AllDoneViewController.swift */; }; + 66AECEC6A6EB8184114B041E /* LiquidityPoolSupplyRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6503D178156C6407EC848D41 /* LiquidityPoolSupplyRouter.swift */; }; 69DE177B9D1745FEE848E870 /* WalletTransactionDetailsInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B37BB3FF5CDF7EA9D7371B7 /* WalletTransactionDetailsInteractor.swift */; }; 69EF1DC4093AC9AF06D71CF4 /* AnalyticsRewardDetailsViewFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29100320799A2B46836A257B /* AnalyticsRewardDetailsViewFactory.swift */; }; 6A16194632D42862692CC067 /* PolkaswapSwapConfirmationInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9B5FD28F2B9A0B0D8ED3607 /* PolkaswapSwapConfirmationInteractor.swift */; }; @@ -421,9 +409,11 @@ 6B4F5F4FD7820C70FB51A2F9 /* PolkaswapSwapConfirmationAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CA950D301F6605D204E99F3 /* PolkaswapSwapConfirmationAssembly.swift */; }; 6B62E63FB9E379EA19A41464 /* AccountCreateProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48C158C8D1855BCE53636934 /* AccountCreateProtocols.swift */; }; 6BAF97802DB9C640515F47C7 /* StakingMainInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 003FA37F2B240C5D7605340D /* StakingMainInteractor.swift */; }; + 6BF307ADE63FA92389340779 /* LiquidityPoolRemoveLiquidityTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C52B689ECDB43EB0FEE95553 /* LiquidityPoolRemoveLiquidityTests.swift */; }; 6C0289728544A96852CCBF20 /* AddCustomNodeProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = D06A0B252CCD6CAE8C5EDC16 /* AddCustomNodeProtocols.swift */; }; 6C56AB4AE63AB2DC73DE98E0 /* AccountImportInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5CC1FB277A878E9C9B7EAEB /* AccountImportInteractor.swift */; }; 6C846ECBBC99A97D1D15C523 /* ReferralCrowdloanTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9272FED2C00908028F223E5C /* ReferralCrowdloanTests.swift */; }; + 6D0E50CEBCB73C23A75A7F46 /* LiquidityPoolDetailsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CF682B92176E0FED5D7B4DB /* LiquidityPoolDetailsTests.swift */; }; 6D315EFF2B664235D297674E /* AccountImportProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = B29514E516CEAAB159851D95 /* AccountImportProtocols.swift */; }; 6D47EAB127FAB7559A9FA107 /* StakingPayoutConfirmationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3BACB7E24BC87F9218DBBC4 /* StakingPayoutConfirmationViewController.swift */; }; 6D5851FB5F830D55EFDB8B7D /* StakingUnbondSetupProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23A74BDB54D503FA2BFBEF35 /* StakingUnbondSetupProtocols.swift */; }; @@ -432,6 +422,7 @@ 6DA57B4E2F3390624BEA03C1 /* StakingPoolCreateConfirmProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA8ECADDA809DE7932B7A17C /* StakingPoolCreateConfirmProtocols.swift */; }; 6ECD0116CD39D8F55D246864 /* SelectValidatorsConfirmPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B5626189788682A84D4E9D7 /* SelectValidatorsConfirmPresenter.swift */; }; 6FA6FA6944AD6519FB8A2AC0 /* WalletMainContainerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 961642321C9AD1885325A3D7 /* WalletMainContainerViewController.swift */; }; + 6FAC7E8F0DACB3F2AA0BE825 /* LiquidityPoolSupplyConfirmProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCCD9A6B753FD1510D3DD311 /* LiquidityPoolSupplyConfirmProtocols.swift */; }; 705F5EEDD70D6941D138D3F9 /* ContactsInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E4DF941DE0EDEF99A843A9D /* ContactsInteractor.swift */; }; 709ABA5647D7DFF36EBCE73E /* WarningAlertViewFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4B7FA75791904AF541BE380 /* WarningAlertViewFactory.swift */; }; 70EAB410A0106F22C2183847 /* StakingUnbondSetupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61E1CD099F7C30ABE0E8A001 /* StakingUnbondSetupTests.swift */; }; @@ -443,6 +434,7 @@ 7401E7CAEEE6890BE74ACCE1 /* CustomValidatorListViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2956D0C69019DDCDAB2EB34 /* CustomValidatorListViewLayout.swift */; }; 742374EE778D76ABC965E107 /* StakingAmountViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB2349A5057312BDB6C65804 /* StakingAmountViewController.xib */; }; 7489BDA1D23D8DF73E7EB9BC /* UsernameSetupWireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65AD15693E21C869DE1FDD17 /* UsernameSetupWireframe.swift */; }; + 74A39BC366D85CC5FCA78579 /* LiquidityPoolSupplyConfirmViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 641B699003FF648A380F7FA6 /* LiquidityPoolSupplyConfirmViewLayout.swift */; }; 75F3A0D30C8BC050489F4644 /* WalletOptionRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EC386082DDF4DF1ADDCB49D /* WalletOptionRouter.swift */; }; 76214649137E7061F701FE38 /* WalletMainContainerAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E096A576B747C09B14FD38D /* WalletMainContainerAssembly.swift */; }; 762BB1AC2F45142B6319B59F /* NftSendProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = F55184167D22A33EF7FF77AE /* NftSendProtocols.swift */; }; @@ -461,6 +453,8 @@ 7C93FA82996A426E7B8CA06E /* AccountExportPasswordViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27D5AF2F7609ADE855308089 /* AccountExportPasswordViewController.swift */; }; 7CBE9FFAF8394786CA131D4D /* CustomValidatorListProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = F28EDDF9277242505FDDECA1 /* CustomValidatorListProtocols.swift */; }; 7D281FEA78E2E5F44990C184 /* AccountImportPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB8605FD90D8C3553A9897B4 /* AccountImportPresenter.swift */; }; + 7D8D644C5E1695288A0E86C0 /* LiquidityPoolDetailsInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = C53DFFFB3B5B48DB51692EFA /* LiquidityPoolDetailsInteractor.swift */; }; + 7DCC939E882247E141B1DE34 /* LiquidityPoolDetailsAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F6F7AE5AFF3F2E7BADA02BB /* LiquidityPoolDetailsAssembly.swift */; }; 7DFB3D265846A31807E1A663 /* StakingPoolCreateConfirmRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0EE58376751B23A9CEAEE1A /* StakingPoolCreateConfirmRouter.swift */; }; 7E1A03082260E0D31AD394CA /* StakingRewardDetailsProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF891BE39D442C2D06DDF3BB /* StakingRewardDetailsProtocols.swift */; }; 7E3FB57A93AFAE39CF3030C8 /* ClaimCrowdloanRewardsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CCB1AFB751075497345C3E7 /* ClaimCrowdloanRewardsViewController.swift */; }; @@ -537,7 +531,6 @@ 842349C52624E98C0066ACFE /* MultiAddress+Query.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842349C42624E98C0066ACFE /* MultiAddress+Query.swift */; }; 8423ADD026B2C38600057EDD /* ImportantFlowViewFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8423ADCF26B2C38600057EDD /* ImportantFlowViewFactory.swift */; }; 8423ADD226B2C9D000057EDD /* ImportantViewProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8423ADD126B2C9D000057EDD /* ImportantViewProtocol.swift */; }; - 8423B0E0251A759000B8687C /* Chain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8423B0DF251A759000B8687C /* Chain.swift */; }; 8423B0E8251B2DAD00B8687C /* SubstrateOperationFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8423B0E7251B2DAD00B8687C /* SubstrateOperationFactory.swift */; }; 8424308D265B1814003E07EC /* CrowdloanOperationFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8424308C265B1814003E07EC /* CrowdloanOperationFactory.swift */; }; 84243095265B1888003E07EC /* CrowdloanMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84243094265B1888003E07EC /* CrowdloanMetadata.swift */; }; @@ -563,7 +556,6 @@ 8428765F24ADE0BB00D91AD8 /* UserSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8428765E24ADE0BB00D91AD8 /* UserSettings.swift */; }; 8428766724ADF22000D91AD8 /* TransformAnimator+Common.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8428766624ADF22000D91AD8 /* TransformAnimator+Common.swift */; }; 8428766924ADF27D00D91AD8 /* AuthorizationPresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8428766824ADF27D00D91AD8 /* AuthorizationPresentable.swift */; }; - 8428766B24ADF51D00D91AD8 /* UIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8428766A24ADF51D00D91AD8 /* UIViewController.swift */; }; 8428768324AE046300D91AD8 /* LanguageSelectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8428766D24AE046200D91AD8 /* LanguageSelectionViewController.swift */; }; 8428768424AE046300D91AD8 /* LanguageSelectionInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8428766E24AE046200D91AD8 /* LanguageSelectionInteractor.swift */; }; 8428768524AE046300D91AD8 /* LanguageSelectionProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8428766F24AE046200D91AD8 /* LanguageSelectionProtocols.swift */; }; @@ -625,6 +617,7 @@ 8434C9E625403686009E4191 /* CDTransactionHistoryItem+CoreDataDecodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8434C9E525403686009E4191 /* CDTransactionHistoryItem+CoreDataDecodable.swift */; }; 8434C9EA2540AE51009E4191 /* ExtrinsicEraTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8434C9E92540AE51009E4191 /* ExtrinsicEraTests.swift */; }; 8436E94426C853E4003D4EA7 /* RuntimeSnapshotOperationFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8436E94326C853E4003D4EA7 /* RuntimeSnapshotOperationFactory.swift */; }; + 8436E94626C85405003D4EA7 /* RuntimeSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8436E94526C85405003D4EA7 /* RuntimeSnapshot.swift */; }; 8436EDE225895804004D9E97 /* RampProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8436EDE125895804004D9E97 /* RampProvider.swift */; }; 8436EDE725895846004D9E97 /* PurchaseProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8436EDE625895846004D9E97 /* PurchaseProvider.swift */; }; 8436EDEF25896722004D9E97 /* PurchaseAggregator+Default.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8436EDEE25896722004D9E97 /* PurchaseAggregator+Default.swift */; }; @@ -672,6 +665,8 @@ 8444D1742671372800AF6D8C /* BytesCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8444D1732671372800AF6D8C /* BytesCodable.swift */; }; 8444D1BE2671465A00AF6D8C /* CrowdloanBonusServiceError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8444D1BD2671465A00AF6D8C /* CrowdloanBonusServiceError.swift */; }; 84452A6025D037AE00F47EC5 /* ChainStorage+Decodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84452A5F25D037AE00F47EC5 /* ChainStorage+Decodable.swift */; }; + 84452F2B25D5B84200F47EC5 /* RuntimeRegistryServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84452F2A25D5B84200F47EC5 /* RuntimeRegistryServiceProtocol.swift */; }; + 84452F4E25D5BB1C00F47EC5 /* RuntimeCoderFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84452F4D25D5BB1C00F47EC5 /* RuntimeCoderFactory.swift */; }; 84452F5825D5C30600F47EC5 /* FilesRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84452F5725D5C30600F47EC5 /* FilesRepository.swift */; }; 84452F5D25D5CB3B00F47EC5 /* FileManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84452F5C25D5CB3B00F47EC5 /* FileManagerTests.swift */; }; 84452F7425D5E2B300F47EC5 /* runtime-westend.json in Resources */ = {isa = PBXBuildFile; fileRef = 84452F7025D5E2B300F47EC5 /* runtime-westend.json */; }; @@ -1124,6 +1119,7 @@ 84CA68E126BEAC7C003B9453 /* SpecVersionSubscriptionFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CA68E026BEAC7C003B9453 /* SpecVersionSubscriptionFactory.swift */; }; 84CB2250270360AC0041C8C1 /* RelaychainStakingLocalSubscriptionFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CB224F270360AC0041C8C1 /* RelaychainStakingLocalSubscriptionFactory.swift */; }; 84CCBFBC2509709500180F4F /* UIBarButtonItem+Style.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CCBFBB2509709500180F4F /* UIBarButtonItem+Style.swift */; }; + 84CD3570252620FB0081BC0B /* CryptoType+Extrinsic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CD356F252620FB0081BC0B /* CryptoType+Extrinsic.swift */; }; 84CD82AE263C1452001A6F01 /* SubstrateProviderSubscriber.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CD82AD263C1452001A6F01 /* SubstrateProviderSubscriber.swift */; }; 84CD82B3263C30BC001A6F01 /* SubstrateProviderSubscriptionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CD82B2263C30BC001A6F01 /* SubstrateProviderSubscriptionHandler.swift */; }; 84CE69DD2565BB6400559427 /* AboutViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CE69DC2565BB6400559427 /* AboutViewModel.swift */; }; @@ -1315,6 +1311,7 @@ 85A093F6055DDD2E2E9253F2 /* ControllerAccountProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = F829E7F8B39EE7D977001510 /* ControllerAccountProtocols.swift */; }; 85B1B7387F09A8405C4E688A /* WalletSendConfirmTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AF4258723E2FACBBA556D00 /* WalletSendConfirmTests.swift */; }; 872DF7DE5A001DF5B8A4E288 /* StakingBondMoreConfirmationFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BA5883C1103D3A2218D839 /* StakingBondMoreConfirmationFlow.swift */; }; + 87C1FC2909A8360DDBA625E5 /* LiquidityPoolSupplyInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BA528679A82B9A327853804 /* LiquidityPoolSupplyInteractor.swift */; }; 885551F78A5926D16D5AF0CB /* ControllerAccountPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E5CB64B91B35804B3671456 /* ControllerAccountPresenter.swift */; }; 886E8CF81EF2566D98D9693E /* ExportSeedViewFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62FA66143B25AA70B02CE461 /* ExportSeedViewFactory.swift */; }; 887DCCC498EB8472021DCE3E /* PolkaswapSwapConfirmationRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC50F2FF6E8EBC00B56CB86D /* PolkaswapSwapConfirmationRouter.swift */; }; @@ -1324,6 +1321,7 @@ 8A109807FBF5FE089DEDBA8E /* FiltersTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C85AF940D0B379062D292D93 /* FiltersTests.swift */; }; 8A1FC8AEE234C7FEBF7B6B2E /* CrowdloanContributionConfirmTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 385FE8691EA37DE9F562B34E /* CrowdloanContributionConfirmTests.swift */; }; 8A3CC3AAFF6B962CF3BE7BF3 /* CreateContactTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCC952210C0714F32C3AE570 /* CreateContactTests.swift */; }; + 8A957CAF82C856E61054B02F /* LiquidityPoolRemoveLiquidityConfirmViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 916326B6F6651BBC5913B26F /* LiquidityPoolRemoveLiquidityConfirmViewController.swift */; }; 8AEF593AFE8F59F7DC0A5753 /* CustomValidatorListInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 365CAE2753E7D5F9B9DB7D1F /* CustomValidatorListInteractor.swift */; }; 8B292AD8D20AB9AB5DB905B1 /* WalletOptionAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1E3F963A56923FD036280BD /* WalletOptionAssembly.swift */; }; 8B8B79D7DB787E4B553F0825 /* AnalyticsValidatorsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08EB1FC5907B5165836318C4 /* AnalyticsValidatorsTests.swift */; }; @@ -1352,6 +1350,7 @@ 96EBE5F57C97C7A7A525E864 /* SwapTransactionDetailProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC265B5F209B038633AE0E3F /* SwapTransactionDetailProtocols.swift */; }; 982BB3FA25BA6AD5443B24C6 /* NetworkIssuesNotificationPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35EAD41DB1444DA38D8C65E2 /* NetworkIssuesNotificationPresenter.swift */; }; 991BF0BF6DD4D4243073E8C9 /* NftSendConfirmAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D9C58C9D53A7EA34E5CB00C /* NftSendConfirmAssembly.swift */; }; + 991DA2DE1E8A45B0A8B187CD /* LiquidityPoolSupplyConfirmAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 112609AE5629962646248BF0 /* LiquidityPoolSupplyConfirmAssembly.swift */; }; 992A5E2E06A9C0E603A10BF7 /* MainNftContainerInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = C16219B3D0D2A658185C0850 /* MainNftContainerInteractor.swift */; }; 9942034DCB680824831B0AC1 /* AccountCreatePresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEBBEC474F607DD9F2A0F4FD /* AccountCreatePresenter.swift */; }; 99A4B2A357ADEA45EFF515A5 /* AccountExportPasswordProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC404A4071AF571FAC4C1994 /* AccountExportPasswordProtocols.swift */; }; @@ -1371,6 +1370,7 @@ 9F664DA212363F5F2C2B530B /* SelectMarketRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C05A688EA7379572BBCE545 /* SelectMarketRouter.swift */; }; A090FF206B56A0E465C62072 /* CrowdloanListPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86F7A369E31DCB9ABD556EE9 /* CrowdloanListPresenter.swift */; }; A14F444FA808457C16EF826C /* WalletOptionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 193908913A5B241C82672D8A /* WalletOptionViewController.swift */; }; + A1C05D0028CD04C16AB6082F /* LiquidityPoolDetailsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67BDE520860A67C800E7F4AB /* LiquidityPoolDetailsViewController.swift */; }; A29F1452BF0AEB885E6460E2 /* SelectMarketPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E07F60661001B2C505D9C8B /* SelectMarketPresenter.swift */; }; A32E1373E3671D518FFC3BC2 /* YourValidatorListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B90CEC70F101AA25A4C00021 /* YourValidatorListViewController.swift */; }; A3DF7ECA1FB8F458F60D7C8A /* StakingPoolCreateAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = F312CA3A7087424A540614DD /* StakingPoolCreateAssembly.swift */; }; @@ -1378,6 +1378,7 @@ A4FE32D50E4B7CB5B53E0067 /* StakingPoolInfoProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDCB1F95F35D50950D0A021E /* StakingPoolInfoProtocols.swift */; }; A565F118B7ED356099662F03 /* ExportMnemonicTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E32C2DC4CC106A3509BE651D /* ExportMnemonicTests.swift */; }; A5AB7027E1E73E39E4026C5C /* Pods_fearlessTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 59FDAE57EE0A97872E76E6CE /* Pods_fearlessTests.framework */; }; + A5C7F51539B8D93D9186DA2C /* LiquidityPoolRemoveLiquidityViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6419D75A346CE10236161522 /* LiquidityPoolRemoveLiquidityViewLayout.swift */; }; A64E3CA61C6CEE74F2FD9825 /* PolkaswapTransaktionSettingsAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7931155840DACB340284ABBB /* PolkaswapTransaktionSettingsAssembly.swift */; }; A6855830B76B0782A696583A /* AssetNetworksInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = C554924081754A981EB4243E /* AssetNetworksInteractor.swift */; }; A69D3B3F6BF76FA9C3070BBD /* AssetNetworksViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFBFF377F35B254AB3141100 /* AssetNetworksViewLayout.swift */; }; @@ -1523,9 +1524,11 @@ AF8193D9F818638254854232 /* StakingMainProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 470B64C45E547C25FCCCFC33 /* StakingMainProtocols.swift */; }; B02EAF42C91E069FE6872EE0 /* SelectValidatorsConfirmWireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D0E02AA5D3EBA9B94950241 /* SelectValidatorsConfirmWireframe.swift */; }; B071927DF8DD5C3CA84494BA /* RecommendedValidatorListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F61D8973ADEB461DE2AD3E13 /* RecommendedValidatorListViewController.swift */; }; + B112AC02371DE4C1DAD48BB1 /* LiquidityPoolRemoveLiquidityRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25D9454047EBBD8D8A0174A4 /* LiquidityPoolRemoveLiquidityRouter.swift */; }; B15D513381B7626AB90018F0 /* StakingPoolInfoInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C9F68A6BF3D3A6D8234 /* StakingPoolInfoInteractor.swift */; }; B1CCC5B7BF30F6ACA309B112 /* StakingRedeemViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7F5F9B54BE4234C5682BDE /* StakingRedeemViewController.swift */; }; B2E3219218E3F54EEB7D5C3C /* NftSendViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0A0CC21B0CD2A47B9B28841 /* NftSendViewController.swift */; }; + B40863AA7377BFE5F8A30259 /* LiquidityPoolSupplyConfirmTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A43F0468DEBA7500C6B23AF /* LiquidityPoolSupplyConfirmTests.swift */; }; B478746C8342468ECACE3478 /* StakingRewardDetailsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D3BFF5C921FEB356E2C39A4 /* StakingRewardDetailsTests.swift */; }; B51AD1836313CE26F369ED3F /* CustomValidatorListWireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96D540DFC00C25D8F73CFDC3 /* CustomValidatorListWireframe.swift */; }; B58B2D9494687F357821D53D /* AnalyticsValidatorsProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F3B726402D4DB25059EF156 /* AnalyticsValidatorsProtocols.swift */; }; @@ -1534,6 +1537,7 @@ B7E42D9E7CA509D7BE723357 /* PolkaswapTransaktionSettingsRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03EFBB5CE05706ADFEF00796 /* PolkaswapTransaktionSettingsRouter.swift */; }; B893A2515909AB6915196317 /* NetworkInfoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B0E2EDF787BF82F16663215 /* NetworkInfoViewController.swift */; }; BA7AEE82627CFC0AFD69B299 /* RecommendedValidatorListPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA2580363AC3E4A9CD40256E /* RecommendedValidatorListPresenter.swift */; }; + BC2DF589C6623601C39EF8F4 /* LiquidityPoolSupplyPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31F848482B2AD7D6831B0CCE /* LiquidityPoolSupplyPresenter.swift */; }; BD571417BD18C711B76E1D62 /* ExportSeedWireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B4C1B5D56DB69BA0AECF731 /* ExportSeedWireframe.swift */; }; BDE80F08EBEE3B0C95598EA8 /* WalletSendConfirmInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAE152D16E6C78D297BFFC3C /* WalletSendConfirmInteractor.swift */; }; BE3F6213B26F35EB6324DBD8 /* ControllerAccountWireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDB9EDB05686DF11958145E1 /* ControllerAccountWireframe.swift */; }; @@ -1563,8 +1567,6 @@ C603E81128583C2A00007B72 /* StakingMainRelaychainStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = C603E81028583C2A00007B72 /* StakingMainRelaychainStrategy.swift */; }; C61166692B3BFA9000F483C4 /* NftHeaderCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C61166682B3BFA9000F483C4 /* NftHeaderCell.swift */; }; C611666C2B3C03B800F483C4 /* NftHeaderCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C611666B2B3C03B800F483C4 /* NftHeaderCellViewModel.swift */; }; - C615668129309D3900391BF3 /* QRService.swift in Sources */ = {isa = PBXBuildFile; fileRef = C615668029309D3900391BF3 /* QRService.swift */; }; - C61566852930A07900391BF3 /* QRCreationOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = C61566842930A07900391BF3 /* QRCreationOperation.swift */; }; C6264C292799A56E00FCA0DB /* WalletDetailsTableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6264C282799A56E00FCA0DB /* WalletDetailsTableCell.swift */; }; C6264C2C2799C15C00FCA0DB /* WalletDetailsCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6264C2B2799C15C00FCA0DB /* WalletDetailsCellViewModel.swift */; }; C6264C2E2799C7EE00FCA0DB /* WalletDetailsViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6264C2D2799C7EE00FCA0DB /* WalletDetailsViewLayout.swift */; }; @@ -1617,7 +1619,6 @@ C661B3B427DFBA41005F1F7D /* AccountInfoSubscriptionProviderWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = C661B3B327DFBA41005F1F7D /* AccountInfoSubscriptionProviderWrapper.swift */; }; C661B3B627E2E7AB005F1F7D /* AccountCreateChainType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C661B3B527E2E7AB005F1F7D /* AccountCreateChainType.swift */; }; C665E4F029C35801001946D1 /* TimeFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C665E4EF29C35801001946D1 /* TimeFormatter.swift */; }; - C66E68CE2BFC119300A14759 /* OnboardingConfigVersionResolver.swift in Sources */ = {isa = PBXBuildFile; fileRef = C66E68CD2BFC119300A14759 /* OnboardingConfigVersionResolver.swift */; }; C67E780F27B3163B0053346B /* CheckPincodeProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = C67E780E27B3163B0053346B /* CheckPincodeProtocols.swift */; }; C67E781127B318840053346B /* CheckPincodeViewFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = C67E781027B318840053346B /* CheckPincodeViewFactory.swift */; }; C67E781527B31FCB0053346B /* CheckPincodePresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C67E781427B31FCB0053346B /* CheckPincodePresenter.swift */; }; @@ -1672,11 +1673,13 @@ CDDAAAD299F26A8B39DABB65 /* WalletHistoryFilterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2648EEF96694A7FEC94520E8 /* WalletHistoryFilterTests.swift */; }; CE2792E78B14CE02394D8CF4 /* ReferralCrowdloanViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 594BC61689EC942ED0A64A4A /* ReferralCrowdloanViewLayout.swift */; }; CEB3D7F9A5DDA211758DC9BF /* ChainSelectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52A64FCFC95E3841032F910B /* ChainSelectionTests.swift */; }; + CF96BE0B636DA8227E689DDA /* LiquidityPoolDetailsProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FED48DE9B681995E6E4A581 /* LiquidityPoolDetailsProtocols.swift */; }; CFAC59D34B15A2FAC4CD8256 /* WalletMainContainerInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEC72ACCA21471C6A9580180 /* WalletMainContainerInteractor.swift */; }; D1C6EABB48DC3EE254E5A095 /* CrowdloanContributionConfirmPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28F5B57A24265C36A5F19B78 /* CrowdloanContributionConfirmPresenter.swift */; }; D1E085712E7BC0EBF2F4F020 /* WalletTransactionHistoryPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8F8199B216D810B36CD4043 /* WalletTransactionHistoryPresenter.swift */; }; D22D29F8EC4C7522345C8772 /* StakingPoolCreateConfirmViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9416E68AE4D5613E9434226 /* StakingPoolCreateConfirmViewController.swift */; }; D23DD717E3EA941FA78B59C9 /* WalletChainAccountDashboardViewFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB719C069A26244D194C4374 /* WalletChainAccountDashboardViewFactory.swift */; }; + D2A85A5EE89EAAA856EA5C0F /* LiquidityPoolDetailsPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81E9DD6EB14A352635BAC711 /* LiquidityPoolDetailsPresenter.swift */; }; D344C6DAC1F8BB6152BA8DD0 /* RecommendedValidatorListProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C6573C52692E4A56E35FF9 /* RecommendedValidatorListProtocols.swift */; }; D3B48F82A875E301D749AC0B /* StakingUnbondConfirmViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5674162035C7D9F226FA9964 /* StakingUnbondConfirmViewController.swift */; }; D3BB5CACD4790A601BF01AF5 /* NftCollectionInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C7AAA265DB437D2CDDC165E /* NftCollectionInteractor.swift */; }; @@ -1689,6 +1692,7 @@ D83B47B07C0D40A327AC44F7 /* CustomValidatorListViewFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = F52B8815D6AF5E69B145D245 /* CustomValidatorListViewFactory.swift */; }; D8581E5440A19D977E17BFDE /* StakingAmountViewFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = D39D54DC9992CF9CB6699AA3 /* StakingAmountViewFactory.swift */; }; D886425A55425810AD070AB5 /* ControllerAccountConfirmationWireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = C96C3B5ABF4A8124848EFD17 /* ControllerAccountConfirmationWireframe.swift */; }; + D8C33C4064C3B2F30BB478A5 /* LiquidityPoolSupplyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C4CAC8978B0848DF5FD6FE /* LiquidityPoolSupplyTests.swift */; }; D9E803290BE797D889EA372D /* AssetSelectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2655EE5CFAAD20C0FF59188 /* AssetSelectionTests.swift */; }; DA5B38EE4622B33AFCA11A50 /* WalletsManagmentPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41E19988955B1C159EDA2555 /* WalletsManagmentPresenter.swift */; }; DA62812C23210601F4ECF84D /* ContactsProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B06C949668CFFDE6F739CC0 /* ContactsProtocols.swift */; }; @@ -1699,6 +1703,7 @@ DBA6A0A26D77E7A587C51792 /* PolkaswapSwapConfirmationProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA6FC016067C632AF256EB62 /* PolkaswapSwapConfirmationProtocols.swift */; }; DBBD1651F45FECA1B17AAF40 /* CreateContactViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 480AE579B48B3DA9C247CCB5 /* CreateContactViewController.swift */; }; DCDAE9E8C805B71A8F8CEFBD /* YourValidatorListTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 890203CBFFCBF517C0BAA396 /* YourValidatorListTests.swift */; }; + DCE13AA9F3BA0EB54F793017 /* LiquidityPoolSupplyAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62928FB3556EEA3A228131AC /* LiquidityPoolSupplyAssembly.swift */; }; DD1ADD4F777B0C6398C73805 /* NftDetailsRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B08B264C09E63A936384E2A /* NftDetailsRouter.swift */; }; DD96B37BBEE1535951802B55 /* AllDoneProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C90AA5852CFA841CED20631 /* AllDoneProtocols.swift */; }; DDEEF4532805420415471B6A /* NftDetailsAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 194E6EDD65CA3FB0B1F6727C /* NftDetailsAssembly.swift */; }; @@ -1706,6 +1711,7 @@ DE6DC04509EFEE35FFBADC59 /* NftSendAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49C564052FAA3160AA8975CB /* NftSendAssembly.swift */; }; DE9FA0FA5A6B685CBD593025 /* AllDoneInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = C705CA1083C1EE58426D90CD /* AllDoneInteractor.swift */; }; DFD5EDA2F7C096DB3A5368E4 /* CustomValidatorListTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A16451B21451996CAA31F8 /* CustomValidatorListTests.swift */; }; + DFF0320CF3AA41142DEAC5F2 /* LiquidityPoolsOverviewInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6717FF1B7777400B62F028C3 /* LiquidityPoolsOverviewInteractor.swift */; }; E14F809C3917EFA4B5388AC8 /* AccountConfirmViewFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = A14CA4551FCC2EBD078E2242 /* AccountConfirmViewFactory.swift */; }; E1772980B5A4EB33D1801204 /* PolkaswapAdjustmentViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25FF82C2FD912021A1F20876 /* PolkaswapAdjustmentViewLayout.swift */; }; E2645EB7614F4C7A60B48777 /* PolkaswapAdjustmentProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A9EBD3B7AEA5EF594DFEB49 /* PolkaswapAdjustmentProtocols.swift */; }; @@ -1719,6 +1725,7 @@ E5B4512B99ED86EF398B648E /* WarningAlertTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E587507F8CDA7F84A1A4EA95 /* WarningAlertTests.swift */; }; E5CE21BA40C554E06B566E98 /* NftCollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB19F24CAA892FE8B5FE1520 /* NftCollectionViewController.swift */; }; E5F3DF66415E54AE04D0C9A9 /* StakingMainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A05EB4FAF2FDE7DECEA93E4 /* StakingMainViewController.swift */; }; + E667BD4B6BA45B9B3464AD85 /* LiquidityPoolRemoveLiquidityConfirmAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECE2059F621D024F85EFBFD0 /* LiquidityPoolRemoveLiquidityConfirmAssembly.swift */; }; E6981A506AC931D30E85169E /* WalletOptionPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFD95EE4822A564C0D4D1CFE /* WalletOptionPresenter.swift */; }; E7CAD629FF0D4E97594F7A05 /* YourValidatorListInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B60728FCFBC8A9BE4C7B50B /* YourValidatorListInteractor.swift */; }; E8B8D3D290DC7057144559CE /* WalletChainAccountDashboardPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E83833EB33E51A12F96F83B /* WalletChainAccountDashboardPresenter.swift */; }; @@ -1729,6 +1736,7 @@ EB7B660B0B1BAA915C004A8D /* AnalyticsRewardDetailsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 095DEF513136A26593FB421F /* AnalyticsRewardDetailsViewController.swift */; }; EB9D8D22AA13BF12F845856B /* ReferralCrowdloanProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 953E21C32079A8051A0EE964 /* ReferralCrowdloanProtocols.swift */; }; EC978E6C4FBF39BE9ED10C86 /* SelectValidatorsStartWireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 889A825F58F5CB54118A9D35 /* SelectValidatorsStartWireframe.swift */; }; + ECA54AB8148BBA63084353FD /* LiquidityPoolRemoveLiquidityConfirmTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31F75A22E215273305AF7AA2 /* LiquidityPoolRemoveLiquidityConfirmTests.swift */; }; EDC02F2FDCDB55519DB0273D /* AnalyticsRewardDetailsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 761FDEBB414B1CFAD6992352 /* AnalyticsRewardDetailsTests.swift */; }; EDC72DAB0BDD63E0521E66B5 /* WarningAlertViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22FD9A4EA33DB4B6AFA5B0C4 /* WarningAlertViewController.swift */; }; EE6FC6EFB089A94EF105F2CC /* StakingRewardPayoutsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 934678CCA0EF35B6AE4AE8A1 /* StakingRewardPayoutsTests.swift */; }; @@ -1738,6 +1746,7 @@ F0C3DB0CEE1975626B0014A8 /* StakingUnbondConfirmInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C34D496D0F57E685237B3A7 /* StakingUnbondConfirmInteractor.swift */; }; F17C7FA0DB540A803558D1BB /* AnalyticsRewardDetailsPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85211D55E2AF0A697FB3EB84 /* AnalyticsRewardDetailsPresenter.swift */; }; F20C8D17ABF18B7104E14394 /* StakingAmountInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 312DE7ADA5ABC3214AD3D4AD /* StakingAmountInteractor.swift */; }; + F31469BD18062A4A008FE39E /* LiquidityPoolSupplyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 497EFA05A2D8076BFE82964D /* LiquidityPoolSupplyViewController.swift */; }; F38273DB7A8B139B9FD8FBE2 /* MainNftContainerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFC9C09ABBCEB6E581134E84 /* MainNftContainerViewController.swift */; }; F3E88A15A597C7B9B92C097B /* NetworkIssuesNotificationProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = F02C3AF74DE2F2CDBD165803 /* NetworkIssuesNotificationProtocols.swift */; }; F400A7C2260CE1670061D576 /* StakingRewardStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = F400A7C1260CE1670061D576 /* StakingRewardStatus.swift */; }; @@ -1882,6 +1891,7 @@ F4FDA0F826A57626003D753B /* EraCountdownOperationFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4FDA0F726A57626003D753B /* EraCountdownOperationFactory.swift */; }; F4FDA0FD26A57860003D753B /* EraCountdown.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4FDA0FC26A57860003D753B /* EraCountdown.swift */; }; F50D9C2CCA49D396E0D6EFDD /* WalletTransactionDetailsViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = D80247ADAAB061D1A10856B2 /* WalletTransactionDetailsViewLayout.swift */; }; + F52C9FF9ABB4ED034D177CF8 /* LiquidityPoolsOverviewRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F25F3A88B4BEB4DE498220C /* LiquidityPoolsOverviewRouter.swift */; }; F59DC31DD3D95BC0A6620773 /* NftDetailsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA7427142A4B905B5DB15498 /* NftDetailsViewController.swift */; }; F643D1682E6787E13385F432 /* NftSendTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45C8249F3F41DC0FFCF27EFF /* NftSendTests.swift */; }; F6CD0ED1CF9A605222745BEC /* ContactsRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75B53E901B1475DE858A2C99 /* ContactsRouter.swift */; }; @@ -1899,11 +1909,14 @@ FA004899282CCFCD0032FF49 /* SelectValidatorsStartParachainViewModelFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA004898282CCFCD0032FF49 /* SelectValidatorsStartParachainViewModelFactory.swift */; }; FA00489B282CCFDC0032FF49 /* SelectValidatorsStartRelaychainViewModelFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA00489A282CCFDC0032FF49 /* SelectValidatorsStartRelaychainViewModelFactory.swift */; }; FA0066E92935D07D0068FC61 /* RecommendedValidatorListPoolStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA0066E82935D07D0068FC61 /* RecommendedValidatorListPoolStrategy.swift */; }; + FA054A9A2BCD1FA3007B8F6D /* AvailableLiquidityPoolsListPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA054A992BCD1FA3007B8F6D /* AvailableLiquidityPoolsListPresenter.swift */; }; + FA054A9C2BCD1FAF007B8F6D /* AvailableLiquidityPoolsListViewModelFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA054A9B2BCD1FAF007B8F6D /* AvailableLiquidityPoolsListViewModelFactory.swift */; }; FA072C14277AE2FE00731718 /* QRCaptureService.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA072C13277AE2FE00731718 /* QRCaptureService.swift */; }; - FA072C16277B023D00731718 /* QRExtractionService.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA072C15277B023D00731718 /* QRExtractionService.swift */; }; FA072C21277B19A900731718 /* ImageGalleryProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA072C20277B19A900731718 /* ImageGalleryProtocols.swift */; }; FA072C25277C0FA900731718 /* ApplicationSettingsPresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA072C24277C0FA900731718 /* ApplicationSettingsPresentable.swift */; }; FA08B3652A31A09E00D9D126 /* BigUInt+StringInitializable.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA08B3642A31A09E00D9D126 /* BigUInt+StringInitializable.swift */; }; + FA09AD352C37ABA000BE0B9C /* TransactionObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA09AD342C37ABA000BE0B9C /* TransactionObserver.swift */; }; + FA09AD372C37AF9200BE0B9C /* SubstrateTransactionObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA09AD362C37AF9200BE0B9C /* SubstrateTransactionObserver.swift */; }; FA1109EB27A92D56003C2158 /* ChainAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA1109EA27A92D56003C2158 /* ChainAction.swift */; }; FA14AE892B0785670066CADF /* SoraSubsquidHistoryResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA14AE882B0785670066CADF /* SoraSubsquidHistoryResponse.swift */; }; FA14AE8B2B0788D20066CADF /* AssetTransactionData+SoraSubsquidHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA14AE8A2B0788D20066CADF /* AssetTransactionData+SoraSubsquidHistory.swift */; }; @@ -1933,6 +1946,26 @@ FA17B4D427E9CF2D006E0735 /* UtilityConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA17B4D327E9CF2C006E0735 /* UtilityConstants.swift */; }; FA1A023C274F51A900DA07CB /* ChainAccountBalanceTableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA1A023B274F51A900DA07CB /* ChainAccountBalanceTableCell.swift */; }; FA1A023E274F55D900DA07CB /* HorizontalKeyValueView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA1A023D274F55D900DA07CB /* HorizontalKeyValueView.swift */; }; + FA1D01F92BBE713D005B7071 /* LiquidityPoolListCellModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA1D01EE2BBE713D005B7071 /* LiquidityPoolListCellModel.swift */; }; + FA1D01FA2BBE713D005B7071 /* LiquidityPoolListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA1D01EF2BBE713D005B7071 /* LiquidityPoolListViewModel.swift */; }; + FA1D01FB2BBE713D005B7071 /* LiquidityPoolsListViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA1D01F02BBE713D005B7071 /* LiquidityPoolsListViewLayout.swift */; }; + FA1D01FC2BBE713D005B7071 /* LiquidityPoolsListRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA1D01F12BBE713D005B7071 /* LiquidityPoolsListRouter.swift */; }; + FA1D01FD2BBE713D005B7071 /* LiquidityPoolsListProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA1D01F22BBE713D005B7071 /* LiquidityPoolsListProtocols.swift */; }; + FA1D01FF2BBE713D005B7071 /* LiquidityPoolsListAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA1D01F42BBE713D005B7071 /* LiquidityPoolsListAssembly.swift */; }; + FA1D02002BBE713D005B7071 /* LiquidityPoolListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA1D01F62BBE713D005B7071 /* LiquidityPoolListCell.swift */; }; + FA1D02012BBE713D005B7071 /* LiquidityPoolsListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA1D01F72BBE713D005B7071 /* LiquidityPoolsListViewController.swift */; }; + FA1D02042BBE71F2005B7071 /* TokenPairIconsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA1D02032BBE71F2005B7071 /* TokenPairIconsView.swift */; }; + FA1D02062BBE71F9005B7071 /* TokenPairsIconViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA1D02052BBE71F9005B7071 /* TokenPairsIconViewModel.swift */; }; + FA1D02092BBE74B7005B7071 /* AvailableLiquidityPoolsListInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA1D02082BBE74B7005B7071 /* AvailableLiquidityPoolsListInteractor.swift */; }; + FA1D020D2BBE7690005B7071 /* UserLiquidityPoolsListInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA1D020C2BBE7690005B7071 /* UserLiquidityPoolsListInteractor.swift */; }; + FA1D51D72BCFD445001353E7 /* LiquidityPools+ViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA1D51D62BCFD445001353E7 /* LiquidityPools+ViewModel.swift */; }; + FA1D51D92BCFE353001353E7 /* SoraFiatService.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA1D51D82BCFE353001353E7 /* SoraFiatService.swift */; }; + FA1D51DC2BCFE38D001353E7 /* SubqueryFiatInfoOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA1D51DB2BCFE38D001353E7 /* SubqueryFiatInfoOperation.swift */; }; + FA22228D2BD237910031DE04 /* SubqueryPriceFetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA22228C2BD237910031DE04 /* SubqueryPriceFetcher.swift */; }; + FA22228F2BD237CF0031DE04 /* SoraSubqueryPriceFetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA22228E2BD237CF0031DE04 /* SoraSubqueryPriceFetcher.swift */; }; + FA2222912BD239500031DE04 /* SoraSubqueryPriceResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA2222902BD239500031DE04 /* SoraSubqueryPriceResponse.swift */; }; + FA2222942BD2726F0031DE04 /* SkeletonLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA2222932BD2726F0031DE04 /* SkeletonLabel.swift */; }; + FA2222962BD272A30031DE04 /* SkeletonLoadableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA2222952BD272A30031DE04 /* SkeletonLoadableView.swift */; }; FA24FEFE2B95C32200CD9E04 /* Decimal+DoubleValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA24FEFD2B95C32200CD9E04 /* Decimal+DoubleValue.swift */; }; FA256984274CE5A500875A53 /* BalanceLockType.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA256982274CE5A400875A53 /* BalanceLockType.swift */; }; FA256985274CE5A500875A53 /* BalanceLocks+Sort.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA256983274CE5A500875A53 /* BalanceLocks+Sort.swift */; }; @@ -2187,6 +2220,7 @@ FA3F5B6B281BAF6600BEF03B /* StakingAmountParachainViewModelState.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA3F5B6A281BAF6600BEF03B /* StakingAmountParachainViewModelState.swift */; }; FA402F2F27C7C646008CF986 /* ExportAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA402F2E27C7C646008CF986 /* ExportAction.swift */; }; FA44284229D44E51000142EB /* ChainStakingSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA44284129D44E51000142EB /* ChainStakingSettings.swift */; }; + FA4441342BF75FD90067C633 /* LiquidityPoolListType.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA4441332BF75FD90067C633 /* LiquidityPoolListType.swift */; }; FA46D2C7283DDD07005A112B /* ParachainStakingCandidateMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA46D2C6283DDD07005A112B /* ParachainStakingCandidateMetadata.swift */; }; FA4889672B7F5E360092ABF8 /* GiantsquidExtrinsic.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA4889662B7F5E360092ABF8 /* GiantsquidExtrinsic.swift */; }; FA4B928F284493C60003BCEF /* DelegateCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA4B928E284493C60003BCEF /* DelegateCall.swift */; }; @@ -2211,6 +2245,8 @@ FA4C3D122886794D00176398 /* SelfSizingTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA4C3D112886794D00176398 /* SelfSizingTableView.swift */; }; FA4CC6642817C3AC00A7E85F /* StackedTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA4CC6632817C3AC00A7E85F /* StackedTableView.swift */; }; FA4CC666281801CB00A7E85F /* StakingUnitInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA4CC665281801CB00A7E85F /* StakingUnitInfoView.swift */; }; + FA5085AC2C33C6D4002DF97D /* SafeArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA5085AA2C33C6D4002DF97D /* SafeArray.swift */; }; + FA5085AD2C33C6D4002DF97D /* SafeDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA5085AB2C33C6D4002DF97D /* SafeDictionary.swift */; }; FA5137AA29AC6F2F00560EBA /* PolkaswapDisclaimerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA5137A129AC6F2F00560EBA /* PolkaswapDisclaimerViewModel.swift */; }; FA5137AB29AC6F2F00560EBA /* PolkaswapDisclaimerRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA5137A229AC6F2F00560EBA /* PolkaswapDisclaimerRouter.swift */; }; FA5137AC29AC6F2F00560EBA /* PolkaswapDisclaimerViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA5137A329AC6F2F00560EBA /* PolkaswapDisclaimerViewLayout.swift */; }; @@ -2224,36 +2260,8 @@ FA5137B929AC76EB00560EBA /* GiantsquidHistoryOperationFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA5137B529AC76EB00560EBA /* GiantsquidHistoryOperationFactory.swift */; }; FA5137BA29AC76EB00560EBA /* SubsquidHistoryOperationFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA5137B629AC76EB00560EBA /* SubsquidHistoryOperationFactory.swift */; }; FA5137BB29AC76EB00560EBA /* HistoryOperationFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA5137B729AC76EB00560EBA /* HistoryOperationFactory.swift */; }; - FA53D8972C096F1100173ADB /* IrohaCrypto in Frameworks */ = {isa = PBXBuildFile; productRef = FA53D8962C096F1100173ADB /* IrohaCrypto */; }; - FA53D8992C096F1100173ADB /* MPQRCoreSDK in Frameworks */ = {isa = PBXBuildFile; productRef = FA53D8982C096F1100173ADB /* MPQRCoreSDK */; }; - FA53D89B2C096F1100173ADB /* RobinHood in Frameworks */ = {isa = PBXBuildFile; productRef = FA53D89A2C096F1100173ADB /* RobinHood */; }; - FA53D89D2C096F1100173ADB /* SSFAccountManagment in Frameworks */ = {isa = PBXBuildFile; productRef = FA53D89C2C096F1100173ADB /* SSFAccountManagment */; }; - FA53D89F2C096F1100173ADB /* SSFAccountManagmentStorage in Frameworks */ = {isa = PBXBuildFile; productRef = FA53D89E2C096F1100173ADB /* SSFAccountManagmentStorage */; }; - FA53D8A12C096F1100173ADB /* SSFAssetManagment in Frameworks */ = {isa = PBXBuildFile; productRef = FA53D8A02C096F1100173ADB /* SSFAssetManagment */; }; - FA53D8A32C096F1100173ADB /* SSFChainConnection in Frameworks */ = {isa = PBXBuildFile; productRef = FA53D8A22C096F1100173ADB /* SSFChainConnection */; }; - FA53D8A52C096F1100173ADB /* SSFChainRegistry in Frameworks */ = {isa = PBXBuildFile; productRef = FA53D8A42C096F1100173ADB /* SSFChainRegistry */; }; - FA53D8A72C096F1100173ADB /* SSFCloudStorage in Frameworks */ = {isa = PBXBuildFile; productRef = FA53D8A62C096F1100173ADB /* SSFCloudStorage */; }; - FA53D8A92C096F1100173ADB /* SSFCrypto in Frameworks */ = {isa = PBXBuildFile; productRef = FA53D8A82C096F1100173ADB /* SSFCrypto */; }; - FA53D8AB2C096F1100173ADB /* SSFEraKit in Frameworks */ = {isa = PBXBuildFile; productRef = FA53D8AA2C096F1100173ADB /* SSFEraKit */; }; - FA53D8AD2C096F1100173ADB /* SSFExtrinsicKit in Frameworks */ = {isa = PBXBuildFile; productRef = FA53D8AC2C096F1100173ADB /* SSFExtrinsicKit */; }; - FA53D8AF2C096F1100173ADB /* SSFHelpers in Frameworks */ = {isa = PBXBuildFile; productRef = FA53D8AE2C096F1100173ADB /* SSFHelpers */; }; - FA53D8B12C096F1100173ADB /* SSFKeyPair in Frameworks */ = {isa = PBXBuildFile; productRef = FA53D8B02C096F1100173ADB /* SSFKeyPair */; }; - FA53D8B32C096F1100173ADB /* SSFLogger in Frameworks */ = {isa = PBXBuildFile; productRef = FA53D8B22C096F1100173ADB /* SSFLogger */; }; - FA53D8B52C096F1100173ADB /* SSFModels in Frameworks */ = {isa = PBXBuildFile; productRef = FA53D8B42C096F1100173ADB /* SSFModels */; }; - FA53D8B72C096F1100173ADB /* SSFNetwork in Frameworks */ = {isa = PBXBuildFile; productRef = FA53D8B62C096F1100173ADB /* SSFNetwork */; }; - FA53D8B92C096F1100173ADB /* SSFPolkaswap in Frameworks */ = {isa = PBXBuildFile; productRef = FA53D8B82C096F1100173ADB /* SSFPolkaswap */; }; - FA53D8BB2C096F1100173ADB /* SSFPools in Frameworks */ = {isa = PBXBuildFile; productRef = FA53D8BA2C096F1100173ADB /* SSFPools */; }; - FA53D8BD2C096F1100173ADB /* SSFPoolsStorage in Frameworks */ = {isa = PBXBuildFile; productRef = FA53D8BC2C096F1100173ADB /* SSFPoolsStorage */; }; - FA53D8BF2C096F1100173ADB /* SSFQRService in Frameworks */ = {isa = PBXBuildFile; productRef = FA53D8BE2C096F1100173ADB /* SSFQRService */; }; - FA53D8C12C096F1100173ADB /* SSFRuntimeCodingService in Frameworks */ = {isa = PBXBuildFile; productRef = FA53D8C02C096F1100173ADB /* SSFRuntimeCodingService */; }; - FA53D8C32C096F1100173ADB /* SSFSigner in Frameworks */ = {isa = PBXBuildFile; productRef = FA53D8C22C096F1100173ADB /* SSFSigner */; }; - FA53D8C52C096F1100173ADB /* SSFSingleValueCache in Frameworks */ = {isa = PBXBuildFile; productRef = FA53D8C42C096F1100173ADB /* SSFSingleValueCache */; }; - FA53D8C72C096F1100173ADB /* SSFStorageQueryKit in Frameworks */ = {isa = PBXBuildFile; productRef = FA53D8C62C096F1100173ADB /* SSFStorageQueryKit */; }; - FA53D8C92C096F1100173ADB /* SSFTransferService in Frameworks */ = {isa = PBXBuildFile; productRef = FA53D8C82C096F1100173ADB /* SSFTransferService */; }; - FA53D8CB2C096F1100173ADB /* SSFUtils in Frameworks */ = {isa = PBXBuildFile; productRef = FA53D8CA2C096F1100173ADB /* SSFUtils */; }; - FA53D8CD2C096F1100173ADB /* SSFXCM in Frameworks */ = {isa = PBXBuildFile; productRef = FA53D8CC2C096F1100173ADB /* SSFXCM */; }; - FA53D8CF2C096F1100173ADB /* SoraKeystore in Frameworks */ = {isa = PBXBuildFile; productRef = FA53D8CE2C096F1100173ADB /* SoraKeystore */; }; - FA53D8D12C096F1100173ADB /* keccak in Frameworks */ = {isa = PBXBuildFile; productRef = FA53D8D02C096F1100173ADB /* keccak */; }; + FA53D8902C084ECA00173ADB /* LiquidityPoolSupplyViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA53D88F2C084ECA00173ADB /* LiquidityPoolSupplyViewModel.swift */; }; + FA53D8922C08510000173ADB /* LiquidityPoolSupplyViewModelFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA53D8912C08510000173ADB /* LiquidityPoolSupplyViewModelFactory.swift */; }; FA584C782AB2BCD500F6F020 /* UniversalMediaView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA584C772AB2BCD500F6F020 /* UniversalMediaView.swift */; }; FA584C7A2AB2BFE300F6F020 /* MediaType.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA584C792AB2BFE300F6F020 /* MediaType.swift */; }; FA584C7C2AB3071E00F6F020 /* AlchemyNFTOperationFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA584C7B2AB3071E00F6F020 /* AlchemyNFTOperationFactory.swift */; }; @@ -2350,6 +2358,8 @@ FA6DB7C62757C9B000233FBA /* ChainAccountWireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA6DB7BF2757C9AF00233FBA /* ChainAccountWireframe.swift */; }; FA6DB7C82757C9B000233FBA /* ChainAccountInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA6DB7C12757C9AF00233FBA /* ChainAccountInteractor.swift */; }; FA6DB7C92757C9B000233FBA /* ChainAccountProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA6DB7C22757C9AF00233FBA /* ChainAccountProtocols.swift */; }; + FA6ECE742BF49C0C00481B2B /* LiquidityPoolDetailsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA6ECE732BF49C0C00481B2B /* LiquidityPoolDetailsViewModel.swift */; }; + FA6ECE762BF49D3D00481B2B /* LiquidityPoolDetailsViewModelFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA6ECE752BF49D3D00481B2B /* LiquidityPoolDetailsViewModelFactory.swift */; }; FA7154C4286B0C7D00100672 /* SelectValidatorsStartTextsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA7154C3286B0C7D00100672 /* SelectValidatorsStartTextsViewModel.swift */; }; FA7254202AC2E48500EC47A6 /* CryptoProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA7253F32AC2E48400EC47A6 /* CryptoProvider.swift */; }; FA7254212AC2E48500EC47A6 /* WalletConnectPayloadSigner.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA7253F42AC2E48400EC47A6 /* WalletConnectPayloadSigner.swift */; }; @@ -2387,7 +2397,6 @@ FA7254432AC2E48500EC47A6 /* WalletConnectService.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA72541D2AC2E48400EC47A6 /* WalletConnectService.swift */; }; FA7254442AC2E48500EC47A6 /* WalletConnectSocketFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA72541E2AC2E48400EC47A6 /* WalletConnectSocketFactory.swift */; }; FA7254452AC2E48500EC47A6 /* WalletConnectPayloadFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA72541F2AC2E48500EC47A6 /* WalletConnectPayloadFactory.swift */; }; - FA7254472AC2E4AB00EC47A6 /* QRUriMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA7254462AC2E4AB00EC47A6 /* QRUriMatcher.swift */; }; FA7254672AC2F12D00EC47A6 /* WalletConnect in Frameworks */ = {isa = PBXBuildFile; productRef = FA7254662AC2F12D00EC47A6 /* WalletConnect */; }; FA7254692AC2F12D00EC47A6 /* WalletConnectAuth in Frameworks */ = {isa = PBXBuildFile; productRef = FA7254682AC2F12D00EC47A6 /* WalletConnectAuth */; }; FA72546B2AC2F12D00EC47A6 /* WalletConnectNetworking in Frameworks */ = {isa = PBXBuildFile; productRef = FA72546A2AC2F12D00EC47A6 /* WalletConnectNetworking */; }; @@ -2470,6 +2479,40 @@ FA8800682B31A335000AE5EB /* StakingAccountSubscriptionV13.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA8800672B31A335000AE5EB /* StakingAccountSubscriptionV13.swift */; }; FA88006A2B31A33E000AE5EB /* StakingAccountSubscriptionV14.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA8800692B31A33E000AE5EB /* StakingAccountSubscriptionV14.swift */; }; FA88006C2B31A46D000AE5EB /* StakingAccountSubscriptionAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA88006B2B31A46D000AE5EB /* StakingAccountSubscriptionAssembly.swift */; }; + FA8810982BDCAF260084CC4B /* IrohaCrypto in Frameworks */ = {isa = PBXBuildFile; productRef = FA8810972BDCAF260084CC4B /* IrohaCrypto */; }; + FA88109A2BDCAF260084CC4B /* RobinHood in Frameworks */ = {isa = PBXBuildFile; productRef = FA8810992BDCAF260084CC4B /* RobinHood */; }; + FA88109C2BDCAF260084CC4B /* SSFAccountManagment in Frameworks */ = {isa = PBXBuildFile; productRef = FA88109B2BDCAF260084CC4B /* SSFAccountManagment */; }; + FA88109E2BDCAF260084CC4B /* SSFAccountManagmentStorage in Frameworks */ = {isa = PBXBuildFile; productRef = FA88109D2BDCAF260084CC4B /* SSFAccountManagmentStorage */; }; + FA8810A02BDCAF260084CC4B /* SSFAssetManagment in Frameworks */ = {isa = PBXBuildFile; productRef = FA88109F2BDCAF260084CC4B /* SSFAssetManagment */; }; + FA8810A22BDCAF260084CC4B /* SSFChainConnection in Frameworks */ = {isa = PBXBuildFile; productRef = FA8810A12BDCAF260084CC4B /* SSFChainConnection */; }; + FA8810A42BDCAF260084CC4B /* SSFChainRegistry in Frameworks */ = {isa = PBXBuildFile; productRef = FA8810A32BDCAF260084CC4B /* SSFChainRegistry */; }; + FA8810A62BDCAF260084CC4B /* SSFCloudStorage in Frameworks */ = {isa = PBXBuildFile; productRef = FA8810A52BDCAF260084CC4B /* SSFCloudStorage */; }; + FA8810A82BDCAF260084CC4B /* SSFCrypto in Frameworks */ = {isa = PBXBuildFile; productRef = FA8810A72BDCAF260084CC4B /* SSFCrypto */; }; + FA8810AA2BDCAF260084CC4B /* SSFEraKit in Frameworks */ = {isa = PBXBuildFile; productRef = FA8810A92BDCAF260084CC4B /* SSFEraKit */; }; + FA8810AC2BDCAF260084CC4B /* SSFExtrinsicKit in Frameworks */ = {isa = PBXBuildFile; productRef = FA8810AB2BDCAF260084CC4B /* SSFExtrinsicKit */; }; + FA8810AE2BDCAF260084CC4B /* SSFHelpers in Frameworks */ = {isa = PBXBuildFile; productRef = FA8810AD2BDCAF260084CC4B /* SSFHelpers */; }; + FA8810B02BDCAF260084CC4B /* SSFKeyPair in Frameworks */ = {isa = PBXBuildFile; productRef = FA8810AF2BDCAF260084CC4B /* SSFKeyPair */; }; + FA8810B22BDCAF260084CC4B /* SSFLogger in Frameworks */ = {isa = PBXBuildFile; productRef = FA8810B12BDCAF260084CC4B /* SSFLogger */; }; + FA8810B42BDCAF260084CC4B /* SSFModels in Frameworks */ = {isa = PBXBuildFile; productRef = FA8810B32BDCAF260084CC4B /* SSFModels */; }; + FA8810B62BDCAF260084CC4B /* SSFNetwork in Frameworks */ = {isa = PBXBuildFile; productRef = FA8810B52BDCAF260084CC4B /* SSFNetwork */; }; + FA8810B82BDCAF260084CC4B /* SSFPolkaswap in Frameworks */ = {isa = PBXBuildFile; productRef = FA8810B72BDCAF260084CC4B /* SSFPolkaswap */; }; + FA8810BA2BDCAF260084CC4B /* SSFPools in Frameworks */ = {isa = PBXBuildFile; productRef = FA8810B92BDCAF260084CC4B /* SSFPools */; }; + FA8810BC2BDCAF260084CC4B /* SSFPoolsStorage in Frameworks */ = {isa = PBXBuildFile; productRef = FA8810BB2BDCAF260084CC4B /* SSFPoolsStorage */; }; + FA8810BE2BDCAF260084CC4B /* SSFQRService in Frameworks */ = {isa = PBXBuildFile; productRef = FA8810BD2BDCAF260084CC4B /* SSFQRService */; }; + FA8810C02BDCAF260084CC4B /* SSFRuntimeCodingService in Frameworks */ = {isa = PBXBuildFile; productRef = FA8810BF2BDCAF260084CC4B /* SSFRuntimeCodingService */; }; + FA8810C22BDCAF260084CC4B /* SSFSigner in Frameworks */ = {isa = PBXBuildFile; productRef = FA8810C12BDCAF260084CC4B /* SSFSigner */; }; + FA8810C42BDCAF260084CC4B /* SSFSingleValueCache in Frameworks */ = {isa = PBXBuildFile; productRef = FA8810C32BDCAF260084CC4B /* SSFSingleValueCache */; }; + FA8810C62BDCAF260084CC4B /* SSFStorageQueryKit in Frameworks */ = {isa = PBXBuildFile; productRef = FA8810C52BDCAF260084CC4B /* SSFStorageQueryKit */; }; + FA8810C82BDCAF260084CC4B /* SSFTransferService in Frameworks */ = {isa = PBXBuildFile; productRef = FA8810C72BDCAF260084CC4B /* SSFTransferService */; }; + FA8810CA2BDCAF260084CC4B /* SSFUtils in Frameworks */ = {isa = PBXBuildFile; productRef = FA8810C92BDCAF260084CC4B /* SSFUtils */; }; + FA8810CC2BDCAF260084CC4B /* SSFXCM in Frameworks */ = {isa = PBXBuildFile; productRef = FA8810CB2BDCAF260084CC4B /* SSFXCM */; }; + FA8810CE2BDCAF260084CC4B /* SoraKeystore in Frameworks */ = {isa = PBXBuildFile; productRef = FA8810CD2BDCAF260084CC4B /* SoraKeystore */; }; + FA8810D02BDCAF260084CC4B /* keccak in Frameworks */ = {isa = PBXBuildFile; productRef = FA8810CF2BDCAF260084CC4B /* keccak */; }; + FA8810D32BDCCF7E0084CC4B /* UserLiquidityPoolsListPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA8810D22BDCCF7E0084CC4B /* UserLiquidityPoolsListPresenter.swift */; }; + FA8810D52BDCD19D0084CC4B /* UserLiquidityPoolsListViewModelFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA8810D42BDCD19D0084CC4B /* UserLiquidityPoolsListViewModelFactory.swift */; }; + FA887A452C107A1100CA720F /* LiquidityPoolSupplyConfirmViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA887A442C107A1100CA720F /* LiquidityPoolSupplyConfirmViewModel.swift */; }; + FA887A472C107A4300CA720F /* LiquidityPoolSupplyConfirmViewModelFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA887A462C107A4300CA720F /* LiquidityPoolSupplyConfirmViewModelFactory.swift */; }; + FA887A492C1C19DB00CA720F /* WarningView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA887A482C1C19DB00CA720F /* WarningView.swift */; }; FA8ED43328FD960F00EBB712 /* YourValidatorListFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA8ED43228FD960F00EBB712 /* YourValidatorListFlow.swift */; }; FA8ED43628FD983A00EBB712 /* YourValidatorListRelaychainStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA8ED43528FD983A00EBB712 /* YourValidatorListRelaychainStrategy.swift */; }; FA8ED43828FD984500EBB712 /* YourValidatorListRelaychainViewModelState.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA8ED43728FD984500EBB712 /* YourValidatorListRelaychainViewModelState.swift */; }; @@ -2482,6 +2525,9 @@ FA8F6386298253ED004B8CD4 /* AddConnectionError.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA8F6385298253ED004B8CD4 /* AddConnectionError.swift */; }; FA8F63AB29825C90004B8CD4 /* AccountShareFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA8F63A529825C90004B8CD4 /* AccountShareFactory.swift */; }; FA8F63B1298273FE004B8CD4 /* DecodedTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA8F63B0298273FE004B8CD4 /* DecodedTypes.swift */; }; + FA8FD1812AF4B55100354482 /* Web3 in Frameworks */ = {isa = PBXBuildFile; productRef = FA8FD1802AF4B55100354482 /* Web3 */; }; + FA8FD1832AF4B55100354482 /* Web3ContractABI in Frameworks */ = {isa = PBXBuildFile; productRef = FA8FD1822AF4B55100354482 /* Web3ContractABI */; }; + FA8FD1852AF4B55100354482 /* Web3PromiseKit in Frameworks */ = {isa = PBXBuildFile; productRef = FA8FD1842AF4B55100354482 /* Web3PromiseKit */; }; FA8FD1882AF4BEDD00354482 /* Swime in Frameworks */ = {isa = PBXBuildFile; productRef = FA8FD1872AF4BEDD00354482 /* Swime */; }; FA8FD18B2AFB7E6C00354482 /* AssetNetworksTableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA8FD18A2AFB7E6C00354482 /* AssetNetworksTableCell.swift */; }; FA8FD18E2AFBA2EA00354482 /* AssetNetworksTableCellModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA8FD18D2AFBA2EA00354482 /* AssetNetworksTableCellModel.swift */; }; @@ -2541,9 +2587,9 @@ FA93A313283653B70021330F /* ValidatorListFilterFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA93A312283653B70021330F /* ValidatorListFilterFlow.swift */; }; FA93A3162836542D0021330F /* ValidatorListFilterRelaychainViewModelState.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA93A3152836542D0021330F /* ValidatorListFilterRelaychainViewModelState.swift */; }; FA93A3182836543B0021330F /* ValidatorListFilterRelaychainViewModelFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA93A3172836543B0021330F /* ValidatorListFilterRelaychainViewModelFactory.swift */; }; + FA9610202C5205B200C3C750 /* UIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA96101F2C5205B200C3C750 /* UIViewController.swift */; }; FA97E68B2A0281230035F5D7 /* GiantsquidRewardOperationFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA97E68A2A0281230035F5D7 /* GiantsquidRewardOperationFactory.swift */; }; FA99422827FE925000D771E5 /* UISwitch+CustomSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA99422727FE925000D771E5 /* UISwitch+CustomSize.swift */; }; - FA99422A27FE927800D771E5 /* AssetModelMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA99422927FE927700D771E5 /* AssetModelMapper.swift */; }; FA99422D28002BB800D771E5 /* MissingAccountOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA99422C28002BB800D771E5 /* MissingAccountOptions.swift */; }; FA99423528053C5000D771E5 /* ChainAccountInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA99423428053C5000D771E5 /* ChainAccountInfo.swift */; }; FA99423728053C6800D771E5 /* IconWithTitleViewModelFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA99423628053C6800D771E5 /* IconWithTitleViewModelFactory.swift */; }; @@ -2695,7 +2741,6 @@ FAAA294A2B8DCF350089AFE6 /* AsyncStorageRequestFactory+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAAA29472B8DCF350089AFE6 /* AsyncStorageRequestFactory+Extension.swift */; }; FAAA294B2B8DCF350089AFE6 /* AsyncStorageRequestFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAAA29482B8DCF350089AFE6 /* AsyncStorageRequestFactory.swift */; }; FAAA29572B8DED770089AFE6 /* MapKeyType.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAAA29562B8DED770089AFE6 /* MapKeyType.swift */; }; - FAAB998D27A7C79D00CD1A3B /* QRParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAAB998C27A7C79D00CD1A3B /* QRParser.swift */; }; FAABC46E2845BADA002CF40E /* CustomValidatorParachainListFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAABC46D2845BADA002CF40E /* CustomValidatorParachainListFilter.swift */; }; FAABC4702845BAEE002CF40E /* CustomValidatorParachainListComposer.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAABC46F2845BAEE002CF40E /* CustomValidatorParachainListComposer.swift */; }; FAABC4732845C7F4002CF40E /* ValidatorListFilterParachainViewModelState.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAABC4722845C7F4002CF40E /* ValidatorListFilterParachainViewModelState.swift */; }; @@ -2721,8 +2766,7 @@ FAADC1BA2926597400DA9903 /* ScanQRPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAADC1B32926597400DA9903 /* ScanQRPresenter.swift */; }; FAADC1BB2926597400DA9903 /* ScanQRProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAADC1B42926597400DA9903 /* ScanQRProtocols.swift */; }; FAADC1BC2926597400DA9903 /* ScanQRRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAADC1B52926597400DA9903 /* ScanQRRouter.swift */; }; - FAADC1C129265A7900DA9903 /* QRInfoMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAADC1BF29265A7900DA9903 /* QRInfoMatcher.swift */; }; - FAADC1C629265C9600DA9903 /* QRCoderFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAADC1C529265C9600DA9903 /* QRCoderFactory.swift */; }; + FAADF71229C47D10002B6D39 /* RuntimeSpecVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAADF71129C47D10002B6D39 /* RuntimeSpecVersion.swift */; }; FAAF61742877DBC50094B4BC /* EthereumIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAAF61732877DBC50094B4BC /* EthereumIcon.swift */; }; FAAF946C2A0CFF90009A4BA5 /* Array+Duplicates.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAAF946B2A0CFF90009A4BA5 /* Array+Duplicates.swift */; }; FAB0EDD927AA692D003D93C2 /* NodeSelectionTableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAB0EDD827AA692D003D93C2 /* NodeSelectionTableCell.swift */; }; @@ -2832,11 +2876,39 @@ FACD42BD2A5BE91E009975AA /* PortionRewardCalculatorService.swift in Sources */ = {isa = PBXBuildFile; fileRef = FACD42BB2A5BE91D009975AA /* PortionRewardCalculatorService.swift */; }; FACD42BF2A5BE93D009975AA /* polkadot-9370metadata in Resources */ = {isa = PBXBuildFile; fileRef = FACD42BE2A5BE93D009975AA /* polkadot-9370metadata */; }; FACD42C12A5C10BB009975AA /* TransferService.swift in Sources */ = {isa = PBXBuildFile; fileRef = FACD42C02A5C10BB009975AA /* TransferService.swift */; }; - FACE6C632BBAC3B100643CEF /* SubstrateDataModel.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = FACE6C5D2BBAC3B000643CEF /* SubstrateDataModel.xcdatamodeld */; }; FAD0068027EA252400C97E09 /* AboutViewModelFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD0067E27EA252400C97E09 /* AboutViewModelFactory.swift */; }; FAD0068127EA252400C97E09 /* AboutViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD0067F27EA252400C97E09 /* AboutViewState.swift */; }; FAD0068427EA255900C97E09 /* AboutTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD0068227EA255900C97E09 /* AboutTableViewCell.swift */; }; FAD0068527EA255900C97E09 /* AboutViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD0068327EA255900C97E09 /* AboutViewLayout.swift */; }; + FAD067912C2042F30050291F /* Requests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD0678E2C2042F30050291F /* Requests.swift */; }; + FAD067922C2042F30050291F /* AccountInfoRemoteService.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD0678F2C2042F30050291F /* AccountInfoRemoteService.swift */; }; + FAD067962C2043DC0050291F /* UIImage+Monochrome.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD067952C2043DC0050291F /* UIImage+Monochrome.swift */; }; + FAD067992C2043FC0050291F /* WalletAssetsObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD067972C2043FC0050291F /* WalletAssetsObserver.swift */; }; + FAD0679A2C2043FC0050291F /* ChainConnectionVisibilityHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD067982C2043FC0050291F /* ChainConnectionVisibilityHelper.swift */; }; + FAD0679C2C2044170050291F /* ExternalApiExplorerType.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD0679B2C2044170050291F /* ExternalApiExplorerType.swift */; }; + FAD0679E2C2044320050291F /* AssetManagementMigrator.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD0679D2C2044320050291F /* AssetManagementMigrator.swift */; }; + FAD067A72C2044490050291F /* SubstrateDataModel.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = FAD0679F2C2044490050291F /* SubstrateDataModel.xcdatamodeld */; }; + FAD067A92C20445F0050291F /* ChainAssetListBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD067A82C20445F0050291F /* ChainAssetListBuilder.swift */; }; + FAD067AD2C2044810050291F /* ErasStakersPagedKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD067AB2C2044810050291F /* ErasStakersPagedKey.swift */; }; + FAD067AE2C2044810050291F /* ErasStakersOverviewKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD067AC2C2044810050291F /* ErasStakersOverviewKey.swift */; }; + FAD067BD2C2044B10050291F /* AssetManagementViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD067B12C2044B10050291F /* AssetManagementViewModel.swift */; }; + FAD067BE2C2044B10050291F /* AssetManagementViewModelFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD067B22C2044B10050291F /* AssetManagementViewModelFactory.swift */; }; + FAD067BF2C2044B10050291F /* AssetManagementInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD067B32C2044B10050291F /* AssetManagementInteractor.swift */; }; + FAD067C02C2044B10050291F /* AssetManagementAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD067B42C2044B10050291F /* AssetManagementAssembly.swift */; }; + FAD067C12C2044B10050291F /* AssetManagementRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD067B52C2044B10050291F /* AssetManagementRouter.swift */; }; + FAD067C22C2044B10050291F /* AssetManagementPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD067B62C2044B10050291F /* AssetManagementPresenter.swift */; }; + FAD067C32C2044B10050291F /* AssetManagementViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD067B72C2044B10050291F /* AssetManagementViewController.swift */; }; + FAD067C42C2044B10050291F /* AssetManagementTableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD067B92C2044B10050291F /* AssetManagementTableCell.swift */; }; + FAD067C52C2044B10050291F /* AssetManagementTableHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD067BA2C2044B10050291F /* AssetManagementTableHeaderView.swift */; }; + FAD067C62C2044B10050291F /* AssetManagementProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD067BB2C2044B10050291F /* AssetManagementProtocols.swift */; }; + FAD067C72C2044B10050291F /* AssetManagementViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD067BC2C2044B10050291F /* AssetManagementViewLayout.swift */; }; + FAD067C92C2044D30050291F /* ChainAssetListViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD067C82C2044D30050291F /* ChainAssetListViewLayout.swift */; }; + FAD067CB2C2044F00050291F /* OnboardingConfigVersionResolver.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD067CA2C2044F00050291F /* OnboardingConfigVersionResolver.swift */; }; + FAD067CF2C20453E0050291F /* EraStakersFetching.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD067CC2C20453E0050291F /* EraStakersFetching.swift */; }; + FAD067D02C20453E0050291F /* LegacyEraStakersFetching.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD067CD2C20453E0050291F /* LegacyEraStakersFetching.swift */; }; + FAD067D12C20453E0050291F /* DefaultEraStakersFetching.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD067CE2C20453E0050291F /* DefaultEraStakersFetching.swift */; }; + FAD067D32C20550B0050291F /* UIImageView+Shimmered.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD067D22C20550B0050291F /* UIImageView+Shimmered.swift */; }; + FAD067D52C214E7C0050291F /* LiquidityPoolsConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD067D42C214E7C0050291F /* LiquidityPoolsConstants.swift */; }; FAD428942A834A8E001D6A16 /* TopViewControllerHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD428932A834A8E001D6A16 /* TopViewControllerHelper.swift */; }; FAD428962A834BA8001D6A16 /* UIApplication+TopViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD428952A834BA8001D6A16 /* UIApplication+TopViewController.swift */; }; FAD428982A860C9B001D6A16 /* EthereumNodeFetching.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD428972A860C9B001D6A16 /* EthereumNodeFetching.swift */; }; @@ -3005,7 +3077,6 @@ FAFFAE7C29AC84B10074AF1F /* KmmCallCodingPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAFFAE4D29AC84B10074AF1F /* KmmCallCodingPath.swift */; }; FAFFAE7D29AC84B10074AF1F /* SubqueryPageInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAFFAE4F29AC84B10074AF1F /* SubqueryPageInfo.swift */; }; FAFFAE7E29AC84B10074AF1F /* SubqueryDelegatorHistoryData.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAFFAE5029AC84B10074AF1F /* SubqueryDelegatorHistoryData.swift */; }; - FAFFAE7F29AC84B10074AF1F /* GraphQLResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAFFAE5129AC84B10074AF1F /* GraphQLResponse.swift */; }; FAFFAE8029AC84B10074AF1F /* SubqueryTransfer.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAFFAE5229AC84B10074AF1F /* SubqueryTransfer.swift */; }; FAFFAE8129AC84B10074AF1F /* SubqueryDelegatorHistoryElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAFFAE5329AC84B10074AF1F /* SubqueryDelegatorHistoryElement.swift */; }; FAFFAE8229AC84B10074AF1F /* SubqueryDelegatorHistoryItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAFFAE5429AC84B10074AF1F /* SubqueryDelegatorHistoryItem.swift */; }; @@ -3041,12 +3112,13 @@ FAFFAEA229AC84D30074AF1F /* HexColorConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAFFAEA029AC84D30074AF1F /* HexColorConverter.swift */; }; FAFFAEA429AC850A0074AF1F /* TimeInterval+Debounce.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAFFAEA329AC850A0074AF1F /* TimeInterval+Debounce.swift */; }; FAFFAEA629AC851A0074AF1F /* Bool + Inverted.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAFFAEA529AC851A0074AF1F /* Bool + Inverted.swift */; }; - FAFFAEA829AC85230074AF1F /* ZeroBalancesSettingChanged.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAFFAEA729AC85230074AF1F /* ZeroBalancesSettingChanged.swift */; }; FAFFAEAB29AC90E50074AF1F /* SubsquidPayoutValidatorsForNominatorFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAFFAEA929AC90E50074AF1F /* SubsquidPayoutValidatorsForNominatorFactory.swift */; }; FAFFAEAC29AC90E50074AF1F /* SubqueryPayoutValidatorsForNominatorFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAFFAEAA29AC90E50074AF1F /* SubqueryPayoutValidatorsForNominatorFactory.swift */; }; FB214D3851B28AA8FF05AA41 /* NftCollectionViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 610A7425DF3F20BE0AB05ECD /* NftCollectionViewLayout.swift */; }; FB377FFB8421F09C875E1968 /* NftDetailsInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09373C708FE543066B943E45 /* NftDetailsInteractor.swift */; }; FB6B2B551238260D754E036D /* NftSendConfirmViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 447D03660EFFD8CF46374D85 /* NftSendConfirmViewController.swift */; }; + FBE4702B7F95484235386631 /* LiquidityPoolSupplyConfirmRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5121DA4DDF11ED6A6659CEB /* LiquidityPoolSupplyConfirmRouter.swift */; }; + FC540426B1BC363842A3677B /* LiquidityPoolRemoveLiquidityInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6887529305794E17D9434D44 /* LiquidityPoolRemoveLiquidityInteractor.swift */; }; FC54046997436059EF436983 /* NftSendRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01A85735F958D05CFEFCB4DF /* NftSendRouter.swift */; }; FC9BD9BC4722D8B17B7A7ACC /* MainNftContainerProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0892AD886F2BE499C075C701 /* MainNftContainerProtocols.swift */; }; FE65F897D63CAA8F8AE4B972 /* NftCollectionAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7DE7B3D0BE06472153C0A78C /* NftCollectionAssembly.swift */; }; @@ -3084,19 +3156,7 @@ 04806331BF10F63A49326941 /* NetworkInfoWireframe.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NetworkInfoWireframe.swift; sourceTree = ""; }; 04EF69DFE142600FF2708A13 /* ControllerAccountConfirmationViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ControllerAccountConfirmationViewController.swift; sourceTree = ""; }; 0533F9E531CDFB721D697769 /* YourValidatorListPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = YourValidatorListPresenter.swift; sourceTree = ""; }; - 070179602BC7F91600908C83 /* ChainAssetListViewLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChainAssetListViewLayout.swift; sourceTree = ""; }; - 070179652BCA3D4F00908C83 /* AssetManagementViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetManagementViewModel.swift; sourceTree = ""; }; - 070179662BCA3D4F00908C83 /* AssetManagementViewModelFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetManagementViewModelFactory.swift; sourceTree = ""; }; - 070179672BCA3D4F00908C83 /* AssetManagementInteractor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetManagementInteractor.swift; sourceTree = ""; }; - 070179682BCA3D4F00908C83 /* AssetManagementAssembly.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetManagementAssembly.swift; sourceTree = ""; }; - 070179692BCA3D4F00908C83 /* AssetManagementRouter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetManagementRouter.swift; sourceTree = ""; }; - 0701796A2BCA3D4F00908C83 /* AssetManagementPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetManagementPresenter.swift; sourceTree = ""; }; - 0701796B2BCA3D4F00908C83 /* AssetManagementViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetManagementViewController.swift; sourceTree = ""; }; - 0701796D2BCA3D4F00908C83 /* AssetManagementTableCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetManagementTableCell.swift; sourceTree = ""; }; - 0701796E2BCA3D4F00908C83 /* AssetManagementTableHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetManagementTableHeaderView.swift; sourceTree = ""; }; - 0701796F2BCA3D4F00908C83 /* AssetManagementProtocols.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetManagementProtocols.swift; sourceTree = ""; }; - 070179702BCA3D4F00908C83 /* AssetManagementViewLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetManagementViewLayout.swift; sourceTree = ""; }; - 0701797C2BCA3D6100908C83 /* WalletAssetsObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletAssetsObserver.swift; sourceTree = ""; }; + 06F6B892F62579DE761073CA /* LiquidityPoolSupplyConfirmPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolSupplyConfirmPresenter.swift; sourceTree = ""; }; 0702B31429701759003519F5 /* AmountInputViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AmountInputViewModel.swift; sourceTree = ""; }; 0702B31729701864003519F5 /* WalletViewModelObserverContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletViewModelObserverContainer.swift; sourceTree = ""; }; 0702B31929701884003519F5 /* MoneyPresentable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoneyPresentable.swift; sourceTree = ""; }; @@ -3119,10 +3179,6 @@ 070B2C5D289CE49700F78F82 /* SelectableListViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectableListViewController.swift; sourceTree = ""; }; 070B2C60289CFE0000F78F82 /* SelectedNetworkButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectedNetworkButton.swift; sourceTree = ""; }; 070CDD6C2ACAACB900F3F20A /* EthereumRemoteBalanceFetching.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EthereumRemoteBalanceFetching.swift; sourceTree = ""; }; - 070CDD6F2ACACEDA00F3F20A /* QRMatcherProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRMatcherProtocol.swift; sourceTree = ""; }; - 070CDD742ACAE04100F3F20A /* SoraQRInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoraQRInfo.swift; sourceTree = ""; }; - 070CDD762ACAE05D00F3F20A /* CexQRInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CexQRInfo.swift; sourceTree = ""; }; - 070CDD782ACBE19000F3F20A /* BokoloCashQRInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BokoloCashQRInfo.swift; sourceTree = ""; }; 070CDD7B2ACBE59700F3F20A /* ReceiveAssetViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReceiveAssetViewModel.swift; sourceTree = ""; }; 070CDD7C2ACBE59700F3F20A /* ReceiveAndRequestAssetRouter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReceiveAndRequestAssetRouter.swift; sourceTree = ""; }; 070CDD7D2ACBE59700F3F20A /* ReceiveAndRequestAssetViewLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReceiveAndRequestAssetViewLayout.swift; sourceTree = ""; }; @@ -3151,30 +3207,17 @@ 073417B0298BA28300104F41 /* EquilibriumTotalBalanceServiceFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EquilibriumTotalBalanceServiceFactory.swift; sourceTree = ""; }; 073417B1298BA28300104F41 /* EquilibriumTotalWalletService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EquilibriumTotalWalletService.swift; sourceTree = ""; }; 07349F3128FE5EEB00A802B9 /* SwipeCellButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwipeCellButton.swift; sourceTree = ""; }; - 0739FD292BFB4A70009ADD7C /* EraStakersFetching.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EraStakersFetching.swift; sourceTree = ""; }; - 0739FD2A2BFB4A70009ADD7C /* DefaultEraStakersFetching.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultEraStakersFetching.swift; sourceTree = ""; }; - 0739FD2B2BFB4A70009ADD7C /* LegacyEraStakersFetching.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LegacyEraStakersFetching.swift; sourceTree = ""; }; - 0739FD2F2BFB4B98009ADD7C /* ErasStakersOverviewKey.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ErasStakersOverviewKey.swift; sourceTree = ""; }; - 0739FD302BFB4B98009ADD7C /* ErasStakersPagedKey.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ErasStakersPagedKey.swift; sourceTree = ""; }; 073B34BB2AE8CC4500DC5106 /* WalletConnectDisconnectService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletConnectDisconnectService.swift; sourceTree = ""; }; 073B34BE2AE91FE600DC5106 /* WalletConnectProposalDataValidating.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletConnectProposalDataValidating.swift; sourceTree = ""; }; - 074D832C2BCA490900AD1336 /* UIImage+Monochrome.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+Monochrome.swift"; sourceTree = ""; }; - 074D832E2BCA496300AD1336 /* ChainAssetListBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChainAssetListBuilder.swift; sourceTree = ""; }; - 074D83302BCA49BF00AD1336 /* UIImageView+Shimmered.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImageView+Shimmered.swift"; sourceTree = ""; }; - 074D83322BCA4A4200AD1336 /* AssetManagementMigrator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetManagementMigrator.swift; sourceTree = ""; }; - 074D83372BCA946200AD1336 /* AccountInfoRemoteService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountInfoRemoteService.swift; sourceTree = ""; }; - 074D833A2BCAAE7C00AD1336 /* Requests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Requests.swift; sourceTree = ""; }; 074EB7A9290B9E20000A2A6A /* ApplicationStatusAlertEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationStatusAlertEvent.swift; sourceTree = ""; }; 074EB7AC290B9F64000A2A6A /* AddressCopiedEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressCopiedEvent.swift; sourceTree = ""; }; 074EB7AE290BA056000A2A6A /* ConnectionOfflineEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectionOfflineEvent.swift; sourceTree = ""; }; 074EB7B0290BA142000A2A6A /* ConnectionOnlineEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectionOnlineEvent.swift; sourceTree = ""; }; - 075A2F092BF722F300CE6F24 /* ExternalApiExplorerType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExternalApiExplorerType.swift; sourceTree = ""; }; 075C646F28098AFB00A55094 /* EthereumConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EthereumConstants.swift; sourceTree = ""; }; 075FC63428D9AB1600E25263 /* CommonInputViewV2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonInputViewV2.swift; sourceTree = ""; }; 0761DEB128E1F54D00B90D2C /* StakingPoolCreateViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StakingPoolCreateViewModel.swift; sourceTree = ""; }; 0761DEB328E1F57600B90D2C /* StakingPoolCreateViewModelFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StakingPoolCreateViewModelFactory.swift; sourceTree = ""; }; 0765296C2AD9517E00BA1D99 /* PolkaswapService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PolkaswapService.swift; sourceTree = ""; }; - 0768FBBD2BDCEDC300FB126F /* ChainConnectionVisibilityHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChainConnectionVisibilityHelper.swift; sourceTree = ""; }; 07696A2C28BDC81F00B17040 /* ReaderWriterLock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReaderWriterLock.swift; sourceTree = ""; }; 076D9D2B29370C33002762E3 /* MarketButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarketButton.swift; sourceTree = ""; }; 076D9D2D2939B77F002762E3 /* PolkaswapOperationFactoryProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PolkaswapOperationFactoryProtocol.swift; sourceTree = ""; }; @@ -3221,7 +3264,6 @@ 07B6BC7E28BC71DB00621864 /* NetworkIssuesNotificationViewModelFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkIssuesNotificationViewModelFactory.swift; sourceTree = ""; }; 07B6BC8028BC720F00621864 /* NetworkIssuesNotificationCellViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkIssuesNotificationCellViewModel.swift; sourceTree = ""; }; 07B6BC8328BC723500621864 /* NetworkIssuesNotificationTableCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkIssuesNotificationTableCell.swift; sourceTree = ""; }; - 07BE13CB2C071E7800EC7424 /* SubstrateDataModel_v6.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = SubstrateDataModel_v6.xcdatamodel; sourceTree = ""; }; 07BF3D932B3D873F0046ABF4 /* OklinkHistoryOperationFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OklinkHistoryOperationFactory.swift; sourceTree = ""; }; 07BF3D952B3D8B3A0046ABF4 /* PriceDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PriceDataSource.swift; sourceTree = ""; }; 07BF3D982B3D8BCD0046ABF4 /* ChainlinkOperationFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChainlinkOperationFactory.swift; sourceTree = ""; }; @@ -3291,6 +3333,7 @@ 07DFA466289B8D8E0035A8AB /* EducationStoriesAssembly.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EducationStoriesAssembly.swift; sourceTree = ""; }; 07DFA467289B8D8E0035A8AB /* EducationStoriesViewState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EducationStoriesViewState.swift; sourceTree = ""; }; 07E346D3288E616E00A8FAEC /* WalletBalanceBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletBalanceBuilder.swift; sourceTree = ""; }; + 07ED2EB82C341A0100FF7500 /* NodeApiKeyInjector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeApiKeyInjector.swift; sourceTree = ""; }; 07F2B75628A3A4B800280C38 /* ChainCollectionView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChainCollectionView.swift; sourceTree = ""; }; 07F2B75A28A6533900280C38 /* assets.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = assets.json; sourceTree = ""; }; 07F2B75B28A6535B00280C38 /* chains.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = chains.json; sourceTree = ""; }; @@ -3321,6 +3364,7 @@ 0E07F60661001B2C505D9C8B /* SelectMarketPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SelectMarketPresenter.swift; sourceTree = ""; }; 0F48467D97F9D06F83F70894 /* Pods-fearlessAll-fearless.dev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-fearlessAll-fearless.dev.xcconfig"; path = "Target Support Files/Pods-fearlessAll-fearless/Pods-fearlessAll-fearless.dev.xcconfig"; sourceTree = ""; }; 0F67BB672040911E4A165446 /* PolkaswapSwapConfirmationViewLayout.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PolkaswapSwapConfirmationViewLayout.swift; sourceTree = ""; }; + 112609AE5629962646248BF0 /* LiquidityPoolSupplyConfirmAssembly.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolSupplyConfirmAssembly.swift; sourceTree = ""; }; 1211B723BB656770C4EA5BC2 /* WalletTransactionDetailsViewFactory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WalletTransactionDetailsViewFactory.swift; sourceTree = ""; }; 12441689D2AF47D508D16CCF /* WalletSendConfirmViewFactory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WalletSendConfirmViewFactory.swift; sourceTree = ""; }; 1366336078BCA34EFB4C6FF9 /* CrowdloanContributionConfirmInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CrowdloanContributionConfirmInteractor.swift; sourceTree = ""; }; @@ -3339,6 +3383,7 @@ 1A7B39A61DB0D2F0F1B1DBA1 /* AccountCreateInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AccountCreateInteractor.swift; sourceTree = ""; }; 1AF4258723E2FACBBA556D00 /* WalletSendConfirmTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WalletSendConfirmTests.swift; sourceTree = ""; }; 1B08B264C09E63A936384E2A /* NftDetailsRouter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NftDetailsRouter.swift; sourceTree = ""; }; + 1B3E9CA265E5C0F3E83429CE /* LiquidityPoolRemoveLiquidityPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolRemoveLiquidityPresenter.swift; sourceTree = ""; }; 1BE8644A4F6DED808248A0FE /* YourValidatorListViewFactory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = YourValidatorListViewFactory.swift; sourceTree = ""; }; 1C52C6CD7112BF0E1E3A98CE /* PurchaseWireframe.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PurchaseWireframe.swift; sourceTree = ""; }; 1CA950D301F6605D204E99F3 /* PolkaswapSwapConfirmationAssembly.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PolkaswapSwapConfirmationAssembly.swift; sourceTree = ""; }; @@ -3359,6 +3404,7 @@ 23BC71941B91D3E372CDB11C /* CrowdloanContributionSetupViewLayout.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CrowdloanContributionSetupViewLayout.swift; sourceTree = ""; }; 23CF7E56EC624BDB60290387 /* CreateContactPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CreateContactPresenter.swift; sourceTree = ""; }; 25B80FDDB5C3032A0BBBD826 /* NftCollectionPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NftCollectionPresenter.swift; sourceTree = ""; }; + 25D9454047EBBD8D8A0174A4 /* LiquidityPoolRemoveLiquidityRouter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolRemoveLiquidityRouter.swift; sourceTree = ""; }; 25FF82C2FD912021A1F20876 /* PolkaswapAdjustmentViewLayout.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PolkaswapAdjustmentViewLayout.swift; sourceTree = ""; }; 262F98DEF54FA9592BE22B94 /* AllDoneAssembly.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AllDoneAssembly.swift; sourceTree = ""; }; 2648EEF96694A7FEC94520E8 /* WalletHistoryFilterTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WalletHistoryFilterTests.swift; sourceTree = ""; }; @@ -3366,6 +3412,7 @@ 270B309EC85D8897A4ADD98A /* CustomValidatorListViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CustomValidatorListViewController.swift; sourceTree = ""; }; 27D5AF2F7609ADE855308089 /* AccountExportPasswordViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AccountExportPasswordViewController.swift; sourceTree = ""; }; 28CCDB1822156D69578A3042 /* StakingPoolInfoPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StakingPoolInfoPresenter.swift; sourceTree = ""; }; + 28E3B4BA1160B87C435C2AAF /* LiquidityPoolDetailsRouter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolDetailsRouter.swift; sourceTree = ""; }; 28EF0F9F97C89137F642016E /* SelectValidatorsConfirmTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SelectValidatorsConfirmTests.swift; sourceTree = ""; }; 28F5B57A24265C36A5F19B78 /* CrowdloanContributionConfirmPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CrowdloanContributionConfirmPresenter.swift; sourceTree = ""; }; 29100320799A2B46836A257B /* AnalyticsRewardDetailsViewFactory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AnalyticsRewardDetailsViewFactory.swift; sourceTree = ""; }; @@ -3381,6 +3428,7 @@ 2B55A4C7E8BD87A7C8634ADD /* WalletsManagmentRouter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WalletsManagmentRouter.swift; sourceTree = ""; }; 2BE0492B98AB9C1540846B39 /* StakingPayoutConfirmationViewFactory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StakingPayoutConfirmationViewFactory.swift; sourceTree = ""; }; 2C542733CEFB871FCD23195E /* NftSendConfirmInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NftSendConfirmInteractor.swift; sourceTree = ""; }; + 2CF682B92176E0FED5D7B4DB /* LiquidityPoolDetailsTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolDetailsTests.swift; sourceTree = ""; }; 2D9C58C9D53A7EA34E5CB00C /* NftSendConfirmAssembly.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NftSendConfirmAssembly.swift; sourceTree = ""; }; 2E4B0600AFFB96A75CF98755 /* StakingRedeemProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StakingRedeemProtocols.swift; sourceTree = ""; }; 2E57C70327E8AB3D00AF075A /* CrowdloanWikiTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrowdloanWikiTableViewCell.swift; sourceTree = ""; }; @@ -3393,6 +3441,8 @@ 31226053044986BC828AA912 /* AccountExportPasswordPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AccountExportPasswordPresenter.swift; sourceTree = ""; }; 312DE7ADA5ABC3214AD3D4AD /* StakingAmountInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StakingAmountInteractor.swift; sourceTree = ""; }; 31302AE4D5325D2AEC030832 /* AllDoneRouter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AllDoneRouter.swift; sourceTree = ""; }; + 31F75A22E215273305AF7AA2 /* LiquidityPoolRemoveLiquidityConfirmTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolRemoveLiquidityConfirmTests.swift; sourceTree = ""; }; + 31F848482B2AD7D6831B0CCE /* LiquidityPoolSupplyPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolSupplyPresenter.swift; sourceTree = ""; }; 320E2207FB549F7C31A80441 /* SelectMarketViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SelectMarketViewController.swift; sourceTree = ""; }; 3211D250E4167C916B8B9D6A /* NetworkIssuesNotificationRouter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NetworkIssuesNotificationRouter.swift; sourceTree = ""; }; 326260E461C031624CDB62BA /* WalletOptionInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WalletOptionInteractor.swift; sourceTree = ""; }; @@ -3408,15 +3458,19 @@ 3837CE5CB2D48D8A694A7EE0 /* StakingPoolCreateConfirmPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StakingPoolCreateConfirmPresenter.swift; sourceTree = ""; }; 385FE8691EA37DE9F562B34E /* CrowdloanContributionConfirmTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CrowdloanContributionConfirmTests.swift; sourceTree = ""; }; 38B543AA1B941C76CB021051 /* Pods-fearlessTests.dev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-fearlessTests.dev.xcconfig"; path = "Target Support Files/Pods-fearlessTests/Pods-fearlessTests.dev.xcconfig"; sourceTree = ""; }; + 3A43F0468DEBA7500C6B23AF /* LiquidityPoolSupplyConfirmTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolSupplyConfirmTests.swift; sourceTree = ""; }; 3A93673EEA8F71E8DDA84557 /* StakingRedeemWireframe.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StakingRedeemWireframe.swift; sourceTree = ""; }; 3ABDA8952766DE724CD078D6 /* NodeSelectionPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NodeSelectionPresenter.swift; sourceTree = ""; }; 3B0E2EDF787BF82F16663215 /* NetworkInfoViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NetworkInfoViewController.swift; sourceTree = ""; }; 3B6244A9538B39AFCD3A6F3A /* SelectValidatorsStartPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SelectValidatorsStartPresenter.swift; sourceTree = ""; }; 3B8473AA386E1AD6F0F0C964 /* ControllerAccountConfirmationInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ControllerAccountConfirmationInteractor.swift; sourceTree = ""; }; + 3BA8DC8007FC0A322C6DF00E /* LiquidityPoolsOverviewPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolsOverviewPresenter.swift; sourceTree = ""; }; 3D2C2FC3E31C03D08BDEC7A1 /* PolkaswapAdjustmentRouter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PolkaswapAdjustmentRouter.swift; sourceTree = ""; }; + 3D49CA5CB156C1EA38BEBE00 /* LiquidityPoolRemoveLiquidityProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolRemoveLiquidityProtocols.swift; sourceTree = ""; }; 3E992CCDC1D581F7E9D3F1CA /* AccountConfirmInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AccountConfirmInteractor.swift; sourceTree = ""; }; 3EDA19BC3280F1838C687EC8 /* NetworkInfoViewFactory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NetworkInfoViewFactory.swift; sourceTree = ""; }; 3F1D5849A2EBF462B32F3A9C /* ExportSeedProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ExportSeedProtocols.swift; sourceTree = ""; }; + 3F25F3A88B4BEB4DE498220C /* LiquidityPoolsOverviewRouter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolsOverviewRouter.swift; sourceTree = ""; }; 3F47E5832513985B89D06155 /* AccountExportPasswordWireframe.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AccountExportPasswordWireframe.swift; sourceTree = ""; }; 3F5C47F8D6CB97D16DFF06B7 /* WalletsManagmentInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WalletsManagmentInteractor.swift; sourceTree = ""; }; 3F7068913923A6DEEE9D8EA0 /* CrowdloanContributionSetupPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CrowdloanContributionSetupPresenter.swift; sourceTree = ""; }; @@ -3428,10 +3482,12 @@ 40B47961B2254E8A4D8EC588 /* StakingAmountPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StakingAmountPresenter.swift; sourceTree = ""; }; 4191E0055768541F6A3D8A61 /* StakingRewardPayoutsInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StakingRewardPayoutsInteractor.swift; sourceTree = ""; }; 41E19988955B1C159EDA2555 /* WalletsManagmentPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WalletsManagmentPresenter.swift; sourceTree = ""; }; + 438E01C5C877428168E9F3F8 /* LiquidityPoolSupplyViewLayout.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolSupplyViewLayout.swift; sourceTree = ""; }; 446B4A7184327D64AE8F0610 /* WarningAlertProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WarningAlertProtocols.swift; sourceTree = ""; }; 447D03660EFFD8CF46374D85 /* NftSendConfirmViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NftSendConfirmViewController.swift; sourceTree = ""; }; 447FE0DC90DF4B4D13CADE62 /* NodeSelectionInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NodeSelectionInteractor.swift; sourceTree = ""; }; 44FDDC470A6921DC2258939E /* WalletMainContainerViewLayout.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WalletMainContainerViewLayout.swift; sourceTree = ""; }; + 4594686D10DBB7627B8C9A12 /* LiquidityPoolSupplyConfirmInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolSupplyConfirmInteractor.swift; sourceTree = ""; }; 45C8249F3F41DC0FFCF27EFF /* NftSendTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NftSendTests.swift; sourceTree = ""; }; 470B64C45E547C25FCCCFC33 /* StakingMainProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StakingMainProtocols.swift; sourceTree = ""; }; 47759907380BE9300E54DC78 /* ExportMnemonicViewFactory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ExportMnemonicViewFactory.swift; sourceTree = ""; }; @@ -3439,6 +3495,7 @@ 480AE579B48B3DA9C247CCB5 /* CreateContactViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CreateContactViewController.swift; sourceTree = ""; }; 48C158C8D1855BCE53636934 /* AccountCreateProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AccountCreateProtocols.swift; sourceTree = ""; }; 4952E0B8F8DCD92FE4A37892 /* AddCustomNodeViewLayout.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AddCustomNodeViewLayout.swift; sourceTree = ""; }; + 497EFA05A2D8076BFE82964D /* LiquidityPoolSupplyViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolSupplyViewController.swift; sourceTree = ""; }; 49C564052FAA3160AA8975CB /* NftSendAssembly.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NftSendAssembly.swift; sourceTree = ""; }; 49EBB77A32A59568B0DACFE5 /* StakingPoolCreateProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StakingPoolCreateProtocols.swift; sourceTree = ""; }; 4B3B14C046584AAAF483715F /* WalletTransactionHistoryWireframe.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WalletTransactionHistoryWireframe.swift; sourceTree = ""; }; @@ -3488,6 +3545,7 @@ 5D81DBDDD34EA20C3270EDB4 /* AddCustomNodeViewFactory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AddCustomNodeViewFactory.swift; sourceTree = ""; }; 5E096A576B747C09B14FD38D /* WalletMainContainerAssembly.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WalletMainContainerAssembly.swift; sourceTree = ""; }; 5E11C7AF9A8DEC07246D5626 /* StakingMainTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StakingMainTests.swift; sourceTree = ""; }; + 5F6F7AE5AFF3F2E7BADA02BB /* LiquidityPoolDetailsAssembly.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolDetailsAssembly.swift; sourceTree = ""; }; 5F791FE1B479CE1DF936F79F /* CrowdloanContributionConfirmViewFactory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CrowdloanContributionConfirmViewFactory.swift; sourceTree = ""; }; 5FC428EB695A80397BDC621C /* PolkaswapAdjustmentAssembly.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PolkaswapAdjustmentAssembly.swift; sourceTree = ""; }; 5FCECA20E6DCA5D228F44477 /* StakingUnbondSetupPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StakingUnbondSetupPresenter.swift; sourceTree = ""; }; @@ -3499,16 +3557,23 @@ 61E1CD099F7C30ABE0E8A001 /* StakingUnbondSetupTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StakingUnbondSetupTests.swift; sourceTree = ""; }; 61EBE466BDCF77E65FDCDF81 /* ExportMnemonicPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ExportMnemonicPresenter.swift; sourceTree = ""; }; 6216F6F1B91F798F07695FB6 /* StakingAmountWireframe.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StakingAmountWireframe.swift; sourceTree = ""; }; + 62928FB3556EEA3A228131AC /* LiquidityPoolSupplyAssembly.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolSupplyAssembly.swift; sourceTree = ""; }; 62FA66143B25AA70B02CE461 /* ExportSeedViewFactory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ExportSeedViewFactory.swift; sourceTree = ""; }; 638A65DAC86BAF9EB4D2F2F8 /* StakingRewardDetailsWireframe.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StakingRewardDetailsWireframe.swift; sourceTree = ""; }; 639AD37D87BD08106E7E6E2A /* WarningAlertWireframe.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WarningAlertWireframe.swift; sourceTree = ""; }; 63B11A7ADEF107B6341C378F /* Pods-fearlessAll-fearlessIntegrationTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-fearlessAll-fearlessIntegrationTests.release.xcconfig"; path = "Target Support Files/Pods-fearlessAll-fearlessIntegrationTests/Pods-fearlessAll-fearlessIntegrationTests.release.xcconfig"; sourceTree = ""; }; 63CCCC63389A70294F816143 /* NodeSelectionProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NodeSelectionProtocols.swift; sourceTree = ""; }; 63F4BE52D0625CD8C21D2460 /* CrowdloanListViewLayout.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CrowdloanListViewLayout.swift; sourceTree = ""; }; + 6419D75A346CE10236161522 /* LiquidityPoolRemoveLiquidityViewLayout.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolRemoveLiquidityViewLayout.swift; sourceTree = ""; }; + 641B699003FF648A380F7FA6 /* LiquidityPoolSupplyConfirmViewLayout.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolSupplyConfirmViewLayout.swift; sourceTree = ""; }; + 6503D178156C6407EC848D41 /* LiquidityPoolSupplyRouter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolSupplyRouter.swift; sourceTree = ""; }; 65AD15693E21C869DE1FDD17 /* UsernameSetupWireframe.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = UsernameSetupWireframe.swift; sourceTree = ""; }; 66FFB904E5A83F2EFBCCBBF8 /* StakingPoolInfoTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StakingPoolInfoTests.swift; sourceTree = ""; }; + 6717FF1B7777400B62F028C3 /* LiquidityPoolsOverviewInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolsOverviewInteractor.swift; sourceTree = ""; }; 67B1037AEC97DBEAF9FD50C1 /* AssetNetworksPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AssetNetworksPresenter.swift; sourceTree = ""; }; 67B3E1906EEBE32E71E82BB6 /* NodeSelectionViewLayout.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NodeSelectionViewLayout.swift; sourceTree = ""; }; + 67BDE520860A67C800E7F4AB /* LiquidityPoolDetailsViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolDetailsViewController.swift; sourceTree = ""; }; + 6887529305794E17D9434D44 /* LiquidityPoolRemoveLiquidityInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolRemoveLiquidityInteractor.swift; sourceTree = ""; }; 6897929D244B5C29E3FD0727 /* StakingPoolCreateRouter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StakingPoolCreateRouter.swift; sourceTree = ""; }; 69B00AC48FB7D11855875EB9 /* SwapTransactionDetailPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SwapTransactionDetailPresenter.swift; sourceTree = ""; }; 6A28799A82C0EC2F8ABDE831 /* Pods_fearlessAll_fearless.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_fearlessAll_fearless.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -3552,9 +3617,11 @@ 80809FE46E7B8EBDE3680706 /* NodeSelectionWireframe.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NodeSelectionWireframe.swift; sourceTree = ""; }; 80C632A122CE8D02B84806C3 /* WalletMainContainerRouter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WalletMainContainerRouter.swift; sourceTree = ""; }; 80DE21374A7FA5AE4D26CEB2 /* ChainAccountBalanceListTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ChainAccountBalanceListTests.swift; sourceTree = ""; }; + 81E9DD6EB14A352635BAC711 /* LiquidityPoolDetailsPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolDetailsPresenter.swift; sourceTree = ""; }; 82072889A33037BFC9D8F574 /* NftDetailsTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NftDetailsTests.swift; sourceTree = ""; }; 82CBCBA8BF2D753248238555 /* ContactsViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ContactsViewController.swift; sourceTree = ""; }; 82FD4E0BB1ABA364AFD2E891 /* WalletTransactionDetailsPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WalletTransactionDetailsPresenter.swift; sourceTree = ""; }; + 835D5A5DD9258786D27BDC23 /* LiquidityPoolRemoveLiquidityViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolRemoveLiquidityViewController.swift; sourceTree = ""; }; 83AB0AD3A7CECD061611F60C /* ChainSelectionInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ChainSelectionInteractor.swift; sourceTree = ""; }; 8400F0B7252BBCFA00E6B4CB /* WalletSelectAccountCommandTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletSelectAccountCommandTests.swift; sourceTree = ""; }; 8400F0B9252BBD2200E6B4CB /* WalletCommandFactoryProtocolMock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletCommandFactoryProtocolMock.swift; sourceTree = ""; }; @@ -3622,7 +3689,6 @@ 842349C42624E98C0066ACFE /* MultiAddress+Query.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MultiAddress+Query.swift"; sourceTree = ""; }; 8423ADCF26B2C38600057EDD /* ImportantFlowViewFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImportantFlowViewFactory.swift; sourceTree = ""; }; 8423ADD126B2C9D000057EDD /* ImportantViewProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImportantViewProtocol.swift; sourceTree = ""; }; - 8423B0DF251A759000B8687C /* Chain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Chain.swift; sourceTree = ""; }; 8423B0E7251B2DAD00B8687C /* SubstrateOperationFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubstrateOperationFactory.swift; sourceTree = ""; }; 8424308C265B1814003E07EC /* CrowdloanOperationFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrowdloanOperationFactory.swift; sourceTree = ""; }; 84243094265B1888003E07EC /* CrowdloanMetadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrowdloanMetadata.swift; sourceTree = ""; }; @@ -3648,7 +3714,6 @@ 8428765E24ADE0BB00D91AD8 /* UserSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSettings.swift; sourceTree = ""; }; 8428766624ADF22000D91AD8 /* TransformAnimator+Common.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TransformAnimator+Common.swift"; sourceTree = ""; }; 8428766824ADF27D00D91AD8 /* AuthorizationPresentable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthorizationPresentable.swift; sourceTree = ""; }; - 8428766A24ADF51D00D91AD8 /* UIViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIViewController.swift; sourceTree = ""; }; 8428766D24AE046200D91AD8 /* LanguageSelectionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LanguageSelectionViewController.swift; sourceTree = ""; }; 8428766E24AE046200D91AD8 /* LanguageSelectionInteractor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LanguageSelectionInteractor.swift; sourceTree = ""; }; 8428766F24AE046200D91AD8 /* LanguageSelectionProtocols.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LanguageSelectionProtocols.swift; sourceTree = ""; }; @@ -3710,6 +3775,7 @@ 8434C9E525403686009E4191 /* CDTransactionHistoryItem+CoreDataDecodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CDTransactionHistoryItem+CoreDataDecodable.swift"; sourceTree = ""; }; 8434C9E92540AE51009E4191 /* ExtrinsicEraTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtrinsicEraTests.swift; sourceTree = ""; }; 8436E94326C853E4003D4EA7 /* RuntimeSnapshotOperationFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuntimeSnapshotOperationFactory.swift; sourceTree = ""; }; + 8436E94526C85405003D4EA7 /* RuntimeSnapshot.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuntimeSnapshot.swift; sourceTree = ""; }; 8436EDE125895804004D9E97 /* RampProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RampProvider.swift; sourceTree = ""; }; 8436EDE625895846004D9E97 /* PurchaseProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PurchaseProvider.swift; sourceTree = ""; }; 8436EDEE25896722004D9E97 /* PurchaseAggregator+Default.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PurchaseAggregator+Default.swift"; sourceTree = ""; }; @@ -3760,6 +3826,8 @@ 8444D1732671372800AF6D8C /* BytesCodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BytesCodable.swift; sourceTree = ""; }; 8444D1BD2671465A00AF6D8C /* CrowdloanBonusServiceError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrowdloanBonusServiceError.swift; sourceTree = ""; }; 84452A5F25D037AE00F47EC5 /* ChainStorage+Decodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ChainStorage+Decodable.swift"; sourceTree = ""; }; + 84452F2A25D5B84200F47EC5 /* RuntimeRegistryServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuntimeRegistryServiceProtocol.swift; sourceTree = ""; }; + 84452F4D25D5BB1C00F47EC5 /* RuntimeCoderFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuntimeCoderFactory.swift; sourceTree = ""; }; 84452F5725D5C30600F47EC5 /* FilesRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilesRepository.swift; sourceTree = ""; }; 84452F5C25D5CB3B00F47EC5 /* FileManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileManagerTests.swift; sourceTree = ""; }; 84452F7025D5E2B300F47EC5 /* runtime-westend.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "runtime-westend.json"; sourceTree = ""; }; @@ -4195,6 +4263,7 @@ 84C3F78B26020DE800D47501 /* StakingStateMachineProtocols.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StakingStateMachineProtocols.swift; sourceTree = ""; }; 84C4C2D6255D2B780045B582 /* PinChangeWireframe.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinChangeWireframe.swift; sourceTree = ""; }; 84C4C2F8255DB9510045B582 /* PinChangeInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinChangeInteractor.swift; sourceTree = ""; }; + 84C4CAC8978B0848DF5FD6FE /* LiquidityPoolSupplyTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolSupplyTests.swift; sourceTree = ""; }; 84C515FA26D84F8C000DBA45 /* AccountImportWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountImportWrapper.swift; sourceTree = ""; }; 84C6800D24D6ECE800006BF5 /* ExpandableActionControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExpandableActionControl.swift; sourceTree = ""; }; 84C6800F24D6EE4500006BF5 /* PlusIndicatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlusIndicatorView.swift; sourceTree = ""; }; @@ -4220,6 +4289,7 @@ 84CA68E026BEAC7C003B9453 /* SpecVersionSubscriptionFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpecVersionSubscriptionFactory.swift; sourceTree = ""; }; 84CB224F270360AC0041C8C1 /* RelaychainStakingLocalSubscriptionFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelaychainStakingLocalSubscriptionFactory.swift; sourceTree = ""; }; 84CCBFBB2509709500180F4F /* UIBarButtonItem+Style.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIBarButtonItem+Style.swift"; sourceTree = ""; }; + 84CD356F252620FB0081BC0B /* CryptoType+Extrinsic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CryptoType+Extrinsic.swift"; sourceTree = ""; }; 84CD82AD263C1452001A6F01 /* SubstrateProviderSubscriber.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubstrateProviderSubscriber.swift; sourceTree = ""; }; 84CD82B2263C30BC001A6F01 /* SubstrateProviderSubscriptionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubstrateProviderSubscriptionHandler.swift; sourceTree = ""; }; 84CE69DC2565BB6400559427 /* AboutViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutViewModel.swift; sourceTree = ""; }; @@ -4309,7 +4379,6 @@ 84DF21A225347042005454AE /* DetailsDisplayTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = DetailsDisplayTableViewCell.xib; sourceTree = ""; }; 84DF21A4253473B0005454AE /* ModalInfoFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalInfoFactory.swift; sourceTree = ""; }; 84DF21B425388B35005454AE /* Scheduler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Scheduler.swift; sourceTree = ""; }; - 84E1CCF4260DCB91001E81B5 /* SwitchAccount+AccountManagementWireframe.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SwitchAccount+AccountManagementWireframe.swift"; sourceTree = ""; }; 84E1CCF9260DCBF9001E81B5 /* SwitchAccount+UsernameSetupWireframe.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SwitchAccount+UsernameSetupWireframe.swift"; sourceTree = ""; }; 84E1CD01260DCC62001E81B5 /* SwitchAccount+OnboardingMainWireframe.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SwitchAccount+OnboardingMainWireframe.swift"; sourceTree = ""; }; 84E1CD06260DCCE8001E81B5 /* SwitchAccount+AccountCreateWireframe.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SwitchAccount+AccountCreateWireframe.swift"; sourceTree = ""; }; @@ -4415,6 +4484,7 @@ 86F7A369E31DCB9ABD556EE9 /* CrowdloanListPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CrowdloanListPresenter.swift; sourceTree = ""; }; 87F9D215513308538FA3FDC4 /* ContactsTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ContactsTests.swift; sourceTree = ""; }; 8821119C96944A0E3526E93A /* StakingRedeemViewFactory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StakingRedeemViewFactory.swift; sourceTree = ""; }; + 882D47A501D9D6CCE7B99691 /* LiquidityPoolRemoveLiquidityConfirmProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolRemoveLiquidityConfirmProtocols.swift; sourceTree = ""; }; 885A9E2D3619FEFC5ED0C093 /* WalletChainAccountDashboardWireframe.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WalletChainAccountDashboardWireframe.swift; sourceTree = ""; }; 889A825F58F5CB54118A9D35 /* SelectValidatorsStartWireframe.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SelectValidatorsStartWireframe.swift; sourceTree = ""; }; 890203CBFFCBF517C0BAA396 /* YourValidatorListTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = YourValidatorListTests.swift; sourceTree = ""; }; @@ -4429,9 +4499,11 @@ 8E83833EB33E51A12F96F83B /* WalletChainAccountDashboardPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WalletChainAccountDashboardPresenter.swift; sourceTree = ""; }; 8F04623D6CE10669D914CA2F /* PolkaswapTransaktionSettingsViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PolkaswapTransaktionSettingsViewController.swift; sourceTree = ""; }; 8F0FEFEAEC5CDCD7C9BF77D5 /* PolkaswapSwapConfirmationPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PolkaswapSwapConfirmationPresenter.swift; sourceTree = ""; }; + 8FB7091F743BBACC09553298 /* LiquidityPoolSupplyProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolSupplyProtocols.swift; sourceTree = ""; }; 900E67A76C0702F8123EBB47 /* AddCustomNodeInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AddCustomNodeInteractor.swift; sourceTree = ""; }; 906C55FC079AF6112AF0745B /* YourValidatorListWireframe.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = YourValidatorListWireframe.swift; sourceTree = ""; }; 909ABB38BF714F553063697F /* StakingRebondConfirmationFlow.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StakingRebondConfirmationFlow.swift; sourceTree = ""; }; + 916326B6F6651BBC5913B26F /* LiquidityPoolRemoveLiquidityConfirmViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolRemoveLiquidityConfirmViewController.swift; sourceTree = ""; }; 916347CF697C30CD455F436E /* WalletTransactionDetailsViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WalletTransactionDetailsViewController.swift; sourceTree = ""; }; 91D44421CCD7AD220A05CD0E /* PurchaseInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PurchaseInteractor.swift; sourceTree = ""; }; 9272FED2C00908028F223E5C /* ReferralCrowdloanTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ReferralCrowdloanTests.swift; sourceTree = ""; }; @@ -4455,14 +4527,18 @@ 9A9EBD3B7AEA5EF594DFEB49 /* PolkaswapAdjustmentProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PolkaswapAdjustmentProtocols.swift; sourceTree = ""; }; 9AEA7ECB8434DF494D2B25B9 /* ChainAccountTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ChainAccountTests.swift; sourceTree = ""; }; 9B5626189788682A84D4E9D7 /* SelectValidatorsConfirmPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SelectValidatorsConfirmPresenter.swift; sourceTree = ""; }; + 9BA528679A82B9A327853804 /* LiquidityPoolSupplyInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolSupplyInteractor.swift; sourceTree = ""; }; 9C01DCD4DA014E8FB50B9F11 /* CrowdloanContributionSetupTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CrowdloanContributionSetupTests.swift; sourceTree = ""; }; 9C05A688EA7379572BBCE545 /* SelectMarketRouter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SelectMarketRouter.swift; sourceTree = ""; }; + 9FED48DE9B681995E6E4A581 /* LiquidityPoolDetailsProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolDetailsProtocols.swift; sourceTree = ""; }; A14CA4551FCC2EBD078E2242 /* AccountConfirmViewFactory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AccountConfirmViewFactory.swift; sourceTree = ""; }; A3104ABC4BECF08B0BA836AA /* AccountConfirmViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AccountConfirmViewController.swift; sourceTree = ""; }; A31780E84948D7FE632ECB02 /* YourValidatorListProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = YourValidatorListProtocols.swift; sourceTree = ""; }; A3BACB7E24BC87F9218DBBC4 /* StakingPayoutConfirmationViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StakingPayoutConfirmationViewController.swift; sourceTree = ""; }; A427660DDA1D882327F8FF5C /* AssetNetworksTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AssetNetworksTests.swift; sourceTree = ""; }; + A4900562AFFD45F29F4C5DEF /* LiquidityPoolDetailsViewLayout.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolDetailsViewLayout.swift; sourceTree = ""; }; A6543901A1EE819323DCD95D /* WalletChainAccountDashboardInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WalletChainAccountDashboardInteractor.swift; sourceTree = ""; }; + A692D227372B24F922EFA058 /* LiquidityPoolsOverviewProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolsOverviewProtocols.swift; sourceTree = ""; }; A7219B81CEA13CD60BD8FAFE /* ClaimCrowdloanRewardsProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ClaimCrowdloanRewardsProtocols.swift; sourceTree = ""; }; A77DF1CA9610844CF63C4BBC /* Pods-fearlessAll-fearless.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-fearlessAll-fearless.debug.xcconfig"; path = "Target Support Files/Pods-fearlessAll-fearless/Pods-fearlessAll-fearless.debug.xcconfig"; sourceTree = ""; }; A7AD1285797131E836CD994B /* AssetSelectionWireframe.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AssetSelectionWireframe.swift; sourceTree = ""; }; @@ -4613,6 +4689,7 @@ B264116DA8F64446D46E12DE /* WalletTransactionDetailsProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WalletTransactionDetailsProtocols.swift; sourceTree = ""; }; B2655EE5CFAAD20C0FF59188 /* AssetSelectionTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AssetSelectionTests.swift; sourceTree = ""; }; B29514E516CEAAB159851D95 /* AccountImportProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AccountImportProtocols.swift; sourceTree = ""; }; + B3459F610D6E5C782D8695A9 /* LiquidityPoolRemoveLiquidityConfirmViewLayout.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolRemoveLiquidityConfirmViewLayout.swift; sourceTree = ""; }; B399E7CA0A03A06EFDF1B126 /* PolkaswapTransaktionSettingsPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PolkaswapTransaktionSettingsPresenter.swift; sourceTree = ""; }; B4774F00EDBB28F374797637 /* ClaimCrowdloanRewardsInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ClaimCrowdloanRewardsInteractor.swift; sourceTree = ""; }; B5934BA68F375F5F8237967D /* NetworkInfoViewController.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; path = NetworkInfoViewController.xib; sourceTree = ""; }; @@ -4634,6 +4711,8 @@ C316BE4F5A0342D379F783E8 /* StartSelectValidatorsTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StartSelectValidatorsTests.swift; sourceTree = ""; }; C323602A21644DCB1B2EEFF6 /* Pods_fearlessAll_fearlessIntegrationTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_fearlessAll_fearlessIntegrationTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C503100478AB56E903598A78 /* ReferralCrowdloanPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ReferralCrowdloanPresenter.swift; sourceTree = ""; }; + C52B689ECDB43EB0FEE95553 /* LiquidityPoolRemoveLiquidityTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolRemoveLiquidityTests.swift; sourceTree = ""; }; + C53DFFFB3B5B48DB51692EFA /* LiquidityPoolDetailsInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolDetailsInteractor.swift; sourceTree = ""; }; C554924081754A981EB4243E /* AssetNetworksInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AssetNetworksInteractor.swift; sourceTree = ""; }; C569B746953D3BA947ACEA8D /* ChainSelectionViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ChainSelectionViewController.swift; sourceTree = ""; }; C597BAB74DF23914B68FDC39 /* SwapTransactionDetailAssembly.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SwapTransactionDetailAssembly.swift; sourceTree = ""; }; @@ -4643,8 +4722,7 @@ C603E81028583C2A00007B72 /* StakingMainRelaychainStrategy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StakingMainRelaychainStrategy.swift; sourceTree = ""; }; C61166682B3BFA9000F483C4 /* NftHeaderCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NftHeaderCell.swift; sourceTree = ""; }; C611666B2B3C03B800F483C4 /* NftHeaderCellViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NftHeaderCellViewModel.swift; sourceTree = ""; }; - C615668029309D3900391BF3 /* QRService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QRService.swift; sourceTree = ""; }; - C61566842930A07900391BF3 /* QRCreationOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QRCreationOperation.swift; sourceTree = ""; }; + C61BE0DFC48282DFDBB820C9 /* LiquidityPoolRemoveLiquidityAssembly.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolRemoveLiquidityAssembly.swift; sourceTree = ""; }; C62522E202A1C5EE60D25122 /* NftSendPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NftSendPresenter.swift; sourceTree = ""; }; C6264C282799A56E00FCA0DB /* WalletDetailsTableCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletDetailsTableCell.swift; sourceTree = ""; }; C6264C2B2799C15C00FCA0DB /* WalletDetailsCellViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletDetailsCellViewModel.swift; sourceTree = ""; }; @@ -4701,7 +4779,6 @@ C661B3B327DFBA41005F1F7D /* AccountInfoSubscriptionProviderWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountInfoSubscriptionProviderWrapper.swift; sourceTree = ""; }; C661B3B527E2E7AB005F1F7D /* AccountCreateChainType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountCreateChainType.swift; sourceTree = ""; }; C665E4EF29C35801001946D1 /* TimeFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeFormatter.swift; sourceTree = ""; }; - C66E68CD2BFC119300A14759 /* OnboardingConfigVersionResolver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingConfigVersionResolver.swift; sourceTree = ""; }; C67ACC943DA07FC529AE69B4 /* StakingBalanceFlow.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StakingBalanceFlow.swift; sourceTree = ""; }; C67E780E27B3163B0053346B /* CheckPincodeProtocols.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckPincodeProtocols.swift; sourceTree = ""; }; C67E781027B318840053346B /* CheckPincodeViewFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckPincodeViewFactory.swift; sourceTree = ""; }; @@ -4770,9 +4847,11 @@ D06A0B252CCD6CAE8C5EDC16 /* AddCustomNodeProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AddCustomNodeProtocols.swift; sourceTree = ""; }; D101339CC1292531CC4DB0AC /* StakingUnbondSetupInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StakingUnbondSetupInteractor.swift; sourceTree = ""; }; D39D54DC9992CF9CB6699AA3 /* StakingAmountViewFactory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StakingAmountViewFactory.swift; sourceTree = ""; }; + D430E8B808864B281A62AB43 /* LiquidityPoolSupplyConfirmViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolSupplyConfirmViewController.swift; sourceTree = ""; }; D45B7031E0809CED062C83F8 /* StakingUnbondConfirmPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StakingUnbondConfirmPresenter.swift; sourceTree = ""; }; D482753E0D75C5F5E0617998 /* CreateContactInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CreateContactInteractor.swift; sourceTree = ""; }; D4C391292F22D16427C77CD9 /* SelectValidatorsStartViewFactory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SelectValidatorsStartViewFactory.swift; sourceTree = ""; }; + D5121DA4DDF11ED6A6659CEB /* LiquidityPoolSupplyConfirmRouter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolSupplyConfirmRouter.swift; sourceTree = ""; }; D55EEBFA4A54B3AAF9F52855 /* WarningAlertViewLayout.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WarningAlertViewLayout.swift; sourceTree = ""; }; D5B7937620F4339EE948EC25 /* AddCustomNodePresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AddCustomNodePresenter.swift; sourceTree = ""; }; D613E20E96E7BA5B8F4B9799 /* StakingRewardDetailsInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StakingRewardDetailsInteractor.swift; sourceTree = ""; }; @@ -4793,6 +4872,7 @@ DC265B5F209B038633AE0E3F /* SwapTransactionDetailProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SwapTransactionDetailProtocols.swift; sourceTree = ""; }; DC50F2FF6E8EBC00B56CB86D /* PolkaswapSwapConfirmationRouter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PolkaswapSwapConfirmationRouter.swift; sourceTree = ""; }; DCC952210C0714F32C3AE570 /* CreateContactTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CreateContactTests.swift; sourceTree = ""; }; + DCCD9A6B753FD1510D3DD311 /* LiquidityPoolSupplyConfirmProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolSupplyConfirmProtocols.swift; sourceTree = ""; }; DDCB1F95F35D50950D0A021E /* StakingPoolInfoProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StakingPoolInfoProtocols.swift; sourceTree = ""; }; DEC72ACCA21471C6A9580180 /* WalletMainContainerInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WalletMainContainerInteractor.swift; sourceTree = ""; }; DFBFF377F35B254AB3141100 /* AssetNetworksViewLayout.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AssetNetworksViewLayout.swift; sourceTree = ""; }; @@ -4814,7 +4894,9 @@ EA86DE0B14A20416D3AF1E1E /* Pods-fearlessAll-fearlessIntegrationTests.dev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-fearlessAll-fearlessIntegrationTests.dev.xcconfig"; path = "Target Support Files/Pods-fearlessAll-fearlessIntegrationTests/Pods-fearlessAll-fearlessIntegrationTests.dev.xcconfig"; sourceTree = ""; }; EB8605FD90D8C3553A9897B4 /* AccountImportPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AccountImportPresenter.swift; sourceTree = ""; }; EC012CF1C792B34BD5FF45A2 /* NftDetailsProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NftDetailsProtocols.swift; sourceTree = ""; }; + EC863A9CE29C63B740C6E4D9 /* LiquidityPoolsOverviewAssembly.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolsOverviewAssembly.swift; sourceTree = ""; }; ECBF10B7D4707E4D7D6387CF /* FiltersViewFactory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = FiltersViewFactory.swift; sourceTree = ""; }; + ECE2059F621D024F85EFBFD0 /* LiquidityPoolRemoveLiquidityConfirmAssembly.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolRemoveLiquidityConfirmAssembly.swift; sourceTree = ""; }; ED916AAFB6B5A7FA0C802615 /* Pods-fearlessTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-fearlessTests.debug.xcconfig"; path = "Target Support Files/Pods-fearlessTests/Pods-fearlessTests.debug.xcconfig"; sourceTree = ""; }; EDB9EDB05686DF11958145E1 /* ControllerAccountWireframe.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ControllerAccountWireframe.swift; sourceTree = ""; }; EDDA0B079962E00FAFBE07AD /* ChainSelectionProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ChainSelectionProtocols.swift; sourceTree = ""; }; @@ -4991,11 +5073,14 @@ FA004898282CCFCD0032FF49 /* SelectValidatorsStartParachainViewModelFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectValidatorsStartParachainViewModelFactory.swift; sourceTree = ""; }; FA00489A282CCFDC0032FF49 /* SelectValidatorsStartRelaychainViewModelFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectValidatorsStartRelaychainViewModelFactory.swift; sourceTree = ""; }; FA0066E82935D07D0068FC61 /* RecommendedValidatorListPoolStrategy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecommendedValidatorListPoolStrategy.swift; sourceTree = ""; }; + FA054A992BCD1FA3007B8F6D /* AvailableLiquidityPoolsListPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AvailableLiquidityPoolsListPresenter.swift; sourceTree = ""; }; + FA054A9B2BCD1FAF007B8F6D /* AvailableLiquidityPoolsListViewModelFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AvailableLiquidityPoolsListViewModelFactory.swift; sourceTree = ""; }; FA072C13277AE2FE00731718 /* QRCaptureService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCaptureService.swift; sourceTree = ""; }; - FA072C15277B023D00731718 /* QRExtractionService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRExtractionService.swift; sourceTree = ""; }; FA072C20277B19A900731718 /* ImageGalleryProtocols.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageGalleryProtocols.swift; sourceTree = ""; }; FA072C24277C0FA900731718 /* ApplicationSettingsPresentable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationSettingsPresentable.swift; sourceTree = ""; }; FA08B3642A31A09E00D9D126 /* BigUInt+StringInitializable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BigUInt+StringInitializable.swift"; sourceTree = ""; }; + FA09AD342C37ABA000BE0B9C /* TransactionObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionObserver.swift; sourceTree = ""; }; + FA09AD362C37AF9200BE0B9C /* SubstrateTransactionObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubstrateTransactionObserver.swift; sourceTree = ""; }; FA0B7C9F68A6BF3D3A6D8234 /* StakingPoolInfoInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StakingPoolInfoInteractor.swift; sourceTree = ""; }; FA1109EA27A92D56003C2158 /* ChainAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChainAction.swift; sourceTree = ""; }; FA14AE882B0785670066CADF /* SoraSubsquidHistoryResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoraSubsquidHistoryResponse.swift; sourceTree = ""; }; @@ -5026,6 +5111,26 @@ FA17B4D327E9CF2C006E0735 /* UtilityConstants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UtilityConstants.swift; sourceTree = ""; }; FA1A023B274F51A900DA07CB /* ChainAccountBalanceTableCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChainAccountBalanceTableCell.swift; sourceTree = ""; }; FA1A023D274F55D900DA07CB /* HorizontalKeyValueView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HorizontalKeyValueView.swift; sourceTree = ""; }; + FA1D01EE2BBE713D005B7071 /* LiquidityPoolListCellModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LiquidityPoolListCellModel.swift; sourceTree = ""; }; + FA1D01EF2BBE713D005B7071 /* LiquidityPoolListViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LiquidityPoolListViewModel.swift; sourceTree = ""; }; + FA1D01F02BBE713D005B7071 /* LiquidityPoolsListViewLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LiquidityPoolsListViewLayout.swift; sourceTree = ""; }; + FA1D01F12BBE713D005B7071 /* LiquidityPoolsListRouter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LiquidityPoolsListRouter.swift; sourceTree = ""; }; + FA1D01F22BBE713D005B7071 /* LiquidityPoolsListProtocols.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LiquidityPoolsListProtocols.swift; sourceTree = ""; }; + FA1D01F42BBE713D005B7071 /* LiquidityPoolsListAssembly.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LiquidityPoolsListAssembly.swift; sourceTree = ""; }; + FA1D01F62BBE713D005B7071 /* LiquidityPoolListCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LiquidityPoolListCell.swift; sourceTree = ""; }; + FA1D01F72BBE713D005B7071 /* LiquidityPoolsListViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LiquidityPoolsListViewController.swift; sourceTree = ""; }; + FA1D02032BBE71F2005B7071 /* TokenPairIconsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TokenPairIconsView.swift; sourceTree = ""; }; + FA1D02052BBE71F9005B7071 /* TokenPairsIconViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TokenPairsIconViewModel.swift; sourceTree = ""; }; + FA1D02082BBE74B7005B7071 /* AvailableLiquidityPoolsListInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AvailableLiquidityPoolsListInteractor.swift; sourceTree = ""; }; + FA1D020C2BBE7690005B7071 /* UserLiquidityPoolsListInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserLiquidityPoolsListInteractor.swift; sourceTree = ""; }; + FA1D51D62BCFD445001353E7 /* LiquidityPools+ViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "LiquidityPools+ViewModel.swift"; sourceTree = ""; }; + FA1D51D82BCFE353001353E7 /* SoraFiatService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoraFiatService.swift; sourceTree = ""; }; + FA1D51DB2BCFE38D001353E7 /* SubqueryFiatInfoOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubqueryFiatInfoOperation.swift; sourceTree = ""; }; + FA22228C2BD237910031DE04 /* SubqueryPriceFetcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubqueryPriceFetcher.swift; sourceTree = ""; }; + FA22228E2BD237CF0031DE04 /* SoraSubqueryPriceFetcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoraSubqueryPriceFetcher.swift; sourceTree = ""; }; + FA2222902BD239500031DE04 /* SoraSubqueryPriceResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoraSubqueryPriceResponse.swift; sourceTree = ""; }; + FA2222932BD2726F0031DE04 /* SkeletonLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SkeletonLabel.swift; sourceTree = ""; }; + FA2222952BD272A30031DE04 /* SkeletonLoadableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SkeletonLoadableView.swift; sourceTree = ""; }; FA24FEFD2B95C32200CD9E04 /* Decimal+DoubleValue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Decimal+DoubleValue.swift"; sourceTree = ""; }; FA256982274CE5A400875A53 /* BalanceLockType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BalanceLockType.swift; sourceTree = ""; }; FA256983274CE5A500875A53 /* BalanceLocks+Sort.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "BalanceLocks+Sort.swift"; sourceTree = ""; }; @@ -5279,12 +5384,12 @@ FA3F5B6A281BAF6600BEF03B /* StakingAmountParachainViewModelState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StakingAmountParachainViewModelState.swift; sourceTree = ""; }; FA402F2E27C7C646008CF986 /* ExportAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExportAction.swift; sourceTree = ""; }; FA44284129D44E51000142EB /* ChainStakingSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChainStakingSettings.swift; sourceTree = ""; }; + FA4441332BF75FD90067C633 /* LiquidityPoolListType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiquidityPoolListType.swift; sourceTree = ""; }; FA46D2C6283DDD07005A112B /* ParachainStakingCandidateMetadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParachainStakingCandidateMetadata.swift; sourceTree = ""; }; FA4889662B7F5E360092ABF8 /* GiantsquidExtrinsic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GiantsquidExtrinsic.swift; sourceTree = ""; }; FA4B928E284493C60003BCEF /* DelegateCall.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DelegateCall.swift; sourceTree = ""; }; FA4B92902844CF750003BCEF /* MetaAccountModelChangedEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MetaAccountModelChangedEvent.swift; sourceTree = ""; }; FA4B92922844D0060003BCEF /* Currency.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Currency.swift; sourceTree = ""; }; - FA4B92942844D0100003BCEF /* UIImageView+Shimmered.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImageView+Shimmered.swift"; sourceTree = ""; }; FA4B92952844D0100003BCEF /* ShimmeredLabel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShimmeredLabel.swift; sourceTree = ""; }; FA4B92962844D0100003BCEF /* ShimmeredProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShimmeredProtocol.swift; sourceTree = ""; }; FA4B929A2844D0470003BCEF /* WalletDetailsTableHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletDetailsTableHeaderView.swift; sourceTree = ""; }; @@ -5304,6 +5409,8 @@ FA4C3D112886794D00176398 /* SelfSizingTableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelfSizingTableView.swift; sourceTree = ""; }; FA4CC6632817C3AC00A7E85F /* StackedTableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StackedTableView.swift; sourceTree = ""; }; FA4CC665281801CB00A7E85F /* StakingUnitInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StakingUnitInfoView.swift; sourceTree = ""; }; + FA5085AA2C33C6D4002DF97D /* SafeArray.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SafeArray.swift; sourceTree = ""; }; + FA5085AB2C33C6D4002DF97D /* SafeDictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SafeDictionary.swift; sourceTree = ""; }; FA5137A129AC6F2F00560EBA /* PolkaswapDisclaimerViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PolkaswapDisclaimerViewModel.swift; sourceTree = ""; }; FA5137A229AC6F2F00560EBA /* PolkaswapDisclaimerRouter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PolkaswapDisclaimerRouter.swift; sourceTree = ""; }; FA5137A329AC6F2F00560EBA /* PolkaswapDisclaimerViewLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PolkaswapDisclaimerViewLayout.swift; sourceTree = ""; }; @@ -5317,6 +5424,8 @@ FA5137B529AC76EB00560EBA /* GiantsquidHistoryOperationFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GiantsquidHistoryOperationFactory.swift; sourceTree = ""; }; FA5137B629AC76EB00560EBA /* SubsquidHistoryOperationFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SubsquidHistoryOperationFactory.swift; sourceTree = ""; }; FA5137B729AC76EB00560EBA /* HistoryOperationFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HistoryOperationFactory.swift; sourceTree = ""; }; + FA53D88F2C084ECA00173ADB /* LiquidityPoolSupplyViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiquidityPoolSupplyViewModel.swift; sourceTree = ""; }; + FA53D8912C08510000173ADB /* LiquidityPoolSupplyViewModelFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiquidityPoolSupplyViewModelFactory.swift; sourceTree = ""; }; FA584C772AB2BCD500F6F020 /* UniversalMediaView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UniversalMediaView.swift; sourceTree = ""; }; FA584C792AB2BFE300F6F020 /* MediaType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaType.swift; sourceTree = ""; }; FA584C7B2AB3071E00F6F020 /* AlchemyNFTOperationFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlchemyNFTOperationFactory.swift; sourceTree = ""; }; @@ -5415,6 +5524,8 @@ FA6DB7C02757C9AF00233FBA /* ChainAccountPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChainAccountPresenter.swift; sourceTree = ""; }; FA6DB7C12757C9AF00233FBA /* ChainAccountInteractor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChainAccountInteractor.swift; sourceTree = ""; }; FA6DB7C22757C9AF00233FBA /* ChainAccountProtocols.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChainAccountProtocols.swift; sourceTree = ""; }; + FA6ECE732BF49C0C00481B2B /* LiquidityPoolDetailsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiquidityPoolDetailsViewModel.swift; sourceTree = ""; }; + FA6ECE752BF49D3D00481B2B /* LiquidityPoolDetailsViewModelFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiquidityPoolDetailsViewModelFactory.swift; sourceTree = ""; }; FA6FC016067C632AF256EB62 /* PolkaswapSwapConfirmationProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PolkaswapSwapConfirmationProtocols.swift; sourceTree = ""; }; FA7154C3286B0C7D00100672 /* SelectValidatorsStartTextsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectValidatorsStartTextsViewModel.swift; sourceTree = ""; }; FA7253F32AC2E48400EC47A6 /* CryptoProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CryptoProvider.swift; sourceTree = ""; }; @@ -5453,7 +5564,6 @@ FA72541D2AC2E48400EC47A6 /* WalletConnectService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletConnectService.swift; sourceTree = ""; }; FA72541E2AC2E48400EC47A6 /* WalletConnectSocketFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletConnectSocketFactory.swift; sourceTree = ""; }; FA72541F2AC2E48500EC47A6 /* WalletConnectPayloadFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletConnectPayloadFactory.swift; sourceTree = ""; }; - FA7254462AC2E4AB00EC47A6 /* QRUriMatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QRUriMatcher.swift; sourceTree = ""; }; FA7336BD2A0E3B7F0096A291 /* NetworkClientFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkClientFactory.swift; sourceTree = ""; }; FA7336BE2A0E3B7F0096A291 /* RequestConfiguratorFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestConfiguratorFactory.swift; sourceTree = ""; }; FA7336BF2A0E3B7F0096A291 /* RequestSignerFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestSignerFactory.swift; sourceTree = ""; }; @@ -5531,6 +5641,11 @@ FA8800672B31A335000AE5EB /* StakingAccountSubscriptionV13.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StakingAccountSubscriptionV13.swift; sourceTree = ""; }; FA8800692B31A33E000AE5EB /* StakingAccountSubscriptionV14.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StakingAccountSubscriptionV14.swift; sourceTree = ""; }; FA88006B2B31A46D000AE5EB /* StakingAccountSubscriptionAssembly.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StakingAccountSubscriptionAssembly.swift; sourceTree = ""; }; + FA8810D22BDCCF7E0084CC4B /* UserLiquidityPoolsListPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserLiquidityPoolsListPresenter.swift; sourceTree = ""; }; + FA8810D42BDCD19D0084CC4B /* UserLiquidityPoolsListViewModelFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserLiquidityPoolsListViewModelFactory.swift; sourceTree = ""; }; + FA887A442C107A1100CA720F /* LiquidityPoolSupplyConfirmViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiquidityPoolSupplyConfirmViewModel.swift; sourceTree = ""; }; + FA887A462C107A4300CA720F /* LiquidityPoolSupplyConfirmViewModelFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiquidityPoolSupplyConfirmViewModelFactory.swift; sourceTree = ""; }; + FA887A482C1C19DB00CA720F /* WarningView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WarningView.swift; sourceTree = ""; }; FA8C34B051607218638BA851 /* FiltersProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = FiltersProtocols.swift; sourceTree = ""; }; FA8ED43228FD960F00EBB712 /* YourValidatorListFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YourValidatorListFlow.swift; sourceTree = ""; }; FA8ED43528FD983A00EBB712 /* YourValidatorListRelaychainStrategy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YourValidatorListRelaychainStrategy.swift; sourceTree = ""; }; @@ -5601,9 +5716,9 @@ FA93A312283653B70021330F /* ValidatorListFilterFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValidatorListFilterFlow.swift; sourceTree = ""; }; FA93A3152836542D0021330F /* ValidatorListFilterRelaychainViewModelState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValidatorListFilterRelaychainViewModelState.swift; sourceTree = ""; }; FA93A3172836543B0021330F /* ValidatorListFilterRelaychainViewModelFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValidatorListFilterRelaychainViewModelFactory.swift; sourceTree = ""; }; + FA96101F2C5205B200C3C750 /* UIViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIViewController.swift; sourceTree = ""; }; FA97E68A2A0281230035F5D7 /* GiantsquidRewardOperationFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GiantsquidRewardOperationFactory.swift; sourceTree = ""; }; FA99422727FE925000D771E5 /* UISwitch+CustomSize.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UISwitch+CustomSize.swift"; sourceTree = ""; }; - FA99422927FE927700D771E5 /* AssetModelMapper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetModelMapper.swift; sourceTree = ""; }; FA99422C28002BB800D771E5 /* MissingAccountOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MissingAccountOptions.swift; sourceTree = ""; }; FA99423428053C5000D771E5 /* ChainAccountInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChainAccountInfo.swift; sourceTree = ""; }; FA99423628053C6800D771E5 /* IconWithTitleViewModelFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IconWithTitleViewModelFactory.swift; sourceTree = ""; }; @@ -5755,7 +5870,6 @@ FAAA29472B8DCF350089AFE6 /* AsyncStorageRequestFactory+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AsyncStorageRequestFactory+Extension.swift"; sourceTree = ""; }; FAAA29482B8DCF350089AFE6 /* AsyncStorageRequestFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AsyncStorageRequestFactory.swift; sourceTree = ""; }; FAAA29562B8DED770089AFE6 /* MapKeyType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapKeyType.swift; sourceTree = ""; }; - FAAB998C27A7C79D00CD1A3B /* QRParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRParser.swift; sourceTree = ""; }; FAABC46D2845BADA002CF40E /* CustomValidatorParachainListFilter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomValidatorParachainListFilter.swift; sourceTree = ""; }; FAABC46F2845BAEE002CF40E /* CustomValidatorParachainListComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomValidatorParachainListComposer.swift; sourceTree = ""; }; FAABC4722845C7F4002CF40E /* ValidatorListFilterParachainViewModelState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValidatorListFilterParachainViewModelState.swift; sourceTree = ""; }; @@ -5784,8 +5898,7 @@ FAADC1B32926597400DA9903 /* ScanQRPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScanQRPresenter.swift; sourceTree = ""; }; FAADC1B42926597400DA9903 /* ScanQRProtocols.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScanQRProtocols.swift; sourceTree = ""; }; FAADC1B52926597400DA9903 /* ScanQRRouter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScanQRRouter.swift; sourceTree = ""; }; - FAADC1BF29265A7900DA9903 /* QRInfoMatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QRInfoMatcher.swift; sourceTree = ""; }; - FAADC1C529265C9600DA9903 /* QRCoderFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QRCoderFactory.swift; sourceTree = ""; }; + FAADF71129C47D10002B6D39 /* RuntimeSpecVersion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuntimeSpecVersion.swift; sourceTree = ""; }; FAAF61732877DBC50094B4BC /* EthereumIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EthereumIcon.swift; sourceTree = ""; }; FAAF946B2A0CFF90009A4BA5 /* Array+Duplicates.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array+Duplicates.swift"; sourceTree = ""; }; FAB0EDD827AA692D003D93C2 /* NodeSelectionTableCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeSelectionTableCell.swift; sourceTree = ""; }; @@ -5895,15 +6008,45 @@ FACD42BB2A5BE91D009975AA /* PortionRewardCalculatorService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PortionRewardCalculatorService.swift; sourceTree = ""; }; FACD42BE2A5BE93D009975AA /* polkadot-9370metadata */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "polkadot-9370metadata"; sourceTree = ""; }; FACD42C02A5C10BB009975AA /* TransferService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransferService.swift; sourceTree = ""; }; - FACE6C5E2BBAC3B000643CEF /* SubstrateDataModel.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = SubstrateDataModel.xcdatamodel; sourceTree = ""; }; - FACE6C5F2BBAC3B000643CEF /* SubstrateDataModel_v4.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = SubstrateDataModel_v4.xcdatamodel; sourceTree = ""; }; - FACE6C602BBAC3B000643CEF /* SubstrateDataModel_v2.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = SubstrateDataModel_v2.xcdatamodel; sourceTree = ""; }; - FACE6C612BBAC3B000643CEF /* SubstrateDataModel_v5.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = SubstrateDataModel_v5.xcdatamodel; sourceTree = ""; }; - FACE6C622BBAC3B000643CEF /* SubstrateDataModel_v3.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = SubstrateDataModel_v3.xcdatamodel; sourceTree = ""; }; FAD0067E27EA252400C97E09 /* AboutViewModelFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AboutViewModelFactory.swift; sourceTree = ""; }; FAD0067F27EA252400C97E09 /* AboutViewState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AboutViewState.swift; sourceTree = ""; }; FAD0068227EA255900C97E09 /* AboutTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AboutTableViewCell.swift; sourceTree = ""; }; FAD0068327EA255900C97E09 /* AboutViewLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AboutViewLayout.swift; sourceTree = ""; }; + FAD0678E2C2042F30050291F /* Requests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Requests.swift; sourceTree = ""; }; + FAD0678F2C2042F30050291F /* AccountInfoRemoteService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountInfoRemoteService.swift; sourceTree = ""; }; + FAD067952C2043DC0050291F /* UIImage+Monochrome.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+Monochrome.swift"; sourceTree = ""; }; + FAD067972C2043FC0050291F /* WalletAssetsObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletAssetsObserver.swift; sourceTree = ""; }; + FAD067982C2043FC0050291F /* ChainConnectionVisibilityHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChainConnectionVisibilityHelper.swift; sourceTree = ""; }; + FAD0679B2C2044170050291F /* ExternalApiExplorerType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExternalApiExplorerType.swift; sourceTree = ""; }; + FAD0679D2C2044320050291F /* AssetManagementMigrator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetManagementMigrator.swift; sourceTree = ""; }; + FAD067A02C2044490050291F /* SubstrateDataModel.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = SubstrateDataModel.xcdatamodel; sourceTree = ""; }; + FAD067A12C2044490050291F /* SubstrateDataModel_v4.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = SubstrateDataModel_v4.xcdatamodel; sourceTree = ""; }; + FAD067A22C2044490050291F /* SubstrateDataModel_v2.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = SubstrateDataModel_v2.xcdatamodel; sourceTree = ""; }; + FAD067A32C2044490050291F /* SubstrateDataModel_v7.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = SubstrateDataModel_v7.xcdatamodel; sourceTree = ""; }; + FAD067A42C2044490050291F /* SubstrateDataModel_v5.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = SubstrateDataModel_v5.xcdatamodel; sourceTree = ""; }; + FAD067A52C2044490050291F /* SubstrateDataModel_v6.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = SubstrateDataModel_v6.xcdatamodel; sourceTree = ""; }; + FAD067A62C2044490050291F /* SubstrateDataModel_v3.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = SubstrateDataModel_v3.xcdatamodel; sourceTree = ""; }; + FAD067A82C20445F0050291F /* ChainAssetListBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChainAssetListBuilder.swift; sourceTree = ""; }; + FAD067AB2C2044810050291F /* ErasStakersPagedKey.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ErasStakersPagedKey.swift; sourceTree = ""; }; + FAD067AC2C2044810050291F /* ErasStakersOverviewKey.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ErasStakersOverviewKey.swift; sourceTree = ""; }; + FAD067B12C2044B10050291F /* AssetManagementViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetManagementViewModel.swift; sourceTree = ""; }; + FAD067B22C2044B10050291F /* AssetManagementViewModelFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetManagementViewModelFactory.swift; sourceTree = ""; }; + FAD067B32C2044B10050291F /* AssetManagementInteractor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetManagementInteractor.swift; sourceTree = ""; }; + FAD067B42C2044B10050291F /* AssetManagementAssembly.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetManagementAssembly.swift; sourceTree = ""; }; + FAD067B52C2044B10050291F /* AssetManagementRouter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetManagementRouter.swift; sourceTree = ""; }; + FAD067B62C2044B10050291F /* AssetManagementPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetManagementPresenter.swift; sourceTree = ""; }; + FAD067B72C2044B10050291F /* AssetManagementViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetManagementViewController.swift; sourceTree = ""; }; + FAD067B92C2044B10050291F /* AssetManagementTableCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetManagementTableCell.swift; sourceTree = ""; }; + FAD067BA2C2044B10050291F /* AssetManagementTableHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetManagementTableHeaderView.swift; sourceTree = ""; }; + FAD067BB2C2044B10050291F /* AssetManagementProtocols.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetManagementProtocols.swift; sourceTree = ""; }; + FAD067BC2C2044B10050291F /* AssetManagementViewLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetManagementViewLayout.swift; sourceTree = ""; }; + FAD067C82C2044D30050291F /* ChainAssetListViewLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChainAssetListViewLayout.swift; sourceTree = ""; }; + FAD067CA2C2044F00050291F /* OnboardingConfigVersionResolver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnboardingConfigVersionResolver.swift; sourceTree = ""; }; + FAD067CC2C20453E0050291F /* EraStakersFetching.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EraStakersFetching.swift; sourceTree = ""; }; + FAD067CD2C20453E0050291F /* LegacyEraStakersFetching.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LegacyEraStakersFetching.swift; sourceTree = ""; }; + FAD067CE2C20453E0050291F /* DefaultEraStakersFetching.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultEraStakersFetching.swift; sourceTree = ""; }; + FAD067D22C20550B0050291F /* UIImageView+Shimmered.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImageView+Shimmered.swift"; sourceTree = ""; }; + FAD067D42C214E7C0050291F /* LiquidityPoolsConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiquidityPoolsConstants.swift; sourceTree = ""; }; FAD428932A834A8E001D6A16 /* TopViewControllerHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopViewControllerHelper.swift; sourceTree = ""; }; FAD428952A834BA8001D6A16 /* UIApplication+TopViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIApplication+TopViewController.swift"; sourceTree = ""; }; FAD428972A860C9B001D6A16 /* EthereumNodeFetching.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EthereumNodeFetching.swift; sourceTree = ""; }; @@ -6076,7 +6219,6 @@ FAFFAE4D29AC84B10074AF1F /* KmmCallCodingPath.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KmmCallCodingPath.swift; sourceTree = ""; }; FAFFAE4F29AC84B10074AF1F /* SubqueryPageInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SubqueryPageInfo.swift; sourceTree = ""; }; FAFFAE5029AC84B10074AF1F /* SubqueryDelegatorHistoryData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SubqueryDelegatorHistoryData.swift; sourceTree = ""; }; - FAFFAE5129AC84B10074AF1F /* GraphQLResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GraphQLResponse.swift; sourceTree = ""; }; FAFFAE5229AC84B10074AF1F /* SubqueryTransfer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SubqueryTransfer.swift; sourceTree = ""; }; FAFFAE5329AC84B10074AF1F /* SubqueryDelegatorHistoryElement.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SubqueryDelegatorHistoryElement.swift; sourceTree = ""; }; FAFFAE5429AC84B10074AF1F /* SubqueryDelegatorHistoryItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SubqueryDelegatorHistoryItem.swift; sourceTree = ""; }; @@ -6112,14 +6254,16 @@ FAFFAEA029AC84D30074AF1F /* HexColorConverter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HexColorConverter.swift; sourceTree = ""; }; FAFFAEA329AC850A0074AF1F /* TimeInterval+Debounce.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "TimeInterval+Debounce.swift"; sourceTree = ""; }; FAFFAEA529AC851A0074AF1F /* Bool + Inverted.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Bool + Inverted.swift"; sourceTree = ""; }; - FAFFAEA729AC85230074AF1F /* ZeroBalancesSettingChanged.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ZeroBalancesSettingChanged.swift; sourceTree = ""; }; FAFFAEA929AC90E50074AF1F /* SubsquidPayoutValidatorsForNominatorFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SubsquidPayoutValidatorsForNominatorFactory.swift; sourceTree = ""; }; FAFFAEAA29AC90E50074AF1F /* SubqueryPayoutValidatorsForNominatorFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SubqueryPayoutValidatorsForNominatorFactory.swift; sourceTree = ""; }; FB19F24CAA892FE8B5FE1520 /* NftCollectionViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NftCollectionViewController.swift; sourceTree = ""; }; FBAA28C551344F1457D76DD5 /* ClaimCrowdloanRewardsAssembly.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ClaimCrowdloanRewardsAssembly.swift; sourceTree = ""; }; FBFDF844248CD43AAD13139F /* StakingPayoutConfirmationInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StakingPayoutConfirmationInteractor.swift; sourceTree = ""; }; + FC0B2D0A77F4B0F7CC9E7C1D /* LiquidityPoolsOverviewViewLayout.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolsOverviewViewLayout.swift; sourceTree = ""; }; FC1236F31289F7F25A25E69C /* ClaimCrowdloanRewardsRouter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ClaimCrowdloanRewardsRouter.swift; sourceTree = ""; }; + FC76E7D99A98423180BC572F /* LiquidityPoolsOverviewTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolsOverviewTests.swift; sourceTree = ""; }; FD845193EDFC3A1D0BC73719 /* NftCollectionProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NftCollectionProtocols.swift; sourceTree = ""; }; + FD8B69E9E18C11EAEC9284B3 /* LiquidityPoolsOverviewViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiquidityPoolsOverviewViewController.swift; sourceTree = ""; }; FE4AF0849E32E5B9C72E2ABB /* RecommendedValidatorListViewFactory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = RecommendedValidatorListViewFactory.swift; sourceTree = ""; }; FE826F356F6D72EACFB0AE31 /* NftSendConfirmPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NftSendConfirmPresenter.swift; sourceTree = ""; }; FF4688AF0658F8BB7A90C2BE /* ExportMnemonicConfirmViewFactory.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ExportMnemonicConfirmViewFactory.swift; sourceTree = ""; }; @@ -6141,46 +6285,45 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - FA53D8D12C096F1100173ADB /* keccak in Frameworks */, - FA53D8CD2C096F1100173ADB /* SSFXCM in Frameworks */, - FA53D8BB2C096F1100173ADB /* SSFPools in Frameworks */, - FA53D8A52C096F1100173ADB /* SSFChainRegistry in Frameworks */, + FA8810B62BDCAF260084CC4B /* SSFNetwork in Frameworks */, FA72546F2AC2F12D00EC47A6 /* Web3Wallet in Frameworks */, - 07F44F072BE4C7FF00570143 /* Web3PromiseKit in Frameworks */, - FA53D8B12C096F1100173ADB /* SSFKeyPair in Frameworks */, - FA53D89F2C096F1100173ADB /* SSFAccountManagmentStorage in Frameworks */, - FA53D8B52C096F1100173ADB /* SSFModels in Frameworks */, - FA53D8CF2C096F1100173ADB /* SoraKeystore in Frameworks */, + FA8810B02BDCAF260084CC4B /* SSFKeyPair in Frameworks */, + FA8810AE2BDCAF260084CC4B /* SSFHelpers in Frameworks */, + FA8810A22BDCAF260084CC4B /* SSFChainConnection in Frameworks */, + FA8810A02BDCAF260084CC4B /* SSFAssetManagment in Frameworks */, + FA88109A2BDCAF260084CC4B /* RobinHood in Frameworks */, + FA8810C82BDCAF260084CC4B /* SSFTransferService in Frameworks */, FA72546B2AC2F12D00EC47A6 /* WalletConnectNetworking in Frameworks */, - 07F44F032BE4C7FF00570143 /* Web3 in Frameworks */, - FA53D8BD2C096F1100173ADB /* SSFPoolsStorage in Frameworks */, - FA53D8A12C096F1100173ADB /* SSFAssetManagment in Frameworks */, - FA53D89D2C096F1100173ADB /* SSFAccountManagment in Frameworks */, - FA53D8C12C096F1100173ADB /* SSFRuntimeCodingService in Frameworks */, + FA8810CA2BDCAF260084CC4B /* SSFUtils in Frameworks */, FA8FD1882AF4BEDD00354482 /* Swime in Frameworks */, + FA8810BA2BDCAF260084CC4B /* SSFPools in Frameworks */, + FA8810A42BDCAF260084CC4B /* SSFChainRegistry in Frameworks */, + FA8FD1832AF4B55100354482 /* Web3ContractABI in Frameworks */, + FA8810B82BDCAF260084CC4B /* SSFPolkaswap in Frameworks */, + FA8FD1812AF4B55100354482 /* Web3 in Frameworks */, + FA8810BE2BDCAF260084CC4B /* SSFQRService in Frameworks */, + FA8810CE2BDCAF260084CC4B /* SoraKeystore in Frameworks */, + FA88109E2BDCAF260084CC4B /* SSFAccountManagmentStorage in Frameworks */, + FA8810AC2BDCAF260084CC4B /* SSFExtrinsicKit in Frameworks */, + FA88109C2BDCAF260084CC4B /* SSFAccountManagment in Frameworks */, + FA8810A62BDCAF260084CC4B /* SSFCloudStorage in Frameworks */, + FA8810A82BDCAF260084CC4B /* SSFCrypto in Frameworks */, + FA8810C42BDCAF260084CC4B /* SSFSingleValueCache in Frameworks */, + FA8810AA2BDCAF260084CC4B /* SSFEraKit in Frameworks */, + FA8FD1852AF4B55100354482 /* Web3PromiseKit in Frameworks */, + FA8810D02BDCAF260084CC4B /* keccak in Frameworks */, + FA8810C62BDCAF260084CC4B /* SSFStorageQueryKit in Frameworks */, + FA8810B42BDCAF260084CC4B /* SSFModels in Frameworks */, FA7254672AC2F12D00EC47A6 /* WalletConnect in Frameworks */, - FA53D8992C096F1100173ADB /* MPQRCoreSDK in Frameworks */, - FA53D8C72C096F1100173ADB /* SSFStorageQueryKit in Frameworks */, FA72546D2AC2F12D00EC47A6 /* WalletConnectPairing in Frameworks */, - FA53D8BF2C096F1100173ADB /* SSFQRService in Frameworks */, - FA53D8C52C096F1100173ADB /* SSFSingleValueCache in Frameworks */, - FA53D8A32C096F1100173ADB /* SSFChainConnection in Frameworks */, - FA53D8B32C096F1100173ADB /* SSFLogger in Frameworks */, - FA53D8B72C096F1100173ADB /* SSFNetwork in Frameworks */, - FA53D8C32C096F1100173ADB /* SSFSigner in Frameworks */, - FA53D8C92C096F1100173ADB /* SSFTransferService in Frameworks */, - FA53D89B2C096F1100173ADB /* RobinHood in Frameworks */, - FA53D8B92C096F1100173ADB /* SSFPolkaswap in Frameworks */, - FA53D8A92C096F1100173ADB /* SSFCrypto in Frameworks */, FA7254692AC2F12D00EC47A6 /* WalletConnectAuth in Frameworks */, - FA53D8AD2C096F1100173ADB /* SSFExtrinsicKit in Frameworks */, - 07F44F052BE4C7FF00570143 /* Web3ContractABI in Frameworks */, - FA53D8CB2C096F1100173ADB /* SSFUtils in Frameworks */, - FA53D8972C096F1100173ADB /* IrohaCrypto in Frameworks */, - FA53D8AF2C096F1100173ADB /* SSFHelpers in Frameworks */, - FA53D8AB2C096F1100173ADB /* SSFEraKit in Frameworks */, + FA8810C02BDCAF260084CC4B /* SSFRuntimeCodingService in Frameworks */, + FA8810BC2BDCAF260084CC4B /* SSFPoolsStorage in Frameworks */, + FA8810B22BDCAF260084CC4B /* SSFLogger in Frameworks */, + FA8810C22BDCAF260084CC4B /* SSFSigner in Frameworks */, + FA8810982BDCAF260084CC4B /* IrohaCrypto in Frameworks */, + FA8810CC2BDCAF260084CC4B /* SSFXCM in Frameworks */, C5AFED6C37C2C29E9903D136 /* Pods_fearlessAll_fearless.framework in Frameworks */, - FA53D8A72C096F1100173ADB /* SSFCloudStorage in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -6226,6 +6369,14 @@ path = StakingUnbondSetup; sourceTree = ""; }; + 04265CAB3B55A71F49337293 /* LiquidityPoolSupply */ = { + isa = PBXGroup; + children = ( + 84C4CAC8978B0848DF5FD6FE /* LiquidityPoolSupplyTests.swift */, + ); + path = LiquidityPoolSupply; + sourceTree = ""; + }; 046ABDDCA893D13536190B6C /* NftCollection */ = { isa = PBXGroup; children = ( @@ -6330,40 +6481,6 @@ path = YourValidatorList; sourceTree = ""; }; - 070179632BCA3D4F00908C83 /* AssetManagement */ = { - isa = PBXGroup; - children = ( - 070179642BCA3D4F00908C83 /* ViewModel */, - 070179672BCA3D4F00908C83 /* AssetManagementInteractor.swift */, - 070179682BCA3D4F00908C83 /* AssetManagementAssembly.swift */, - 070179692BCA3D4F00908C83 /* AssetManagementRouter.swift */, - 0701796A2BCA3D4F00908C83 /* AssetManagementPresenter.swift */, - 0701796B2BCA3D4F00908C83 /* AssetManagementViewController.swift */, - 0701796C2BCA3D4F00908C83 /* TableViews */, - 0701796F2BCA3D4F00908C83 /* AssetManagementProtocols.swift */, - 070179702BCA3D4F00908C83 /* AssetManagementViewLayout.swift */, - ); - path = AssetManagement; - sourceTree = ""; - }; - 070179642BCA3D4F00908C83 /* ViewModel */ = { - isa = PBXGroup; - children = ( - 070179652BCA3D4F00908C83 /* AssetManagementViewModel.swift */, - 070179662BCA3D4F00908C83 /* AssetManagementViewModelFactory.swift */, - ); - path = ViewModel; - sourceTree = ""; - }; - 0701796C2BCA3D4F00908C83 /* TableViews */ = { - isa = PBXGroup; - children = ( - 0701796D2BCA3D4F00908C83 /* AssetManagementTableCell.swift */, - 0701796E2BCA3D4F00908C83 /* AssetManagementTableHeaderView.swift */, - ); - path = TableViews; - sourceTree = ""; - }; 0702B3162970182B003519F5 /* Amount */ = { isa = PBXGroup; children = ( @@ -6407,26 +6524,6 @@ path = SelectNetwork; sourceTree = ""; }; - 070CDD6E2ACACEBC00F3F20A /* Matchers */ = { - isa = PBXGroup; - children = ( - 070CDD6F2ACACEDA00F3F20A /* QRMatcherProtocol.swift */, - FAADC1BF29265A7900DA9903 /* QRInfoMatcher.swift */, - FA7254462AC2E4AB00EC47A6 /* QRUriMatcher.swift */, - ); - path = Matchers; - sourceTree = ""; - }; - 070CDD732ACAE02400F3F20A /* QRInfos */ = { - isa = PBXGroup; - children = ( - 070CDD782ACBE19000F3F20A /* BokoloCashQRInfo.swift */, - 070CDD742ACAE04100F3F20A /* SoraQRInfo.swift */, - 070CDD762ACAE05D00F3F20A /* CexQRInfo.swift */, - ); - name = QRInfos; - sourceTree = ""; - }; 070CDD7A2ACBE59700F3F20A /* ReceiveAndRequestAsset */ = { isa = PBXGroup; children = ( @@ -6511,15 +6608,6 @@ path = Swipable; sourceTree = ""; }; - 0739FD312BFB4B98009ADD7C /* Keys */ = { - isa = PBXGroup; - children = ( - 0739FD2F2BFB4B98009ADD7C /* ErasStakersOverviewKey.swift */, - 0739FD302BFB4B98009ADD7C /* ErasStakersPagedKey.swift */, - ); - path = Keys; - sourceTree = ""; - }; 073B34BD2AE91FC600DC5106 /* Validators */ = { isa = PBXGroup; children = ( @@ -6528,24 +6616,6 @@ name = Validators; sourceTree = ""; }; - 074D83342BCA84A900AD1336 /* AccountInfoRemoteService */ = { - isa = PBXGroup; - children = ( - 074D83392BCAAE5800AD1336 /* Requests */, - 074D83372BCA946200AD1336 /* AccountInfoRemoteService.swift */, - ); - name = AccountInfoRemoteService; - path = RemoteSubscription; - sourceTree = ""; - }; - 074D83392BCAAE5800AD1336 /* Requests */ = { - isa = PBXGroup; - children = ( - 074D833A2BCAAE7C00AD1336 /* Requests.swift */, - ); - name = Requests; - sourceTree = ""; - }; 074EB7AB290B9F02000A2A6A /* Events */ = { isa = PBXGroup; children = ( @@ -7200,6 +7270,13 @@ path = Pods; sourceTree = ""; }; + 26F53332B25039CD43301CAF /* AccountManagement */ = { + isa = PBXGroup; + children = ( + ); + path = AccountManagement; + sourceTree = ""; + }; 28CCC9C191E2305B65727756 /* NodeSelection */ = { isa = PBXGroup; children = ( @@ -7272,6 +7349,21 @@ path = WalletOption; sourceTree = ""; }; + 3362664DE1DD71BB75722C2D /* LiquidityPoolSupplyConfirm */ = { + isa = PBXGroup; + children = ( + FA887A432C107A0200CA720F /* ViewModel */, + DCCD9A6B753FD1510D3DD311 /* LiquidityPoolSupplyConfirmProtocols.swift */, + D5121DA4DDF11ED6A6659CEB /* LiquidityPoolSupplyConfirmRouter.swift */, + 06F6B892F62579DE761073CA /* LiquidityPoolSupplyConfirmPresenter.swift */, + 4594686D10DBB7627B8C9A12 /* LiquidityPoolSupplyConfirmInteractor.swift */, + D430E8B808864B281A62AB43 /* LiquidityPoolSupplyConfirmViewController.swift */, + 641B699003FF648A380F7FA6 /* LiquidityPoolSupplyConfirmViewLayout.swift */, + 112609AE5629962646248BF0 /* LiquidityPoolSupplyConfirmAssembly.swift */, + ); + path = LiquidityPoolSupplyConfirm; + sourceTree = ""; + }; 3722354DA3C59896C49B5794 /* StakingRewardDetails */ = { isa = PBXGroup; children = ( @@ -7379,6 +7471,30 @@ path = NftCollection; sourceTree = ""; }; + 478C62A42D572C8647512722 /* LiquidityPoolDetails */ = { + isa = PBXGroup; + children = ( + FA6ECE722BF49BE300481B2B /* ViewModel */, + 9FED48DE9B681995E6E4A581 /* LiquidityPoolDetailsProtocols.swift */, + 28E3B4BA1160B87C435C2AAF /* LiquidityPoolDetailsRouter.swift */, + 81E9DD6EB14A352635BAC711 /* LiquidityPoolDetailsPresenter.swift */, + C53DFFFB3B5B48DB51692EFA /* LiquidityPoolDetailsInteractor.swift */, + 67BDE520860A67C800E7F4AB /* LiquidityPoolDetailsViewController.swift */, + A4900562AFFD45F29F4C5DEF /* LiquidityPoolDetailsViewLayout.swift */, + 84452F6F25D5E2B300F47EC5 /* Resources */, + 5F6F7AE5AFF3F2E7BADA02BB /* LiquidityPoolDetailsAssembly.swift */, + ); + path = LiquidityPoolDetails; + sourceTree = ""; + }; + 48EAF80DCC0C537917FC5A23 /* LiquidityPoolRemoveLiquidity */ = { + isa = PBXGroup; + children = ( + C52B689ECDB43EB0FEE95553 /* LiquidityPoolRemoveLiquidityTests.swift */, + ); + path = LiquidityPoolRemoveLiquidity; + sourceTree = ""; + }; 493D529207797CDC4F179A5C /* NftSend */ = { isa = PBXGroup; children = ( @@ -7574,6 +7690,20 @@ path = CustomValidators; sourceTree = ""; }; + 675669EAE3DAF27168F1B390 /* LiquidityPoolsOverview */ = { + isa = PBXGroup; + children = ( + A692D227372B24F922EFA058 /* LiquidityPoolsOverviewProtocols.swift */, + 3F25F3A88B4BEB4DE498220C /* LiquidityPoolsOverviewRouter.swift */, + 3BA8DC8007FC0A322C6DF00E /* LiquidityPoolsOverviewPresenter.swift */, + 6717FF1B7777400B62F028C3 /* LiquidityPoolsOverviewInteractor.swift */, + FD8B69E9E18C11EAEC9284B3 /* LiquidityPoolsOverviewViewController.swift */, + FC0B2D0A77F4B0F7CC9E7C1D /* LiquidityPoolsOverviewViewLayout.swift */, + EC863A9CE29C63B740C6E4D9 /* LiquidityPoolsOverviewAssembly.swift */, + ); + path = LiquidityPoolsOverview; + sourceTree = ""; + }; 6784511E27C7B7E095FFD4AB /* Modules */ = { isa = PBXGroup; children = ( @@ -7629,6 +7759,12 @@ E1A8025898B97966D25AF46D /* NftSendConfirm */, 85BB4B6268BB3E4F39F414D1 /* AssetNetworks */, D734A66128ED3C8653098101 /* ClaimCrowdloanRewards */, + 9468F26496DF90FEE7016AA3 /* LiquidityPoolsOverview */, + 9439C16432098735E8F4C122 /* LiquidityPoolDetails */, + 04265CAB3B55A71F49337293 /* LiquidityPoolSupply */, + 749EAA035EECE4D63C56C358 /* LiquidityPoolSupplyConfirm */, + 48EAF80DCC0C537917FC5A23 /* LiquidityPoolRemoveLiquidity */, + BDB80385E6818AE7707DDFF8 /* LiquidityPoolRemoveLiquidityConfirm */, ); path = Modules; sourceTree = ""; @@ -7676,6 +7812,14 @@ path = ControllerAccountConfirmation; sourceTree = ""; }; + 749EAA035EECE4D63C56C358 /* LiquidityPoolSupplyConfirm */ = { + isa = PBXGroup; + children = ( + 3A43F0468DEBA7500C6B23AF /* LiquidityPoolSupplyConfirmTests.swift */, + ); + path = LiquidityPoolSupplyConfirm; + sourceTree = ""; + }; 77D9A8552D1961A00A3683BE /* SelectValidatorsConfirm */ = { isa = PBXGroup; children = ( @@ -7831,6 +7975,7 @@ F4DCAE4526207ECD00CCA6BF /* PayoutRewardsService */, 845BB8B625E4464D00E5FCDC /* ExtrinsicService */, 2AB7A7FD25CD0E3E00767D87 /* GitHubPhishingService */, + 84452F2925D5B81800F47EC5 /* RuntimeRegistryService */, 84155DE9253980E100A27058 /* WebSocketService */, 84155DEC2539817200A27058 /* ApplicationService.swift */, 84BE209D25E85CCA00B4748C /* ServiceCoordinator.swift */, @@ -7907,6 +8052,7 @@ 84D1110B26B922D50016D962 /* ConnectionPool.swift */, 84CA68DC26BEA60A003B9453 /* ConnectionFactory.swift */, FA9A8F482A82034B008FA99F /* EthereumConnectionPool.swift */, + 07ED2EB82C341A0100FF7500 /* NodeApiKeyInjector.swift */, ); path = ConnectionPool; sourceTree = ""; @@ -8386,6 +8532,15 @@ path = Bifrost; sourceTree = ""; }; + 84452F2925D5B81800F47EC5 /* RuntimeRegistryService */ = { + isa = PBXGroup; + children = ( + 84452F2A25D5B84200F47EC5 /* RuntimeRegistryServiceProtocol.swift */, + 84452F4D25D5BB1C00F47EC5 /* RuntimeCoderFactory.swift */, + ); + path = RuntimeRegistryService; + sourceTree = ""; + }; 84452F6F25D5E2B300F47EC5 /* Resources */ = { isa = PBXGroup; children = ( @@ -8493,7 +8648,6 @@ isa = PBXGroup; children = ( FA74359E29C073790085A47E /* ChainSettingsMapper.swift */, - FA99422927FE927700D771E5 /* AssetModelMapper.swift */, 845B821826EF808D00D25C72 /* MetaAccountMapper.swift */, 84CA68DE26BEAA0F003B9453 /* ChainModelMapper.swift */, 845B822026EF8F1A00D25C72 /* ManagedMetaAccountMapper.swift */, @@ -8592,7 +8746,9 @@ 07C3397129189B720057C4A5 /* ChainsTypesSyncService.swift */, 8436E94326C853E4003D4EA7 /* RuntimeSnapshotOperationFactory.swift */, 07F2B76228ACDA7800280C38 /* RuntimeHotBootSnapshotFactory.swift */, + 8436E94526C85405003D4EA7 /* RuntimeSnapshot.swift */, 844CB57126F9EB2000396E13 /* RuntimeCodingService.swift */, + FAADF71129C47D10002B6D39 /* RuntimeSpecVersion.swift */, ); path = RuntimeProviderPool; sourceTree = ""; @@ -8735,7 +8891,7 @@ 8467FD4E24EFD0EC005D486C /* Storage */ = { isa = PBXGroup; children = ( - FACE6C5D2BBAC3B000643CEF /* SubstrateDataModel.xcdatamodeld */, + FAD0679F2C2044490050291F /* SubstrateDataModel.xcdatamodeld */, FACD42852A5BE811009975AA /* Migration */, FA74359C29C0736F0085A47E /* StorageWrapper.swift */, 8457F91126EB9088006803E1 /* EntityToModel */, @@ -8984,9 +9140,9 @@ 848FFE6425E670CE00652AA5 /* EraValidatorsService */ = { isa = PBXGroup; children = ( - 0739FD2A2BFB4A70009ADD7C /* DefaultEraStakersFetching.swift */, - 0739FD292BFB4A70009ADD7C /* EraStakersFetching.swift */, - 0739FD2B2BFB4A70009ADD7C /* LegacyEraStakersFetching.swift */, + FAD067CE2C20453E0050291F /* DefaultEraStakersFetching.swift */, + FAD067CC2C20453E0050291F /* EraStakersFetching.swift */, + FAD067CD2C20453E0050291F /* LegacyEraStakersFetching.swift */, 848FFE6525E6742400652AA5 /* EraValidatorService.swift */, 848FFE8A25E69A6000652AA5 /* EraValidatorServiceProtocol.swift */, 84786DA725F9F58E0089DFF7 /* EraValidatorService+Fetch.swift */, @@ -9022,7 +9178,6 @@ children = ( FA8644342767AB7E00956D8E /* CoreLayer */, FA38C9A227606FDD005C5577 /* ApplicationLayer */, - 84452F6F25D5E2B300F47EC5 /* Resources */, 8490141D24A93027008F705E /* Fonts */, 849013E324A92915008F705E /* Configs */, 849013D124A92686008F705E /* Common */, @@ -9064,7 +9219,6 @@ FAC6CDA22BA80D590013A17E /* Errors */, FAC6CD9B2BA8096D0013A17E /* Localization */, FA6C178F2993601A00A55254 /* AddressChainDefiner */, - FAADC1BD29265A7900DA9903 /* QRCoding */, 07FBC9E328BE269F00ED65B4 /* ChainIssuesCenter */, FA4B929C2844D0C80003BCEF /* SyntaxSugar */, FAF5E9C827E46D3E005A3448 /* Codable */, @@ -9099,7 +9253,8 @@ 849013D224A9268D008F705E /* Modules */ = { isa = PBXGroup; children = ( - 070179632BCA3D4F00908C83 /* AssetManagement */, + FAD067AF2C2044B10050291F /* AssetManagement */, + FA1D51D42BCFD410001353E7 /* LiquidityPools */, FA34EEC82B98723B0042E73E /* BalanceLocksDetail */, FA34EEBD2B98723B0042E73E /* Onboarding */, FA34EEB52B98723B0042E73E /* OnboardingStart */, @@ -9130,6 +9285,7 @@ 0D927CDE29F5C9F4CA537F8F /* AccountConfirm */, 4C5888389F25B5C82454F92D /* AccountCreate */, BF6F50DD15230CADAC713359 /* AccountImport */, + 26F53332B25039CD43301CAF /* AccountManagement */, 8468B86824F63C8400B76BC6 /* AddAccount */, 84F4A9DC2551EC7D000CF0A3 /* Export */, 8428766C24AE046200D91AD8 /* LanguageSelection */, @@ -9189,6 +9345,8 @@ 849013D724A927E2008F705E /* Extension */ = { isa = PBXGroup; children = ( + FA5085AA2C33C6D4002DF97D /* SafeArray.swift */, + FA5085AB2C33C6D4002DF97D /* SafeDictionary.swift */, FACD427E2A5BE7D8009975AA /* JSONRPCOperation+Result.swift */, FAFFAEA529AC851A0074AF1F /* Bool + Inverted.swift */, FAF5E9DD27E46DCC005A3448 /* String+VersionComparsion.swift */, @@ -9248,7 +9406,6 @@ 842876B024AE059700D91AD8 /* AboutData.swift */, 84113B6B255B2835009BD21A /* AccountCreateError.swift */, 843C49DC24DF397800B71DDA /* AccountImportSource.swift */, - 8423B0DF251A759000B8687C /* Chain.swift */, 8463A72C25E3A8E1003B8160 /* ChainStorageDecodedItem.swift */, 843910AF253ED36C00E3C217 /* ChainStorageItem.swift */, 84893C0624DA890F008F6A3F /* CommonError.swift */, @@ -9448,8 +9605,9 @@ 8490144D24A93E2E008F705E /* UIKit */ = { isa = PBXGroup; children = ( - 074D83302BCA49BF00AD1336 /* UIImageView+Shimmered.swift */, - 074D832C2BCA490900AD1336 /* UIImage+Monochrome.swift */, + FA96101F2C5205B200C3C750 /* UIViewController.swift */, + FAD067D22C20550B0050291F /* UIImageView+Shimmered.swift */, + FAD067952C2043DC0050291F /* UIImage+Monochrome.swift */, FAD429342A8656B7001D6A16 /* UICollectionView.swift */, FAD429332A8656B6001D6A16 /* UITableView.swift */, 0716C84E28880304004C8CB1 /* UIResponder.swift */, @@ -9458,7 +9616,6 @@ F409672526B29B04008CD244 /* UIScrollView+ScrollToPage.swift */, 8490144E24A93E2E008F705E /* UIImage+Drawing.swift */, 849014C424AA890D008F705E /* UIFont+Style.swift */, - 8428766A24ADF51D00D91AD8 /* UIViewController.swift */, 84EBC55E24F71D6A00459D15 /* UITableViewCell+ReorderColor.swift */, 84CCBFBB2509709500180F4F /* UIBarButtonItem+Style.swift */, 84D331AE2519E8080078D044 /* TriangularedView+Style.swift */, @@ -9486,7 +9643,8 @@ 8490145424A9403C008F705E /* Helpers */ = { isa = PBXGroup; children = ( - 0701797C2BCA3D6100908C83 /* WalletAssetsObserver.swift */, + FAD067982C2043FC0050291F /* ChainConnectionVisibilityHelper.swift */, + FAD067972C2043FC0050291F /* WalletAssetsObserver.swift */, FACD42802A5BE7E7009975AA /* Abbreviations.swift */, FA286AF42A3043C3008BD527 /* ConvenienceError.swift */, FA74359829C0735B0085A47E /* ChainSettingsRepositoryFactory.swift */, @@ -9528,7 +9686,6 @@ FA584C792AB2BFE300F6F020 /* MediaType.swift */, FAC6CD932BA802840013A17E /* NumberFormatterFactoryProtocol.swift */, FAC6CDAE2BA81FA00013A17E /* WalletLoggerProtocol.swift */, - 0768FBBD2BDCEDC300FB126F /* ChainConnectionVisibilityHelper.swift */, ); path = Helpers; sourceTree = ""; @@ -9621,6 +9778,7 @@ 8490149D24AA7F9A008F705E /* View */ = { isa = PBXGroup; children = ( + FA1D02032BBE71F2005B7071 /* TokenPairIconsView.swift */, FA34EE9D2B9871BD0042E73E /* TriangularedTitleMultiValueView.swift */, FAD429312A865695001D6A16 /* CheckboxButton.swift */, FACD42A82A5BE82A009975AA /* ContentAlignment.swift */, @@ -9639,7 +9797,6 @@ 07DE95CD28A16C7C00E9C2CB /* SearchTextField.swift */, FA4B92952844D0100003BCEF /* ShimmeredLabel.swift */, FA4B92962844D0100003BCEF /* ShimmeredProtocol.swift */, - FA4B92942844D0100003BCEF /* UIImageView+Shimmered.swift */, FA8644502768A13300956D8E /* TwoLabelView.swift */, FA38C988275DFB8D005C5577 /* NavigationBar */, FA2569B9274CE74000875A53 /* AttentionView.swift */, @@ -9705,6 +9862,9 @@ FA584C772AB2BCD500F6F020 /* UniversalMediaView.swift */, C6DC2D592B1458CC00BAA4DB /* CollectionViewSectionHeader.swift */, FAC6CD972BA807D30013A17E /* AccessoryView.swift */, + FA2222932BD2726F0031DE04 /* SkeletonLabel.swift */, + FA2222952BD272A30031DE04 /* SkeletonLoadableView.swift */, + FA887A482C1C19DB00CA720F /* WarningView.swift */, ); path = View; sourceTree = ""; @@ -9887,6 +10047,7 @@ 849244902514EDD900477C1B /* ViewModel */ = { isa = PBXGroup; children = ( + FA1D02052BBE71F9005B7071 /* TokenPairsIconViewModel.swift */, 0702B3162970182B003519F5 /* Amount */, FAA013A028DA1328000A5230 /* StakeAmountViewModel.swift */, FAA013A128DA1328000A5230 /* TitleMultiValueViewModel.swift */, @@ -10268,6 +10429,7 @@ 84D1110F26B932300016D962 /* ChainRegistry */ = { isa = PBXGroup; children = ( + FAD0679B2C2044170050291F /* ExternalApiExplorerType.swift */, 84D1110D26B931C20016D962 /* ChainModel.swift */, 84D1111026B932480016D962 /* AssetModel.swift */, 84D1111226B932C40016D962 /* ChainNodeModel.swift */, @@ -10275,7 +10437,6 @@ 845B821C26EF80DB00D25C72 /* ChainAccountModel.swift */, 845B821E26EF8E8900D25C72 /* ManagedMetaAccountModel.swift */, C63C82FC2769ECCC002EA6A8 /* ChainAssetModel.swift */, - 075A2F092BF722F300CE6F24 /* ExternalApiExplorerType.swift */, ); path = ChainRegistry; sourceTree = ""; @@ -10364,6 +10525,7 @@ 843C49E024DFFC9500B71DDA /* AccountImportSource+ViewModel.swift */, 84754C992513871300854599 /* SNAddressType+Codable.swift */, 84D97EC0251FEE1E00F07405 /* WalletAssetId+Display.swift */, + 84CD356F252620FB0081BC0B /* CryptoType+Extrinsic.swift */, 8460516C25536C4800A1F0B4 /* ExportOption+ViewModel.swift */, 84A259F72555C8C9001E91BC /* CryptoType+Keystore.swift */, ); @@ -10442,7 +10604,6 @@ 84E1CCF3260DC973001E81B5 /* SwitchAccount */ = { isa = PBXGroup; children = ( - 84E1CCF4260DCB91001E81B5 /* SwitchAccount+AccountManagementWireframe.swift */, 84E1CCF9260DCBF9001E81B5 /* SwitchAccount+UsernameSetupWireframe.swift */, 84E1CD01260DCC62001E81B5 /* SwitchAccount+OnboardingMainWireframe.swift */, 84E1CD06260DCCE8001E81B5 /* SwitchAccount+AccountCreateWireframe.swift */, @@ -10487,7 +10648,6 @@ children = ( FACD42782A5BE7C6009975AA /* RuntimeSnapshotReady.swift */, FACD42792A5BE7C6009975AA /* WalletRemoteSubscriptionWasUpdatedEvent.swift */, - FAFFAEA729AC85230074AF1F /* ZeroBalancesSettingChanged.swift */, FA4B92902844CF750003BCEF /* MetaAccountModelChangedEvent.swift */, FA99549A27B3B60700CCC94B /* WalletNameChanged.swift */, 84EBC55A24F660F500459D15 /* SelectedAccountChanged.swift */, @@ -10756,6 +10916,22 @@ path = StakingRewardPayouts; sourceTree = ""; }; + 9439C16432098735E8F4C122 /* LiquidityPoolDetails */ = { + isa = PBXGroup; + children = ( + 2CF682B92176E0FED5D7B4DB /* LiquidityPoolDetailsTests.swift */, + ); + path = LiquidityPoolDetails; + sourceTree = ""; + }; + 9468F26496DF90FEE7016AA3 /* LiquidityPoolsOverview */ = { + isa = PBXGroup; + children = ( + FC76E7D99A98423180BC572F /* LiquidityPoolsOverviewTests.swift */, + ); + path = LiquidityPoolsOverview; + sourceTree = ""; + }; 98D53F0D0FA4CBD6693747C1 /* WalletTransactionDetails */ = { isa = PBXGroup; children = ( @@ -11362,6 +11538,14 @@ path = NodeSelection; sourceTree = ""; }; + BDB80385E6818AE7707DDFF8 /* LiquidityPoolRemoveLiquidityConfirm */ = { + isa = PBXGroup; + children = ( + 31F75A22E215273305AF7AA2 /* LiquidityPoolRemoveLiquidityConfirmTests.swift */, + ); + path = LiquidityPoolRemoveLiquidityConfirm; + sourceTree = ""; + }; BF6F50DD15230CADAC713359 /* AccountImport */ = { isa = PBXGroup; children = ( @@ -11470,7 +11654,7 @@ C6267B8B28BDF6A5001E31BF /* Views */ = { isa = PBXGroup; children = ( - 070179602BC7F91600908C83 /* ChainAssetListViewLayout.swift */, + FAD067C82C2044D30050291F /* ChainAssetListViewLayout.swift */, FA1A023B274F51A900DA07CB /* ChainAccountBalanceTableCell.swift */, ); path = Views; @@ -11703,6 +11887,20 @@ path = ReferralCrowdloan; sourceTree = ""; }; + D8F784121F6FDD3BCB25424B /* LiquidityPoolRemoveLiquidity */ = { + isa = PBXGroup; + children = ( + 3D49CA5CB156C1EA38BEBE00 /* LiquidityPoolRemoveLiquidityProtocols.swift */, + 25D9454047EBBD8D8A0174A4 /* LiquidityPoolRemoveLiquidityRouter.swift */, + 1B3E9CA265E5C0F3E83429CE /* LiquidityPoolRemoveLiquidityPresenter.swift */, + 6887529305794E17D9434D44 /* LiquidityPoolRemoveLiquidityInteractor.swift */, + 835D5A5DD9258786D27BDC23 /* LiquidityPoolRemoveLiquidityViewController.swift */, + 6419D75A346CE10236161522 /* LiquidityPoolRemoveLiquidityViewLayout.swift */, + C61BE0DFC48282DFDBB820C9 /* LiquidityPoolRemoveLiquidityAssembly.swift */, + ); + path = LiquidityPoolRemoveLiquidity; + sourceTree = ""; + }; DA46895F73B0FB1064146E47 /* AssetNetworks */ = { isa = PBXGroup; children = ( @@ -11837,6 +12035,21 @@ path = WalletsManagment; sourceTree = ""; }; + EE3CBEFADE55F44DE05DCEF2 /* LiquidityPoolSupply */ = { + isa = PBXGroup; + children = ( + FA53D88E2C084EB800173ADB /* ViewModel */, + 8FB7091F743BBACC09553298 /* LiquidityPoolSupplyProtocols.swift */, + 6503D178156C6407EC848D41 /* LiquidityPoolSupplyRouter.swift */, + 31F848482B2AD7D6831B0CCE /* LiquidityPoolSupplyPresenter.swift */, + 9BA528679A82B9A327853804 /* LiquidityPoolSupplyInteractor.swift */, + 497EFA05A2D8076BFE82964D /* LiquidityPoolSupplyViewController.swift */, + 438E01C5C877428168E9F3F8 /* LiquidityPoolSupplyViewLayout.swift */, + 62928FB3556EEA3A228131AC /* LiquidityPoolSupplyAssembly.swift */, + ); + path = LiquidityPoolSupply; + sourceTree = ""; + }; EFC2669335EE7F7297DF423E /* CrowdloanContributionSetup */ = { isa = PBXGroup; children = ( @@ -11858,6 +12071,17 @@ path = Purchase; sourceTree = ""; }; + F27AF708352372E8D743CD3F /* LiquidityPoolRemoveLiquidityConfirm */ = { + isa = PBXGroup; + children = ( + 882D47A501D9D6CCE7B99691 /* LiquidityPoolRemoveLiquidityConfirmProtocols.swift */, + 916326B6F6651BBC5913B26F /* LiquidityPoolRemoveLiquidityConfirmViewController.swift */, + B3459F610D6E5C782D8695A9 /* LiquidityPoolRemoveLiquidityConfirmViewLayout.swift */, + ECE2059F621D024F85EFBFD0 /* LiquidityPoolRemoveLiquidityConfirmAssembly.swift */, + ); + path = LiquidityPoolRemoveLiquidityConfirm; + sourceTree = ""; + }; F400A7C0260CE1560061D576 /* Model */ = { isa = PBXGroup; children = ( @@ -12336,11 +12560,19 @@ isa = PBXGroup; children = ( FA072C13277AE2FE00731718 /* QRCaptureService.swift */, - FA072C15277B023D00731718 /* QRExtractionService.swift */, ); path = QRService; sourceTree = ""; }; + FA09AD332C37AB9400BE0B9C /* TransactionObserver */ = { + isa = PBXGroup; + children = ( + FA09AD342C37ABA000BE0B9C /* TransactionObserver.swift */, + FA09AD362C37AF9200BE0B9C /* SubstrateTransactionObserver.swift */, + ); + path = TransactionObserver; + sourceTree = ""; + }; FA176BB62851B41900258125 /* Parachain */ = { isa = PBXGroup; children = ( @@ -12372,6 +12604,119 @@ path = CustomTransition; sourceTree = ""; }; + FA1D01EC2BBE713D005B7071 /* LiquidityPoolsList */ = { + isa = PBXGroup; + children = ( + FA1D02072BBE74A6005B7071 /* Flows */, + FA1D01ED2BBE713D005B7071 /* ViewModel */, + FA1D01F02BBE713D005B7071 /* LiquidityPoolsListViewLayout.swift */, + FA1D01F12BBE713D005B7071 /* LiquidityPoolsListRouter.swift */, + FA1D01F22BBE713D005B7071 /* LiquidityPoolsListProtocols.swift */, + FA1D01F42BBE713D005B7071 /* LiquidityPoolsListAssembly.swift */, + FA1D01F52BBE713D005B7071 /* View */, + FA1D01F72BBE713D005B7071 /* LiquidityPoolsListViewController.swift */, + ); + path = LiquidityPoolsList; + sourceTree = ""; + }; + FA1D01ED2BBE713D005B7071 /* ViewModel */ = { + isa = PBXGroup; + children = ( + FA1D01EE2BBE713D005B7071 /* LiquidityPoolListCellModel.swift */, + FA1D01EF2BBE713D005B7071 /* LiquidityPoolListViewModel.swift */, + FA4441332BF75FD90067C633 /* LiquidityPoolListType.swift */, + ); + path = ViewModel; + sourceTree = ""; + }; + FA1D01F52BBE713D005B7071 /* View */ = { + isa = PBXGroup; + children = ( + FA1D01F62BBE713D005B7071 /* LiquidityPoolListCell.swift */, + ); + path = View; + sourceTree = ""; + }; + FA1D02072BBE74A6005B7071 /* Flows */ = { + isa = PBXGroup; + children = ( + FA1D020B2BBE7678005B7071 /* UserPools */, + FA1D020A2BBE766E005B7071 /* AvailablePools */, + ); + path = Flows; + sourceTree = ""; + }; + FA1D020A2BBE766E005B7071 /* AvailablePools */ = { + isa = PBXGroup; + children = ( + FA1D02082BBE74B7005B7071 /* AvailableLiquidityPoolsListInteractor.swift */, + FA054A992BCD1FA3007B8F6D /* AvailableLiquidityPoolsListPresenter.swift */, + FA054A9B2BCD1FAF007B8F6D /* AvailableLiquidityPoolsListViewModelFactory.swift */, + ); + path = AvailablePools; + sourceTree = ""; + }; + FA1D020B2BBE7678005B7071 /* UserPools */ = { + isa = PBXGroup; + children = ( + FA1D020C2BBE7690005B7071 /* UserLiquidityPoolsListInteractor.swift */, + FA8810D22BDCCF7E0084CC4B /* UserLiquidityPoolsListPresenter.swift */, + FA8810D42BDCD19D0084CC4B /* UserLiquidityPoolsListViewModelFactory.swift */, + ); + path = UserPools; + sourceTree = ""; + }; + FA1D51D42BCFD410001353E7 /* LiquidityPools */ = { + isa = PBXGroup; + children = ( + D8F784121F6FDD3BCB25424B /* LiquidityPoolRemoveLiquidity */, + F27AF708352372E8D743CD3F /* LiquidityPoolRemoveLiquidityConfirm */, + 3362664DE1DD71BB75722C2D /* LiquidityPoolSupplyConfirm */, + EE3CBEFADE55F44DE05DCEF2 /* LiquidityPoolSupply */, + 478C62A42D572C8647512722 /* LiquidityPoolDetails */, + 675669EAE3DAF27168F1B390 /* LiquidityPoolsOverview */, + FA1D51D52BCFD41F001353E7 /* Common */, + FA1D01EC2BBE713D005B7071 /* LiquidityPoolsList */, + ); + path = LiquidityPools; + sourceTree = ""; + }; + FA1D51D52BCFD41F001353E7 /* Common */ = { + isa = PBXGroup; + children = ( + FA1D51D62BCFD445001353E7 /* LiquidityPools+ViewModel.swift */, + FAD067D42C214E7C0050291F /* LiquidityPoolsConstants.swift */, + ); + path = Common; + sourceTree = ""; + }; + FA1D51DA2BCFE377001353E7 /* SoraFiatService */ = { + isa = PBXGroup; + children = ( + FA1D51D82BCFE353001353E7 /* SoraFiatService.swift */, + FA1D51DB2BCFE38D001353E7 /* SubqueryFiatInfoOperation.swift */, + ); + path = SoraFiatService; + sourceTree = ""; + }; + FA22228B2BD237850031DE04 /* Pricing */ = { + isa = PBXGroup; + children = ( + FA22228C2BD237910031DE04 /* SubqueryPriceFetcher.swift */, + FA22228E2BD237CF0031DE04 /* SoraSubqueryPriceFetcher.swift */, + FA2222922BD239620031DE04 /* Model */, + ); + path = Pricing; + sourceTree = ""; + }; + FA2222922BD239620031DE04 /* Model */ = { + isa = PBXGroup; + children = ( + FA2222902BD239500031DE04 /* SoraSubqueryPriceResponse.swift */, + ); + path = Model; + sourceTree = ""; + }; FA25698C274CE65100875A53 /* Requests */ = { isa = PBXGroup; children = ( @@ -12744,7 +13089,7 @@ FA3067292B6246BD006A0BA5 /* Storage */ = { isa = PBXGroup; children = ( - 0739FD312BFB4B98009ADD7C /* Keys */, + FAD067AA2C2044810050291F /* Keys */, FAD9AAC22B8DFE0200AA603B /* PrefixRequest.swift */, FAAA29352B8DCE930089AFE6 /* MultipleRequest.swift */, FAAA29342B8DCE930089AFE6 /* StorageRequest.swift */, @@ -12929,6 +13274,7 @@ FA34EEBD2B98723B0042E73E /* Onboarding */ = { isa = PBXGroup; children = ( + FAD067CA2C2044F00050291F /* OnboardingConfigVersionResolver.swift */, FA34EEBE2B98723B0042E73E /* OnboardingRouter.swift */, FA34EEBF2B98723B0042E73E /* OnboardingPresenter.swift */, FA34EEC02B98723B0042E73E /* ViewModel */, @@ -12937,7 +13283,6 @@ FA34EEC52B98723B0042E73E /* OnboardingViewController.swift */, FA34EEC62B98723B0042E73E /* OnboardingViewLayout.swift */, FA34EEC72B98723B0042E73E /* OnboardingAssembly.swift */, - C66E68CD2BFC119300A14759 /* OnboardingConfigVersionResolver.swift */, ); path = Onboarding; sourceTree = ""; @@ -13075,7 +13420,7 @@ FA38C993275E0A63005C5577 /* ViewModelFactory */ = { isa = PBXGroup; children = ( - 074D832E2BCA496300AD1336 /* ChainAssetListBuilder.swift */, + FAD067A82C20445F0050291F /* ChainAssetListBuilder.swift */, FA38C994275E0A70005C5577 /* RemoteImageViewModelFactory.swift */, FA38C996275E0AB8005C5577 /* AssetPriceViewModelFactory.swift */, FA38C99C275F3B1B005C5577 /* ChainOptionsViewModelFactory.swift */, @@ -13087,6 +13432,7 @@ FA38C9A227606FDD005C5577 /* ApplicationLayer */ = { isa = PBXGroup; children = ( + FA22228B2BD237850031DE04 /* Pricing */, FA34EE8D2B98710C0042E73E /* Models */, FA34EE8A2B9870FE0042E73E /* ComponentFactories */, FA7741D32B6A350200358315 /* StakingRewards */, @@ -13105,6 +13451,7 @@ FA38C9A32760700B005C5577 /* Services */ = { isa = PBXGroup; children = ( + FA09AD332C37AB9400BE0B9C /* TransactionObserver */, FA34EE902B98711F0042E73E /* CrowdloanService.swift */, FA34EE912B9871200042E73E /* Onboarding */, 0765296B2AD9516800BA1D99 /* Polkaswap */, @@ -13121,6 +13468,7 @@ FA38C9A52760701F005C5577 /* SearchService.swift */, FA8644322767AB2300956D8E /* HistoryService.swift */, FADBA5F52B61222C00CFCF30 /* NetworkInfoFetching.swift */, + FA1D51DA2BCFE377001353E7 /* SoraFiatService */, ); path = Services; sourceTree = ""; @@ -13233,6 +13581,15 @@ path = Main; sourceTree = ""; }; + FA53D88E2C084EB800173ADB /* ViewModel */ = { + isa = PBXGroup; + children = ( + FA53D88F2C084ECA00173ADB /* LiquidityPoolSupplyViewModel.swift */, + FA53D8912C08510000173ADB /* LiquidityPoolSupplyViewModelFactory.swift */, + ); + path = ViewModel; + sourceTree = ""; + }; FA584C7F2AB308AE00F6F020 /* Etherscan */ = { isa = PBXGroup; children = ( @@ -13420,6 +13777,15 @@ path = ChainAccount; sourceTree = ""; }; + FA6ECE722BF49BE300481B2B /* ViewModel */ = { + isa = PBXGroup; + children = ( + FA6ECE732BF49C0C00481B2B /* LiquidityPoolDetailsViewModel.swift */, + FA6ECE752BF49D3D00481B2B /* LiquidityPoolDetailsViewModelFactory.swift */, + ); + path = ViewModel; + sourceTree = ""; + }; FA7253F92AC2E48400EC47A6 /* Model */ = { isa = PBXGroup; children = ( @@ -13717,6 +14083,15 @@ path = StakingAccountSubscription; sourceTree = ""; }; + FA887A432C107A0200CA720F /* ViewModel */ = { + isa = PBXGroup; + children = ( + FA887A442C107A1100CA720F /* LiquidityPoolSupplyConfirmViewModel.swift */, + FA887A462C107A4300CA720F /* LiquidityPoolSupplyConfirmViewModelFactory.swift */, + ); + path = ViewModel; + sourceTree = ""; + }; FA8ED43128FD8D6200EBB712 /* Flows */ = { isa = PBXGroup; children = ( @@ -14092,7 +14467,7 @@ FA9A8F282A725AE9008FA99F /* Balance */ = { isa = PBXGroup; children = ( - 074D83342BCA84A900AD1336 /* AccountInfoRemoteService */, + FAD0678C2C2042F30050291F /* RemoteSubscription */, FA34EE992B98712D0042E73E /* BalanceLocksFetching.swift */, FA9A8F292A725AFC008FA99F /* AccountInfo */, 07E346D2288E614C00A8FAEC /* WalletBalanceSubscription */, @@ -14419,19 +14794,10 @@ FA3067292B6246BD006A0BA5 /* Storage */, FAFB47D52ABD588D0008F8CA /* Repository */, FA7336C52A0E3B870096A291 /* Network */, - FAAB998B27A7C79000CD1A3B /* QR */, ); path = CoreComponents; sourceTree = ""; }; - FAAB998B27A7C79000CD1A3B /* QR */ = { - isa = PBXGroup; - children = ( - FAAB998C27A7C79D00CD1A3B /* QRParser.swift */, - ); - path = QR; - sourceTree = ""; - }; FAABC4712845C7E7002CF40E /* Parachain */ = { isa = PBXGroup; children = ( @@ -14480,7 +14846,6 @@ FAADC1AE2926597400DA9903 /* ScanQR */ = { isa = PBXGroup; children = ( - 070CDD6E2ACACEBC00F3F20A /* Matchers */, FAADC1AF2926597400DA9903 /* ScanQRAssembly.swift */, FAADC1B02926597400DA9903 /* ScanQRViewLayout.swift */, FAADC1B12926597400DA9903 /* ScanQRInteractor.swift */, @@ -14492,17 +14857,6 @@ path = ScanQR; sourceTree = ""; }; - FAADC1BD29265A7900DA9903 /* QRCoding */ = { - isa = PBXGroup; - children = ( - 070CDD732ACAE02400F3F20A /* QRInfos */, - C61566842930A07900391BF3 /* QRCreationOperation.swift */, - C615668029309D3900391BF3 /* QRService.swift */, - FAADC1C529265C9600DA9903 /* QRCoderFactory.swift */, - ); - path = QRCoding; - sourceTree = ""; - }; FAB0EDD727AA6922003D93C2 /* Views */ = { isa = PBXGroup; children = ( @@ -14725,7 +15079,7 @@ FACD42852A5BE811009975AA /* Migration */ = { isa = PBXGroup; children = ( - 074D83322BCA4A4200AD1336 /* AssetManagementMigrator.swift */, + FAD0679D2C2044320050291F /* AssetManagementMigrator.swift */, FACD42862A5BE811009975AA /* SettingsMigrator.swift */, FACD42872A5BE811009975AA /* SubstrateStorage */, FACD428D2A5BE811009975AA /* UserStorage */, @@ -14770,6 +15124,58 @@ path = Model; sourceTree = ""; }; + FAD0678C2C2042F30050291F /* RemoteSubscription */ = { + isa = PBXGroup; + children = ( + FAD0678E2C2042F30050291F /* Requests.swift */, + FAD0678F2C2042F30050291F /* AccountInfoRemoteService.swift */, + ); + path = RemoteSubscription; + sourceTree = ""; + }; + FAD067AA2C2044810050291F /* Keys */ = { + isa = PBXGroup; + children = ( + FAD067AB2C2044810050291F /* ErasStakersPagedKey.swift */, + FAD067AC2C2044810050291F /* ErasStakersOverviewKey.swift */, + ); + path = Keys; + sourceTree = ""; + }; + FAD067AF2C2044B10050291F /* AssetManagement */ = { + isa = PBXGroup; + children = ( + FAD067B02C2044B10050291F /* ViewModel */, + FAD067B32C2044B10050291F /* AssetManagementInteractor.swift */, + FAD067B42C2044B10050291F /* AssetManagementAssembly.swift */, + FAD067B52C2044B10050291F /* AssetManagementRouter.swift */, + FAD067B62C2044B10050291F /* AssetManagementPresenter.swift */, + FAD067B72C2044B10050291F /* AssetManagementViewController.swift */, + FAD067B82C2044B10050291F /* TableViews */, + FAD067BB2C2044B10050291F /* AssetManagementProtocols.swift */, + FAD067BC2C2044B10050291F /* AssetManagementViewLayout.swift */, + ); + path = AssetManagement; + sourceTree = ""; + }; + FAD067B02C2044B10050291F /* ViewModel */ = { + isa = PBXGroup; + children = ( + FAD067B12C2044B10050291F /* AssetManagementViewModel.swift */, + FAD067B22C2044B10050291F /* AssetManagementViewModelFactory.swift */, + ); + path = ViewModel; + sourceTree = ""; + }; + FAD067B82C2044B10050291F /* TableViews */ = { + isa = PBXGroup; + children = ( + FAD067B92C2044B10050291F /* AssetManagementTableCell.swift */, + FAD067BA2C2044B10050291F /* AssetManagementTableHeaderView.swift */, + ); + path = TableViews; + sourceTree = ""; + }; FAD4289B2A865635001D6A16 /* BackupRiskWarnings */ = { isa = PBXGroup; children = ( @@ -15291,7 +15697,6 @@ children = ( FAFFAE4F29AC84B10074AF1F /* SubqueryPageInfo.swift */, FAFFAE5029AC84B10074AF1F /* SubqueryDelegatorHistoryData.swift */, - FAFFAE5129AC84B10074AF1F /* GraphQLResponse.swift */, FAFFAE5229AC84B10074AF1F /* SubqueryTransfer.swift */, FAFFAE5329AC84B10074AF1F /* SubqueryDelegatorHistoryElement.swift */, FAFFAE5429AC84B10074AF1F /* SubqueryDelegatorHistoryItem.swift */, @@ -15414,40 +15819,39 @@ FA72546A2AC2F12D00EC47A6 /* WalletConnectNetworking */, FA72546C2AC2F12D00EC47A6 /* WalletConnectPairing */, FA72546E2AC2F12D00EC47A6 /* Web3Wallet */, + FA8FD1802AF4B55100354482 /* Web3 */, + FA8FD1822AF4B55100354482 /* Web3ContractABI */, + FA8FD1842AF4B55100354482 /* Web3PromiseKit */, FA8FD1872AF4BEDD00354482 /* Swime */, - 07F44F022BE4C7FF00570143 /* Web3 */, - 07F44F042BE4C7FF00570143 /* Web3ContractABI */, - 07F44F062BE4C7FF00570143 /* Web3PromiseKit */, - FA53D8962C096F1100173ADB /* IrohaCrypto */, - FA53D8982C096F1100173ADB /* MPQRCoreSDK */, - FA53D89A2C096F1100173ADB /* RobinHood */, - FA53D89C2C096F1100173ADB /* SSFAccountManagment */, - FA53D89E2C096F1100173ADB /* SSFAccountManagmentStorage */, - FA53D8A02C096F1100173ADB /* SSFAssetManagment */, - FA53D8A22C096F1100173ADB /* SSFChainConnection */, - FA53D8A42C096F1100173ADB /* SSFChainRegistry */, - FA53D8A62C096F1100173ADB /* SSFCloudStorage */, - FA53D8A82C096F1100173ADB /* SSFCrypto */, - FA53D8AA2C096F1100173ADB /* SSFEraKit */, - FA53D8AC2C096F1100173ADB /* SSFExtrinsicKit */, - FA53D8AE2C096F1100173ADB /* SSFHelpers */, - FA53D8B02C096F1100173ADB /* SSFKeyPair */, - FA53D8B22C096F1100173ADB /* SSFLogger */, - FA53D8B42C096F1100173ADB /* SSFModels */, - FA53D8B62C096F1100173ADB /* SSFNetwork */, - FA53D8B82C096F1100173ADB /* SSFPolkaswap */, - FA53D8BA2C096F1100173ADB /* SSFPools */, - FA53D8BC2C096F1100173ADB /* SSFPoolsStorage */, - FA53D8BE2C096F1100173ADB /* SSFQRService */, - FA53D8C02C096F1100173ADB /* SSFRuntimeCodingService */, - FA53D8C22C096F1100173ADB /* SSFSigner */, - FA53D8C42C096F1100173ADB /* SSFSingleValueCache */, - FA53D8C62C096F1100173ADB /* SSFStorageQueryKit */, - FA53D8C82C096F1100173ADB /* SSFTransferService */, - FA53D8CA2C096F1100173ADB /* SSFUtils */, - FA53D8CC2C096F1100173ADB /* SSFXCM */, - FA53D8CE2C096F1100173ADB /* SoraKeystore */, - FA53D8D02C096F1100173ADB /* keccak */, + FA8810972BDCAF260084CC4B /* IrohaCrypto */, + FA8810992BDCAF260084CC4B /* RobinHood */, + FA88109B2BDCAF260084CC4B /* SSFAccountManagment */, + FA88109D2BDCAF260084CC4B /* SSFAccountManagmentStorage */, + FA88109F2BDCAF260084CC4B /* SSFAssetManagment */, + FA8810A12BDCAF260084CC4B /* SSFChainConnection */, + FA8810A32BDCAF260084CC4B /* SSFChainRegistry */, + FA8810A52BDCAF260084CC4B /* SSFCloudStorage */, + FA8810A72BDCAF260084CC4B /* SSFCrypto */, + FA8810A92BDCAF260084CC4B /* SSFEraKit */, + FA8810AB2BDCAF260084CC4B /* SSFExtrinsicKit */, + FA8810AD2BDCAF260084CC4B /* SSFHelpers */, + FA8810AF2BDCAF260084CC4B /* SSFKeyPair */, + FA8810B12BDCAF260084CC4B /* SSFLogger */, + FA8810B32BDCAF260084CC4B /* SSFModels */, + FA8810B52BDCAF260084CC4B /* SSFNetwork */, + FA8810B72BDCAF260084CC4B /* SSFPolkaswap */, + FA8810B92BDCAF260084CC4B /* SSFPools */, + FA8810BB2BDCAF260084CC4B /* SSFPoolsStorage */, + FA8810BD2BDCAF260084CC4B /* SSFQRService */, + FA8810BF2BDCAF260084CC4B /* SSFRuntimeCodingService */, + FA8810C12BDCAF260084CC4B /* SSFSigner */, + FA8810C32BDCAF260084CC4B /* SSFSingleValueCache */, + FA8810C52BDCAF260084CC4B /* SSFStorageQueryKit */, + FA8810C72BDCAF260084CC4B /* SSFTransferService */, + FA8810C92BDCAF260084CC4B /* SSFUtils */, + FA8810CB2BDCAF260084CC4B /* SSFXCM */, + FA8810CD2BDCAF260084CC4B /* SoraKeystore */, + FA8810CF2BDCAF260084CC4B /* keccak */, ); productName = fearless; productReference = 849013A824A80984008F705E /* fearless.app */; @@ -15516,9 +15920,9 @@ mainGroup = 8490139F24A80984008F705E; packageReferences = ( FA7254652AC2F12D00EC47A6 /* XCRemoteSwiftPackageReference "WalletConnectSwiftV2" */, + FA8FD17F2AF4B55100354482 /* XCRemoteSwiftPackageReference "Web3.swift" */, FA8FD1862AF4BEDD00354482 /* XCRemoteSwiftPackageReference "Swime" */, - 07F44F012BE4C7FF00570143 /* XCRemoteSwiftPackageReference "Web3.swift" */, - FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */, + FA8810962BDCAF260084CC4B /* XCRemoteSwiftPackageReference "shared-features-spm" */, ); productRefGroup = 849013A924A80984008F705E /* Products */; projectDirPath = ""; @@ -15905,6 +16309,7 @@ FAFFAE9A29AC84B10074AF1F /* ParachainSubsquidHistoryResponse.swift in Sources */, F462B364260C88050005AB01 /* UITableView+Reuse.swift in Sources */, FA286AF52A3043C3008BD527 /* ConvenienceError.swift in Sources */, + FA1D02062BBE71F9005B7071 /* TokenPairsIconViewModel.swift in Sources */, FA72543F2AC2E48500EC47A6 /* ABI+Collection.swift in Sources */, 848919D726FB238E004DBAD5 /* JsonDataProviderFactory.swift in Sources */, 846802A3265DA5530034F9B5 /* CrowdloanContributionSetupViewModel.swift in Sources */, @@ -15952,7 +16357,6 @@ FA7A4C802A1F937A0051FB4D /* RelaychainRewardCalculatorEngine.swift in Sources */, 846CD25B265709A800A2E4B6 /* StorageKeySuffixMapper.swift in Sources */, 076D9D4D29431C71002762E3 /* SwapQuoteAmountFactory.swift in Sources */, - 8423B0E0251A759000B8687C /* Chain.swift in Sources */, 07F2B75728A3A4B800280C38 /* ChainCollectionView.swift in Sources */, 8473D40D2657E9DC00B394B2 /* MultiSigner.swift in Sources */, FA17B4B527E858CB006E0735 /* JsonLoadingFailedAlertConfig.swift in Sources */, @@ -15979,7 +16383,6 @@ 84DD5F4C263DE82C00425ACF /* DataValidationRunner.swift in Sources */, 84D8F16B24D8263300AF43E9 /* ModalPickerFactory.swift in Sources */, 847C965E255363B9002D288F /* ExportRestoreJsonWireframe.swift in Sources */, - FA7254472AC2E4AB00EC47A6 /* QRUriMatcher.swift in Sources */, FAE9EBA3288ABBD4009390B6 /* AnalyticRewardsParachainViewModelFactory.swift in Sources */, 8434C9E425401EF3009E4191 /* TransactionHistoryItem.swift in Sources */, AE8B8835267349C200AB0AA9 /* CustomVlidatorRelaychainListFilter.swift in Sources */, @@ -15994,11 +16397,13 @@ 84DA3B1224C6D29100B5E27F /* RuntimeVersion.swift in Sources */, FA176BB82851B42700258125 /* StakingBalanceParachainViewModelFactory.swift in Sources */, 843C49DB24DF373000B71DDA /* AccountImportRequest.swift in Sources */, + FA09AD352C37ABA000BE0B9C /* TransactionObserver.swift in Sources */, 843910C1253F36F300E3C217 /* BaseStorageChildSubscription.swift in Sources */, 84644AC52567EC05004EAA4B /* MultilineTriangularedView.swift in Sources */, FA86443E2768439900956D8E /* ContainerProtocols.swift in Sources */, 07F818012AD55D3600B87358 /* WalletConnectSessionCoordinator.swift in Sources */, 84FB1F69252694B600E0242B /* HistoryInfo.swift in Sources */, + FA53D8902C084ECA00173ADB /* LiquidityPoolSupplyViewModel.swift in Sources */, 84C74361251E4B5E009576C6 /* FeeType.swift in Sources */, 8428765224ADDE0200D91AD8 /* ProfilePresenter.swift in Sources */, F4F22987260DC4F300ACFDB8 /* StakingRewardDetailsSimpleLabelViewModel.swift in Sources */, @@ -16026,7 +16431,6 @@ 849014C824AA8A28008F705E /* BiometryAuth.swift in Sources */, 84690797264154E80030E693 /* SlashesOperationFactory.swift in Sources */, 8424A8C7262EC0E50091BFB1 /* PayoutInfo.swift in Sources */, - 070179722BCA3D4F00908C83 /* AssetManagementViewModelFactory.swift in Sources */, 8428768C24AE046300D91AD8 /* AboutPresenter.swift in Sources */, FA62626B2AC2E35A005D3D95 /* WalletConnectProposalViewModel.swift in Sources */, FA2E9BB927A14A600023FAD2 /* FiltersPresentable.swift in Sources */, @@ -16065,6 +16469,7 @@ 845CB6EF26276104005F798B /* SubscanQueryService.swift in Sources */, 849ABE5126276C3400011A2A /* SubscanQueryParams.swift in Sources */, 8428765624ADDE0200D91AD8 /* ProfileOptionViewModel.swift in Sources */, + FAD067922C2042F30050291F /* AccountInfoRemoteService.swift in Sources */, FAFFAE8729AC84B10074AF1F /* SubqueryRewardOrSlashData.swift in Sources */, 076D9D5E29500F5B002762E3 /* PolkaswapSwapConfirmationViewModel.swift in Sources */, 84C6801424D7013500006BF5 /* SubtitleContentView.swift in Sources */, @@ -16075,7 +16480,6 @@ 073B34BC2AE8CC4500DC5106 /* WalletConnectDisconnectService.swift in Sources */, F47BBD93263199830087DA11 /* StakingBalanceUnbondingWidgetView.swift in Sources */, AE8B8837267351E300AB0AA9 /* CustomValidatorRelaychainListComposer.swift in Sources */, - 0739FD322BFB4B98009ADD7C /* ErasStakersOverviewKey.swift in Sources */, FAE39B042AA0655B0011A9D6 /* BaseEthereumService.swift in Sources */, FA3F5B6B281BAF6600BEF03B /* StakingAmountParachainViewModelState.swift in Sources */, 845E49832636C87B002F8C22 /* StakingManageViewModel.swift in Sources */, @@ -16134,6 +16538,7 @@ 8401AEC42642A71D000B03E3 /* StakingRebondConfirmationWireframe.swift in Sources */, FA256A48274CE8C200875A53 /* StakingMainInteractor+Subscription.swift in Sources */, F4A198FB2632A1C000CD6E61 /* StakingBalanceViewModelFactory.swift in Sources */, + FAD067CF2C20453E0050291F /* EraStakersFetching.swift in Sources */, F4F3C3CB265BB12200C58400 /* CustomValidatorListViewModelFactory.swift in Sources */, 84B018B026E0450F00C75E28 /* ValidatorStateView.swift in Sources */, FAAA29302B8DCE590089AFE6 /* EncodableStorageRequestWorker.swift in Sources */, @@ -16144,7 +16549,6 @@ 84563CFF24EFE07E0055591D /* Storage+Identifiable.swift in Sources */, FA7336E32A0E3B880096A291 /* AlchemyRequestSigner.swift in Sources */, FA80391728DD70D7007365E8 /* AccountOperationFactory.swift in Sources */, - 0701797A2BCA3D4F00908C83 /* AssetManagementProtocols.swift in Sources */, FA2569BF274CE74100875A53 /* NetworkFeeView+Protocol.swift in Sources */, 843C49E124DFFC9500B71DDA /* AccountImportSource+ViewModel.swift in Sources */, 84038FF226FFBE1900C73F3F /* JsonLocalSubscriptionHandler.swift in Sources */, @@ -16162,8 +16566,10 @@ FA9278A827C382C600FF7B5B /* MultiassetV2.xcmappingmodel in Sources */, FA72542D2AC2E48500EC47A6 /* WalletConnectPolkadotTransaction.swift in Sources */, FA38C99B275F384E005C5577 /* ChainOptionsViewModel.swift in Sources */, + 84CD3570252620FB0081BC0B /* CryptoType+Extrinsic.swift in Sources */, FA85373627EC874500918A1E /* InactiveBondAlertConfig.swift in Sources */, FADB9DB529D551A100303F7D /* SoraRewardCalculatorService.swift in Sources */, + FAD067BE2C2044B10050291F /* AssetManagementViewModelFactory.swift in Sources */, 843910BB253F021E00E3C217 /* WalletStakingChanged.swift in Sources */, 84EBC55F24F71D6A00459D15 /* UITableViewCell+ReorderColor.swift in Sources */, F43F934B26D76E8E00A6B529 /* AnalyticsRewardsBaseView.swift in Sources */, @@ -16191,6 +16597,7 @@ FA7254282AC2E48500EC47A6 /* JSONRPCError+Fearless.swift in Sources */, FA93A3182836543B0021330F /* ValidatorListFilterRelaychainViewModelFactory.swift in Sources */, 8490141124A92F6D008F705E /* OnboardingMainViewController.swift in Sources */, + FAD067D02C20453E0050291F /* LegacyEraStakersFetching.swift in Sources */, 842349C52624E98C0066ACFE /* MultiAddress+Query.swift in Sources */, 84155DED2539817200A27058 /* ApplicationService.swift in Sources */, FA169FAB28BCBAF000E8D2DC /* PoolStakingAccountUpdatingService.swift in Sources */, @@ -16209,6 +16616,7 @@ FA389B362840CBD700FF16E9 /* ValidatorSearchParachainViewModelState.swift in Sources */, FAF5E9DC27E46DAA005A3448 /* RootViewController.swift in Sources */, C6267BBA28D0A18D001E31BF /* AmountInputViewV2.swift in Sources */, + FAD067C12C2044B10050291F /* AssetManagementRouter.swift in Sources */, FA6262382AC2E35A005D3D95 /* WalletConnectConfirmationViewLayout.swift in Sources */, 848FFE9025E6CF4300652AA5 /* StorageKeyEncodingOperation.swift in Sources */, 075C647028098AFB00A55094 /* EthereumConstants.swift in Sources */, @@ -16216,6 +16624,7 @@ FAC0BBDF291D0EB000E6F106 /* SelectAssetRouter.swift in Sources */, FAD646CA284DFE4D007CCB92 /* StakingBondMoreRelaychainStrategy.swift in Sources */, 8443FDB6255540570092893D /* ExportMnemonicData.swift in Sources */, + FAD067AD2C2044810050291F /* ErasStakersPagedKey.swift in Sources */, 84893C0724DA890F008F6A3F /* CommonError.swift in Sources */, 849DEC6125EE13CE00C64C19 /* AddressOptionsPresentable.swift in Sources */, FAAA29272B8DCE3E0089AFE6 /* MultipleStorageResponseValueExtractor.swift in Sources */, @@ -16321,6 +16730,7 @@ AEF50586261EE6230098574D /* PurchaseProviderPickerTableViewCell.swift in Sources */, FA4B92AE2844D0E60003BCEF /* SelectCurrencyCellViewModel.swift in Sources */, 842876AD24AE049B00D91AD8 /* SelectionSubtitleTableViewCell.swift in Sources */, + FAD067D12C20453E0050291F /* DefaultEraStakersFetching.swift in Sources */, FA15BC112823AFE10037C023 /* ParachainStakingLocalSubscriptionHandler.swift in Sources */, FAD646C2284DD2CF007CCB92 /* StakingBalanceRelaychainStrategy.swift in Sources */, FAF5E9D827E46D77005A3448 /* AppVersion.swift in Sources */, @@ -16345,7 +16755,6 @@ 8406B5AF26FBE7EF00635B61 /* SelectionIconDetailsTableViewCell.swift in Sources */, FA256A23274CE7D600875A53 /* MoonbeamAgreeRemarkInfo.swift in Sources */, 849014BE24AA87E4008F705E /* PinSetupPresenter.swift in Sources */, - FAFFAE7F29AC84B10074AF1F /* GraphQLResponse.swift in Sources */, 849ABE63262785F200011A2A /* ControllerMapper.swift in Sources */, FAC0BBD9291D0EB000E6F106 /* SendViewController.swift in Sources */, FAA0139D28DA131B000A5230 /* StakingBondMorePoolViewModelState.swift in Sources */, @@ -16358,6 +16767,7 @@ 84D97EC1251FEE1E00F07405 /* WalletAssetId+Display.swift in Sources */, 076D9D3F293E367C002762E3 /* PolkaswapDex.swift in Sources */, 849244922514EDE800477C1B /* SelectableViewModel.swift in Sources */, + FA6ECE742BF49C0C00481B2B /* LiquidityPoolDetailsViewModel.swift in Sources */, 84CFF1E826526FBC00DB7CF7 /* StakingBondMoreViewFactory.swift in Sources */, FA38C9672758764B005C5577 /* VerticalContentButton.swift in Sources */, 8490147524A94A37008F705E /* RootWireframe.swift in Sources */, @@ -16376,7 +16786,6 @@ 84FD3DB92540F70400A234E3 /* TransactionHistoryItem+Extrinsic.swift in Sources */, 84F6B6432619A8480038F10D /* SubscanConcreteExtrinsicsData.swift in Sources */, FAD429212A865680001D6A16 /* WalletNamePresenter.swift in Sources */, - C61566852930A07900391BF3 /* QRCreationOperation.swift in Sources */, 844EFB65265FD61D0090ACB1 /* CrowdloanContributeConfirmViewModel.swift in Sources */, FAADC1B72926597400DA9903 /* ScanQRViewLayout.swift in Sources */, AEE5FAFF26415E0C002B8FDC /* StakingRebondSetupPresenter.swift in Sources */, @@ -16400,6 +16809,7 @@ 849842FE26592C2B006BBB9F /* StatusSectionView.swift in Sources */, F42D125F26C1B14D00E59214 /* AnalyticsValidatorsViewModelFactory.swift in Sources */, FAFFAE9329AC84B10074AF1F /* GiantsquidBond.swift in Sources */, + FA2222912BD239500031DE04 /* SoraSubqueryPriceResponse.swift in Sources */, FAD4292A2A865680001D6A16 /* BackupWalletImportedViewController.swift in Sources */, 8461CC7F26BBFEEA007460E4 /* ExtrinsicEraOperationFactory.swift in Sources */, FA6262622AC2E35A005D3D95 /* RawDataViewLayout.swift in Sources */, @@ -16423,7 +16833,6 @@ 841AAC2F26F73E0C00F0A25E /* LocalStorageKeyFactory.swift in Sources */, FACD429F2A5BE811009975AA /* StorageMigrator.swift in Sources */, FAFFAE7429AC84B10074AF1F /* SubqueryLiquidity.swift in Sources */, - 0739FD2C2BFB4A71009ADD7C /* EraStakersFetching.swift in Sources */, C6264C3C279B008600FCA0DB /* WalletDetailsWireframe.swift in Sources */, 8461CC8A26BD2F07007460E4 /* RuntimeProviderPool.swift in Sources */, F4AE12A1268DD69B0097D1C7 /* MnemonicTextNormalizer.swift in Sources */, @@ -16436,17 +16845,16 @@ FA99425828053C8800D771E5 /* SelectExportAccountAssembly.swift in Sources */, AEF7404E25E6DC9400407D41 /* RewardCalculatorEngine.swift in Sources */, FA7A4C7F2A1F937A0051FB4D /* ParachainRewardCalculatorEngine.swift in Sources */, - 070179712BCA3D4F00908C83 /* AssetManagementViewModel.swift in Sources */, 07DFA4462897EE370035A8AB /* WalletsManagmentViewModelFactory.swift in Sources */, 07D05E4A28EEFF2F00B66C70 /* SelectValidatorsStartPoolStrategy.swift in Sources */, FAA0137E28DA12F0000A5230 /* StakingRedeemPoolViewModelFactory.swift in Sources */, FAFFAE8529AC84B10074AF1F /* SubqueryRewardOrSlash.swift in Sources */, 84CA68D926BE9E7F003B9453 /* SpecVersionSubscription.swift in Sources */, 84C74363251E4C2F009576C6 /* DummySigner.swift in Sources */, + FA1D02042BBE71F2005B7071 /* TokenPairIconsView.swift in Sources */, 07AC51132AD8040C000970B8 /* XorlessTransfer.swift in Sources */, 84BEE22D2564765F00D05EB3 /* UIAlertViewController+Account.swift in Sources */, FA8FD1902AFBA34700354482 /* AssetNetworksViewModelFactory.swift in Sources */, - 074D832D2BCA490900AD1336 /* UIImage+Monochrome.swift in Sources */, FA99C936283B76E3007B1F83 /* SelectValidatorsConfirmRelaychainExistingViewModelState.swift in Sources */, FA93A2EE2833B1110021330F /* RecommendedValidatorListParachainViewModelState.swift in Sources */, 8454C26A2632B8CE00657DAD /* BalanceDepositEvent.swift in Sources */, @@ -16472,6 +16880,7 @@ FA7336E22A0E3B880096A291 /* ResponseDecoder.swift in Sources */, 84100F3626A6069200A5054E /* IconTitleValueView.swift in Sources */, 842876AB24AE049B00D91AD8 /* SelectionItemViewProtocol.swift in Sources */, + FA09AD372C37AF9200BE0B9C /* SubstrateTransactionObserver.swift in Sources */, FA2FC82528B380C500CC0A42 /* StakingPoolMember.swift in Sources */, FA584C862AB30ACE00F6F020 /* AlchemyNftMediaInfo.swift in Sources */, 8472C5AF265CF9C500E2481B /* StakingRewardDestConfirmViewLayout.swift in Sources */, @@ -16507,7 +16916,6 @@ FAD4290C2A86567F001D6A16 /* BannersProtocols.swift in Sources */, 84D2F45F25EF0599008B914D /* RecommendedValidatorCell.swift in Sources */, FAD429222A865680001D6A16 /* BackupWalletViewLayout.swift in Sources */, - 074D833B2BCAAE7C00AD1336 /* Requests.swift in Sources */, 8490151324AB8A3A008F705E /* WalletEmptyStateDataSource.swift in Sources */, 84243095265B1888003E07EC /* CrowdloanMetadata.swift in Sources */, 84CFF1ED26526FBC00DB7CF7 /* StakingBondMoreConfirmationWireframe.swift in Sources */, @@ -16555,6 +16963,7 @@ 84DA3B1424C6D7C700B5E27F /* RuntimeDispatchInfo.swift in Sources */, F4D96B6C2637EB1300B23D3D /* StakingBalanceActionsWidgetViewModel.swift in Sources */, FA8F6386298253ED004B8CD4 /* AddConnectionError.swift in Sources */, + FA6ECE762BF49D3D00481B2B /* LiquidityPoolDetailsViewModelFactory.swift in Sources */, 84A8FD8E265FDA76002ADB58 /* CrowdloanContributionConfirmData.swift in Sources */, 8428768B24AE046300D91AD8 /* AboutViewFactory.swift in Sources */, FAFFAEA229AC84D30074AF1F /* HexColorConverter.swift in Sources */, @@ -16570,9 +16979,9 @@ 843461CB26E2590200DCE0CD /* SubscanHistoryOperationFactory.swift in Sources */, FAD429032A86567F001D6A16 /* BackupCreatePasswordAssembly.swift in Sources */, 84CFF1F226526FBC00DB7CF7 /* StakingBondMoreConfirmationVC.swift in Sources */, + FAD067C32C2044B10050291F /* AssetManagementViewController.swift in Sources */, 84786E1F25FA6C390089DFF7 /* CDStashItem+CoreDataCodable.swift in Sources */, 840882B02514024800177E20 /* SelectedConnectionChanged.swift in Sources */, - 0739FD2D2BFB4A71009ADD7C /* DefaultEraStakersFetching.swift in Sources */, 84FD3DB72540EF0700A234E3 /* TransactionSubscription.swift in Sources */, FA7741E02B6A350200358315 /* StakingRewardsFetcherAssembly.swift in Sources */, 84C3F7832602086100D47501 /* StakingViewState.swift in Sources */, @@ -16592,16 +17001,15 @@ FAD429202A865680001D6A16 /* WalletNameProtocols.swift in Sources */, FA7741DE2B6A350200358315 /* StakingRewardFetcher.swift in Sources */, 84452F5825D5C30600F47EC5 /* FilesRepository.swift in Sources */, + FAD067A72C2044490050291F /* SubstrateDataModel.xcdatamodeld in Sources */, FAFFAE7C29AC84B10074AF1F /* KmmCallCodingPath.swift in Sources */, FA2FC84128B3879900CC0A42 /* InsettedLabel.swift in Sources */, FAADC1AD29261F7000DA9903 /* PoolRolesConfirmRouter.swift in Sources */, F4871DF326D63E8700D27F23 /* AnalyticsRewardDetailsViewModelFactory.swift in Sources */, - 070179762BCA3D4F00908C83 /* AssetManagementPresenter.swift in Sources */, FA9A8F1F2A72573C008FA99F /* AlchemyHistory.swift in Sources */, 84873B0426029B75000A83EE /* StakingEstimationViewModel.swift in Sources */, AE6F7FE32685E812002BBC3E /* ValidatorListFilterViewLayout.swift in Sources */, FA169FA928BCBA1F00E8D2DC /* PoolStakingAccountSubscription.swift in Sources */, - 075A2F0A2BF722F300CE6F24 /* ExternalApiExplorerType.swift in Sources */, 84038FF026FFBE0600C73F3F /* JsonLocalStorageSubscriber.swift in Sources */, 84BEE0F02562897100D05EB3 /* AccountImportJsonFactory.swift in Sources */, 849014DF24AA8F60008F705E /* MainTabBarViewController.swift in Sources */, @@ -16615,8 +17023,8 @@ 84C6801824D7053B00006BF5 /* BorderedSubtitleActionView.swift in Sources */, 84A2C90C24E192F50020D3B7 /* ShakeAnimator.swift in Sources */, FA6262352AC2E35A005D3D95 /* WalletConnectConfirmationInputData.swift in Sources */, + 84452F2B25D5B84200F47EC5 /* RuntimeRegistryServiceProtocol.swift in Sources */, FA7336DF2A0E3B880096A291 /* NetworkRequestType.swift in Sources */, - 070CDD752ACAE04100F3F20A /* SoraQRInfo.swift in Sources */, FACD42992A5BE811009975AA /* SubstrateStorageMigrator+Sync.swift in Sources */, FAA0132E28DA12B6000A5230 /* StakingPoolNetworkInfoViewModel.swift in Sources */, FAADC1AA29261F7000DA9903 /* PoolRolesConfirmInteractor.swift in Sources */, @@ -16638,7 +17046,6 @@ 84B64E412704569D00914E88 /* RelaychainStakingLocalSubscriptionHandler.swift in Sources */, 848FFE9525E6DF2200652AA5 /* PagedKeysRequest.swift in Sources */, FAABC4732845C7F4002CF40E /* ValidatorListFilterParachainViewModelState.swift in Sources */, - 8428766B24ADF51D00D91AD8 /* UIViewController.swift in Sources */, FAAC292C2ADCF3BB00063962 /* WalletConnectConfirmationCoordinator.swift in Sources */, 84F30E9725FD3C5300039D09 /* EventEmittingStorageSubscription.swift in Sources */, AEAC68FE26EA3C2A00346599 /* CoingeckoPriceSource.swift in Sources */, @@ -16671,7 +17078,6 @@ 84C6801A24D75E2A00006BF5 /* BorderedSubtitleActionView+Inspectable.swift in Sources */, FA256A34274CE7D600875A53 /* MoonbeamJSONEncoder.swift in Sources */, FA6A6DBD27B60A84007D1A20 /* ChainNodeModelMapper.swift in Sources */, - FAAB998D27A7C79D00CD1A3B /* QRParser.swift in Sources */, FA93A2DB28323CCD0021330F /* CustomValidatorListParachainStrategy.swift in Sources */, 8430AAD42602285B005B1066 /* StakingStateCommonData.swift in Sources */, F4F2296C260DBDCE00ACFDB8 /* StakingPayoutLabelTableCell.swift in Sources */, @@ -16679,6 +17085,7 @@ 844CB57826FA702700396E13 /* CrowdloansViewInfo.swift in Sources */, AEACD5F9265E94AB00A09892 /* StatusViewModel.swift in Sources */, 84CCBFBC2509709500180F4F /* UIBarButtonItem+Style.swift in Sources */, + FA1D02092BBE74B7005B7071 /* AvailableLiquidityPoolsListInteractor.swift in Sources */, 8449660A25E15ECA00F2E9F5 /* RewardDestinationViewModel.swift in Sources */, FA2E9BBB27A14BB00023FAD2 /* WalletTransactionHistoryFilters.swift in Sources */, 847DD8DC26034B99003DE053 /* LocalizableViewProtocol.swift in Sources */, @@ -16712,7 +17119,9 @@ FA00488F282CC7710032FF49 /* SelectValidatorsStartFlow.swift in Sources */, FAA0137828DA12E3000A5230 /* StakingRedeemConfirmation]PoolStrategy.swift in Sources */, FACD42B92A5BE90C009975AA /* InflationRewardCalculatorService.swift in Sources */, + 07ED2EB92C341A0100FF7500 /* NodeApiKeyInjector.swift in Sources */, 849014DD24AA8F60008F705E /* MainTabBarViewFactory.swift in Sources */, + FA1D51D72BCFD445001353E7 /* LiquidityPools+ViewModel.swift in Sources */, FA9942712805524200D771E5 /* BalanceBuilder.swift in Sources */, AE7129C12608CAE7000AA3F5 /* NetworkStakingInfo.swift in Sources */, C6267B8D28BDF6A5001E31BF /* ChainAssetListAssembly.swift in Sources */, @@ -16723,8 +17132,6 @@ F4113B3F260C77FF00DF4DBA /* StakingRewardPayoutsViewLayout.swift in Sources */, FA17B4BA27E873E9006E0735 /* WarningAlertPresentAnimator.swift in Sources */, FA584C782AB2BCD500F6F020 /* UniversalMediaView.swift in Sources */, - 070CDD792ACBE19100F3F20A /* BokoloCashQRInfo.swift in Sources */, - C66E68CE2BFC119300A14759 /* OnboardingConfigVersionResolver.swift in Sources */, AEA0C8A8267B6B3200F9666F /* SelectedValidatorListPresenter.swift in Sources */, FAFFAE9529AC84B10074AF1F /* GiantsquidTransfer.swift in Sources */, FA256985274CE5A500875A53 /* BalanceLocks+Sort.swift in Sources */, @@ -16784,6 +17191,7 @@ FA7336E52A0E3B880096A291 /* NetworkClient.swift in Sources */, C65A6592288E5CF400679D65 /* AccountInfoFetching.swift in Sources */, FA256A20274CE7D600875A53 /* AstarBonusService.swift in Sources */, + FAD067BD2C2044B10050291F /* AssetManagementViewModel.swift in Sources */, 078E34C128058B9D00DF187A /* DocumentType.swift in Sources */, 8494D8702525321700614D8F /* SubscanDefinitions.swift in Sources */, 84DB9E902640A48E00F23DD3 /* StakingRedeemViewModel.swift in Sources */, @@ -16818,6 +17226,7 @@ FA6C176429935DC800A55254 /* SubqueryRewardOperationFactory.swift in Sources */, AE4A71D42607B1440017C663 /* NetworkStakingInfoViewModel.swift in Sources */, FAADC1B82926597400DA9903 /* ScanQRInteractor.swift in Sources */, + FAD067BF2C2044B10050291F /* AssetManagementInteractor.swift in Sources */, 8439398A2636E8840087658D /* YourValidatorListViewLayout.swift in Sources */, FA93A3012834C8240021330F /* ValidatorInfoRelaychainStrategy.swift in Sources */, 84378775264D2C6600E6AFD2 /* UsernameSetupModel.swift in Sources */, @@ -16851,7 +17260,6 @@ FA8ED43628FD983A00EBB712 /* YourValidatorListRelaychainStrategy.swift in Sources */, AE6F7FE62685F2C3002BBC3E /* ValidatorListFilterViewModel.swift in Sources */, C6264C322799DB8C00FCA0DB /* WalletDetailsViewController.swift in Sources */, - 0701797B2BCA3D4F00908C83 /* AssetManagementViewLayout.swift in Sources */, FA3067202B621144006A0BA5 /* TokenLock.swift in Sources */, F40966F626B299FC008CD244 /* SubqueryStakeSource.swift in Sources */, C69E89462B0C5F7D003663BA /* MainNftContainerStateHolder.swift in Sources */, @@ -16883,6 +17291,7 @@ FAAA292A2B8DCE3E0089AFE6 /* SingleStorageResponseValueExtractor.swift in Sources */, FAA0139828DA1312000A5230 /* StakingBondMoreConfirmationPoolStrategy.swift in Sources */, 84CFF1E526526FBC00DB7CF7 /* StakingBondMoreViewController.swift in Sources */, + FA1D02012BBE713D005B7071 /* LiquidityPoolsListViewController.swift in Sources */, 84E1CD11260DCD44001E81B5 /* SwitchAccount+AccountImportWireframe.swift in Sources */, 8401AEC72642A71D000B03E3 /* StakingRebondConfirmationPresenter.swift in Sources */, FAC6CDA12BA80CB10013A17E /* WalletTransactionType.swift in Sources */, @@ -16905,7 +17314,6 @@ FA2E9BB727A13E890023FAD2 /* FiltersViewState.swift in Sources */, FA4B92B52844D0E60003BCEF /* SelectCurrencyPresenter.swift in Sources */, FAAF946C2A0CFF90009A4BA5 /* Array+Duplicates.swift in Sources */, - 070179772BCA3D4F00908C83 /* AssetManagementViewController.swift in Sources */, 074EB7AD290B9F64000A2A6A /* AddressCopiedEvent.swift in Sources */, FAB16A312A9C9BBF00E71F43 /* NftCollectionCell.swift in Sources */, FAFFAE8C29AC84B10074AF1F /* SubqueryDelegatorHistoryNodes.swift in Sources */, @@ -16915,6 +17323,7 @@ 842876AA24AE049B00D91AD8 /* SelectionTitleTableViewCell.swift in Sources */, FAD646D0284F104B007CCB92 /* StakingBondMoreConfirmationRelaychainStrategy.swift in Sources */, 84CA68DD26BEA60A003B9453 /* ConnectionFactory.swift in Sources */, + FAD067D32C20550B0050291F /* UIImageView+Shimmered.swift in Sources */, FA37AE232859A985001DCA96 /* StakingBondMoreParachainStrategy.swift in Sources */, F40966B626B297D6008CD244 /* AnalyticsRewardsPresenter.swift in Sources */, 848EAEB82659859600676CEA /* CrowdloansViewModelFactory.swift in Sources */, @@ -16937,6 +17346,7 @@ FA6262582AC2E35A005D3D95 /* MultiSelectNetworksRouter.swift in Sources */, 84C6800E24D6ECE800006BF5 /* ExpandableActionControl.swift in Sources */, 8490148424AA27C1008F705E /* OperationManagerFacade.swift in Sources */, + FAD067C72C2044B10050291F /* AssetManagementViewLayout.swift in Sources */, 2AD0A19025D3D1E100312428 /* GitHubPhishingServiceFactory.swift in Sources */, FA14AE892B0785670066CADF /* SoraSubsquidHistoryResponse.swift in Sources */, FAAA29572B8DED770089AFE6 /* MapKeyType.swift in Sources */, @@ -16988,7 +17398,6 @@ AEA0C8C6268131C500F9666F /* InitiatedBondingSelectedValidatorsListWireframe.swift in Sources */, 84F2FEFA25E797E8008338D5 /* StorageRequestFactory.swift in Sources */, 07F67CA32ACFC4910044047D /* WalletConnectCoordinator.swift in Sources */, - 0701797D2BCA3D6100908C83 /* WalletAssetsObserver.swift in Sources */, 8468B87424F63D4B00B76BC6 /* AddAccount+AccountConfirmWireframe.swift in Sources */, FA6262552AC2E35A005D3D95 /* MultiSelectNetworksTableCell.swift in Sources */, FA2FC82828B380FD00CC0A42 /* RuntimeCall+CallCodingPath.swift in Sources */, @@ -17081,6 +17490,7 @@ FA37AE452859E33E001DCA96 /* StakingRedeemParachainViewModelFactory.swift in Sources */, 84F30EE425FFAC0800039D09 /* StreamableProviderOptions+Substrate.swift in Sources */, FAF9C2A42AAF3FCC00A61D21 /* FeatureToggleService.swift in Sources */, + FAD067CB2C2044F00050291F /* OnboardingConfigVersionResolver.swift in Sources */, FAC0BBDA291D0EB000E6F106 /* SendRouter.swift in Sources */, FA2FC80D28B3807D00CC0A42 /* StakingPoolJoinConfirmRouter.swift in Sources */, 070B2C61289CFE0000F78F82 /* SelectedNetworkButton.swift in Sources */, @@ -17111,10 +17521,12 @@ 843910B4253EE52100E3C217 /* WalletBalanceChanged.swift in Sources */, 07B6BC7C28B875D800621864 /* UIControl.swift in Sources */, FA7336E92A0E3CCC0096A291 /* HTTPMethod.swift in Sources */, + FAD067C22C2044B10050291F /* AssetManagementPresenter.swift in Sources */, FA93A2FD2834AF930021330F /* ValidatorInfoParachainViewModelFactory.swift in Sources */, 84FAB0692542EBDE00319F74 /* SearchData+Contacts.swift in Sources */, FA7741DD2B6A350200358315 /* SubsquidStakingRewardsFetcher.swift in Sources */, 8428765924ADDE0200D91AD8 /* ProfileProtocol.swift in Sources */, + FAD067962C2043DC0050291F /* UIImage+Monochrome.swift in Sources */, FAD646C4284DD2DA007CCB92 /* StakingBalanceRelaychainViewModelState.swift in Sources */, 0702B355297948C8003519F5 /* SwapTransactionViewModel.swift in Sources */, FAA0131028DA1277000A5230 /* StakingBondMoreViewLayout.swift in Sources */, @@ -17140,6 +17552,7 @@ FA86442C27674A8600956D8E /* WalletTransactionHistoryViewState.swift in Sources */, AEB99798261310D5005C60A5 /* StoriesProgressBar.swift in Sources */, AEE5FB1626457AA9002B8FDC /* StakingRewardDestSetupPresenter.swift in Sources */, + FA887A452C107A1100CA720F /* LiquidityPoolSupplyConfirmViewModel.swift in Sources */, FA256987274CE5B700875A53 /* SHA256.swift in Sources */, 8468B86E24F63D1400B76BC6 /* AddAccount+OnboardingMainWireframe.swift in Sources */, FAA0137028DA12E3000A5230 /* StakingRedeemConfirmationParachainViewModelState.swift in Sources */, @@ -17148,6 +17561,7 @@ FAA013A328DA1328000A5230 /* TitleMultiValueViewModel.swift in Sources */, 84729741260A9C13009B86D0 /* DisplayAddress.swift in Sources */, 84F4386125D9A83100AEDA56 /* TimeInterval+Time.swift in Sources */, + FA9610202C5205B200C3C750 /* UIViewController.swift in Sources */, FA99425A28053C8800D771E5 /* SelectExportAccountProtocols.swift in Sources */, 844EFB5F265FCE180090ACB1 /* CrowdloanContributionInteractor.swift in Sources */, FAA0138F28DA1303000A5230 /* StakingPayoutConfirmationPoolViewModelFactory.swift in Sources */, @@ -17187,7 +17601,6 @@ 84D8F15524D80CA100AF43E9 /* ModalPickerViewController.swift in Sources */, FA2569A1274CE66100875A53 /* SubscanMemoData.swift in Sources */, 84F43BAA25DEB75000AEDA56 /* StakingMainViewModel.swift in Sources */, - FAADC1C129265A7900DA9903 /* QRInfoMatcher.swift in Sources */, 84DD5F35263D86EF00425ACF /* AccountFetching.swift in Sources */, 849014A624AA801B008F705E /* TextSharingSource.swift in Sources */, 8490152524ABCBF3008F705E /* AmountFormatterFactory.swift in Sources */, @@ -17206,6 +17619,7 @@ 8444D13F267133CF00AF6D8C /* CrowdloanAddMemo.swift in Sources */, 84EBC54324F656D100459D15 /* SortDescriptor+Storage.swift in Sources */, 845532D02684690D00C2645D /* ParachainSlotLease.swift in Sources */, + FA22228F2BD237CF0031DE04 /* SoraSubqueryPriceFetcher.swift in Sources */, 84CD82B3263C30BC001A6F01 /* SubstrateProviderSubscriptionHandler.swift in Sources */, 84DB4E1E25E93B1700A6DF41 /* Identity.swift in Sources */, F47F5A822626FDB9009BCFF4 /* StakingPayoutViewModel.swift in Sources */, @@ -17232,6 +17646,7 @@ FAD429262A865680001D6A16 /* BackupWalletViewModelFactory.swift in Sources */, 849ABE6D2627949E00011A2A /* BatchMapper.swift in Sources */, FAFFAE7E29AC84B10074AF1F /* SubqueryDelegatorHistoryData.swift in Sources */, + FAD0679E2C2044320050291F /* AssetManagementMigrator.swift in Sources */, FAF9C2A52AAF3FCC00A61D21 /* FeatureToggleConfig.swift in Sources */, FAE5F62F27B2383E00F13206 /* AddCustomNodeViewState.swift in Sources */, C6CA203D2B06C0D9001503C2 /* NftFiltersInteractor.swift in Sources */, @@ -17247,6 +17662,7 @@ FA2FC82D28B3816D00CC0A42 /* StorageKeyDataExtractor.swift in Sources */, 849013DD24A927E2008F705E /* KeystoreExtensions.swift in Sources */, FAD429062A86567F001D6A16 /* BackupCreatePasswordPresenter.swift in Sources */, + FAD0679A2C2043FC0050291F /* ChainConnectionVisibilityHelper.swift in Sources */, FAD0068427EA255900C97E09 /* AboutTableViewCell.swift in Sources */, FAE39AF32A9E1A4F0011A9D6 /* ChainsSetupCompleted.swift in Sources */, AE20602C2636EA5800357578 /* MoonPayKeys.swift in Sources */, @@ -17255,9 +17671,11 @@ FA851FF127917494004F5979 /* WalletTransactionDetailsViewState.swift in Sources */, FAEDC13D2820F59100E6582C /* StakingAmountViewModel.swift in Sources */, FA256A2F274CE7D600875A53 /* MoonbeamAgreeRemarkRequest.swift in Sources */, + FAD067AE2C2044810050291F /* ErasStakersOverviewKey.swift in Sources */, FA9A8F1A2A72573C008FA99F /* AlchemyEndpoint.swift in Sources */, FA62626D2AC2E35A005D3D95 /* WalletConnectProposalViewLayout.swift in Sources */, F40966CC26B297D6008CD244 /* AnalyticsStakeWireframe.swift in Sources */, + FAD067C52C2044B10050291F /* AssetManagementTableHeaderView.swift in Sources */, AE9EF27D260B53130026910A /* StoriesViewFactory.swift in Sources */, FAD428FC2A86567F001D6A16 /* BackupRiskWarningsInteractor.swift in Sources */, 8428765F24ADE0BB00D91AD8 /* UserSettings.swift in Sources */, @@ -17290,8 +17708,8 @@ 845C407D2702812E00BFA50B /* StakingAccountUpdatingService.swift in Sources */, FAC6CD9F2BA80AB70013A17E /* WalletLanguage.swift in Sources */, 84DA3B1924C8200E00B5E27F /* ConnectionItem+Default.swift in Sources */, - 070179792BCA3D4F00908C83 /* AssetManagementTableHeaderView.swift in Sources */, FAD429072A86567F001D6A16 /* BackupCreatePasswordProtocols.swift in Sources */, + FA887A492C1C19DB00CA720F /* WarningView.swift in Sources */, 84D331AF2519E8080078D044 /* TriangularedView+Style.swift in Sources */, 84C74365251E4D60009576C6 /* SigningWrapperProtocol.swift in Sources */, 844CB56A26F9C57D00396E13 /* WalletLocalStorageSubscriber.swift in Sources */, @@ -17352,7 +17770,6 @@ FAD4292E2A865680001D6A16 /* BackupWalletImportedProtocols.swift in Sources */, 84BAB6102642C286007782D0 /* SelectedRebondVariant.swift in Sources */, 84F5107C263C0C11005D15AE /* AnyProviderCleaning.swift in Sources */, - C615668129309D3900391BF3 /* QRService.swift in Sources */, FAA0134628DA12CD000A5230 /* StakingUnbondSetupPoolViewModelState.swift in Sources */, 84BEE22325646AC000D05EB3 /* SelectedUsernameChanged.swift in Sources */, 8467FD4124ED3C72005D486C /* AlignableContentControl.swift in Sources */, @@ -17411,7 +17828,10 @@ FA9A8F092A6FB8F9008FA99F /* AssetTransactionData+EtherscanHistory.swift in Sources */, FA93A3062834FBF60021330F /* ValidatorSearchFlow.swift in Sources */, 84E6D57C262E2CE8000EA3F5 /* OperationCombiningService.swift in Sources */, + FA1D01FA2BBE713D005B7071 /* LiquidityPoolListViewModel.swift in Sources */, 0726FFAD2AC4399C00336D76 /* WalletConnectPolkadotParser.swift in Sources */, + FA2222942BD2726F0031DE04 /* SkeletonLabel.swift in Sources */, + FA22228D2BD237910031DE04 /* SubqueryPriceFetcher.swift in Sources */, FAED6F4427DA19C70051B337 /* AccountInfoSubscriptionAdapter.swift in Sources */, FAD646CC284DFE5A007CCB92 /* StakingBondMoreRelaychainViewModelState.swift in Sources */, 846C372E26B199D10098F303 /* StakingDurationOperationFactory.swift in Sources */, @@ -17424,7 +17844,6 @@ AE805FC526B3DF8B00007CE9 /* ValidatorInfoInteractorBase.swift in Sources */, FAF9C29E2AAEED9600A61D21 /* TitleCopyableValueView.swift in Sources */, FA5137BA29AC76EB00560EBA /* SubsquidHistoryOperationFactory.swift in Sources */, - FACE6C632BBAC3B100643CEF /* SubstrateDataModel.xcdatamodeld in Sources */, F4D96B712637FE8600B23D3D /* StakingBalanceWidgetViewModel.swift in Sources */, FA37AE332859C171001DCA96 /* ScheduleDelegatorBondLessCall.swift in Sources */, AEE5FB0526415E5D002B8FDC /* StakingRebondSetupViewFactory.swift in Sources */, @@ -17553,7 +17972,6 @@ FAFFAE8829AC84B10074AF1F /* SubqueryExtrinsic.swift in Sources */, 8472C5B2265CF9C500E2481B /* StakingRewardDestConfirmInteractor.swift in Sources */, FACD42B42A5BE8E1009975AA /* CheckPincodeWireframe.swift in Sources */, - 070179732BCA3D4F00908C83 /* AssetManagementInteractor.swift in Sources */, 846CA77A27099B1E0011124C /* StakingAnalyticsLocalSubscriptionFactory.swift in Sources */, FA62626E2AC2E35A005D3D95 /* WalletConnectProposalWalletsTableCell.swift in Sources */, FAADC1B62926597400DA9903 /* ScanQRAssembly.swift in Sources */, @@ -17565,6 +17983,8 @@ FA34EED52B98723C0042E73E /* OnboardingStartProtocols.swift in Sources */, AE9EF264260A82B80026910A /* StoriesWireframe.swift in Sources */, 848EAEB02659310A00676CEA /* CrowdloanStatus.swift in Sources */, + FA1D020D2BBE7690005B7071 /* UserLiquidityPoolsListInteractor.swift in Sources */, + FAD0679C2C2044170050291F /* ExternalApiExplorerType.swift in Sources */, 841185E7263F3B6D00E8A8B6 /* HintView.swift in Sources */, 8494D87C252537E500614D8F /* SubscanError.swift in Sources */, 07DFA452289A5C870035A8AB /* WalletsManagmentCellViewModel.swift in Sources */, @@ -17606,7 +18026,6 @@ AEF50556261A04AD0098574D /* MoonpayProvider.swift in Sources */, FAF9C2962AAADE3300A61D21 /* DeprecatedControllerStashAccountCheckService.swift in Sources */, FAA0137928DA12E3000A5230 /* StakingRedeemConfirmationPoolViewModelState.swift in Sources */, - 070179742BCA3D4F00908C83 /* AssetManagementAssembly.swift in Sources */, 84FB29942639ABD700BE0FCD /* YourValidatorList+SelectionStart.swift in Sources */, 84DB9E8A26409E8200F23DD3 /* StakingRedeemLayout.swift in Sources */, 84644A2B2567222A004EAA4B /* TriangularedBlurButton.swift in Sources */, @@ -17619,7 +18038,11 @@ C67E781927B3AC350053346B /* CheckPincodeViewController.swift in Sources */, FA5137B029AC6F2F00560EBA /* PolkaswapDisclaimerProtocols.swift in Sources */, FACD42972A5BE811009975AA /* SettingsMigrator.swift in Sources */, + FA1D01FF2BBE713D005B7071 /* LiquidityPoolsListAssembly.swift in Sources */, 84DED3EF26661CC600A153BB /* CrowdloanFlow.swift in Sources */, + FA1D01FB2BBE713D005B7071 /* LiquidityPoolsListViewLayout.swift in Sources */, + 84452F4E25D5BB1C00F47EC5 /* RuntimeCoderFactory.swift in Sources */, + FA1D51DC2BCFE38D001353E7 /* SubqueryFiatInfoOperation.swift in Sources */, 84452A6025D037AE00F47EC5 /* ChainStorage+Decodable.swift in Sources */, F4F65C3D26D8B9DD002EE838 /* FWYAxisChartFormatter.swift in Sources */, 847C963525534E41002D288F /* UIFactory.swift in Sources */, @@ -17657,6 +18080,7 @@ FAFFAE9629AC84B10074AF1F /* GiantsquidResponse.swift in Sources */, 84DAC198268D3DD9002D0DF4 /* SNAddressType.swift in Sources */, 846B32A126DCDB7300250E89 /* SubqueryRewardSource.swift in Sources */, + 8436E94626C85405003D4EA7 /* RuntimeSnapshot.swift in Sources */, 847C965425536199002D288F /* ExportRestoreJsonProtocols.swift in Sources */, FAA0139028DA1303000A5230 /* StakingPayoutConfirmationPoolViewModelState.swift in Sources */, FA8800662B31A316000AE5EB /* StakingAccountSubscription.swift in Sources */, @@ -17685,6 +18109,7 @@ 845B822926F0BB6700D25C72 /* CrowdloanChainSettings.swift in Sources */, AEE5FB072641669B002B8FDC /* StakingRebondSetupLayout.swift in Sources */, FA2FC85D28B38A1400CC0A42 /* StakingAssetSelectionPresenter.swift in Sources */, + FA1D01FD2BBE713D005B7071 /* LiquidityPoolsListProtocols.swift in Sources */, FA2FC81428B3807D00CC0A42 /* StakingPoolStartViewModel.swift in Sources */, 847119C0262EF3BD00716580 /* PayoutValidatorsFactoryProtocol.swift in Sources */, 075FC63528D9AB1600E25263 /* CommonInputViewV2.swift in Sources */, @@ -17740,6 +18165,7 @@ 84981CC32666D95F00C4C691 /* GradientButton+Style.swift in Sources */, C6992F10280836FA003BC769 /* AccountConfirmFlow.swift in Sources */, 845CB6FA26276326005F798B /* LongrunOperation.swift in Sources */, + FAD067C42C2044B10050291F /* AssetManagementTableCell.swift in Sources */, 84FB1F6D2526987D00E0242B /* TransactionHistoryContext.swift in Sources */, AE9EF269260A82C30026910A /* StoriesProtocols.swift in Sources */, F47BBD852631888C0087DA11 /* StakingBalanceActionsWidgetView.swift in Sources */, @@ -17747,7 +18173,6 @@ FACD42A32A5BE811009975AA /* SelectedLanguageMigrator.swift in Sources */, 2A66CF4F25D109780006E4C1 /* CDPhishingItem+CoreDataDecodable.swift in Sources */, FA2DF99B2A8C99AA0047F440 /* EtherscanNftResponseElement.swift in Sources */, - 070179752BCA3D4F00908C83 /* AssetManagementRouter.swift in Sources */, 8460517225536E3F00A1F0B4 /* ExportGenericViewModelBinder.swift in Sources */, C6264C38279AB09600FCA0DB /* WalletDetailsInteractor.swift in Sources */, 84A15489262888CA0050D557 /* IdentityOperationFactory.swift in Sources */, @@ -17769,11 +18194,14 @@ FA004891282CCA400032FF49 /* SelectValidatorsStartParachainStrategy.swift in Sources */, FAFFAEA129AC84D30074AF1F /* LinkDecorator.swift in Sources */, FA5137AD29AC6F2F00560EBA /* PolkaswapDisclaimerViewController.swift in Sources */, + FA887A472C107A4300CA720F /* LiquidityPoolSupplyConfirmViewModelFactory.swift in Sources */, 849632072555CE9D00B8E316 /* ExportSeedData.swift in Sources */, FAD428F52A86567F001D6A16 /* BackupPasswordProtocols.swift in Sources */, FACD429D2A5BE811009975AA /* MultiassetV9MigrationPolicy.swift in Sources */, FA88006A2B31A33E000AE5EB /* StakingAccountSubscriptionV14.swift in Sources */, + FAADF71229C47D10002B6D39 /* RuntimeSpecVersion.swift in Sources */, FAD428F42A86567F001D6A16 /* BackupPasswordPresenter.swift in Sources */, + FAD067C62C2044B10050291F /* AssetManagementProtocols.swift in Sources */, FA72543A2AC2E48500EC47A6 /* ABIElements.swift in Sources */, 848919DB26FB663D004DBAD5 /* CrowdloansChainViewModel.swift in Sources */, FAC6CDB12BA821B00013A17E /* WalletImageViewModelProtocol.swift in Sources */, @@ -17811,7 +18239,6 @@ FAF5E9D627E46D77005A3448 /* AppVersionError.swift in Sources */, F462B351260C7DBE0005AB01 /* StakingRewardHistoryTableCell.swift in Sources */, FA72543C2AC2E48500EC47A6 /* ABIParameterTypes.swift in Sources */, - FA99422A27FE927800D771E5 /* AssetModelMapper.swift in Sources */, AE89720825F12143008EC414 /* ValidatorInfoViewModel.swift in Sources */, FA864445276851CF00956D8E /* ContainerViewController.swift in Sources */, FA9A8F272A72579D008FA99F /* AlchemyTokenCategory.swift in Sources */, @@ -17837,8 +18264,10 @@ 84CFF1EC26526FBC00DB7CF7 /* StakingBondMoreConfirmRelaychainViewModelFactory.swift in Sources */, FAC0BBB2291D074500E6F106 /* RuntimeCallPath.swift in Sources */, FA6C176229935DC700A55254 /* SubsquidRewardOperationFactory.swift in Sources */, + FA1D01F92BBE713D005B7071 /* LiquidityPoolListCellModel.swift in Sources */, 84038FF626FFDF4E00C73F3F /* CrowdloanSharedState.swift in Sources */, FAAA29402B8DCED90089AFE6 /* NMapKeyEncodingWorker.swift in Sources */, + FA1D01FC2BBE713D005B7071 /* LiquidityPoolsListRouter.swift in Sources */, 054C4BCDEC29ED5F74A36E8B /* ExportMnemonicPresenter.swift in Sources */, 39218CF5AA701518BD3B0103 /* ExportMnemonicInteractor.swift in Sources */, F4F22967260DBC7200ACFDB8 /* StakingPayoutStatusTableCell.swift in Sources */, @@ -17867,10 +18296,10 @@ C89D156BA8B690E8E4DE19ED /* ExportSeedProtocols.swift in Sources */, 076D9D2E2939B780002762E3 /* PolkaswapOperationFactoryProtocol.swift in Sources */, FA74359D29C0736F0085A47E /* StorageWrapper.swift in Sources */, - 0739FD332BFB4B98009ADD7C /* ErasStakersPagedKey.swift in Sources */, 84B64E3F2704567700914E88 /* RelaychainStakingLocalStorageSubscriber.swift in Sources */, BD571417BD18C711B76E1D62 /* ExportSeedWireframe.swift in Sources */, 8463A73825E3AA47003B8160 /* AccountInfo.swift in Sources */, + FA53D8922C08510000173ADB /* LiquidityPoolSupplyViewModelFactory.swift in Sources */, ABA3D873BBECB7F4BD670872 /* ExportSeedPresenter.swift in Sources */, FA5DD0E3278EFE2500967047 /* WalletTransactionHistoryTableSectionHeader.swift in Sources */, FAA0134728DA12CD000A5230 /* StakingUnbondSetupPoolStrategy.swift in Sources */, @@ -17952,6 +18381,7 @@ FA9A8F222A72573C008FA99F /* AlchemyHistoryRequest.swift in Sources */, EC978E6C4FBF39BE9ED10C86 /* SelectValidatorsStartWireframe.swift in Sources */, FA2FC81828B3807D00CC0A42 /* StakingPoolStartRouter.swift in Sources */, + FAD067C92C2044D30050291F /* ChainAssetListViewLayout.swift in Sources */, FAC6CD942BA802840013A17E /* NumberFormatterFactoryProtocol.swift in Sources */, 0713098128C6F7BB002B17D0 /* CDScamInfo+CoreDataCodable.swift in Sources */, FA93A3162836542D0021330F /* ValidatorListFilterRelaychainViewModelState.swift in Sources */, @@ -17965,6 +18395,7 @@ FA38C995275E0A70005C5577 /* RemoteImageViewModelFactory.swift in Sources */, 07DFA46F289B8D8E0035A8AB /* EducationStoriesSlideView.swift in Sources */, 2C3124A5EBC1AD57C01EEA17 /* SelectValidatorsStartInteractor.swift in Sources */, + FAD067A92C20445F0050291F /* ChainAssetListBuilder.swift in Sources */, FAA0133F28DA12B6000A5230 /* StakingPoolManagementInteractor.swift in Sources */, FA8F63AB29825C90004B8CD4 /* AccountShareFactory.swift in Sources */, 84F6B6502619E1ED0038F10D /* Int+Operations.swift in Sources */, @@ -18000,6 +18431,7 @@ FA93A2EA2833B0F90021330F /* RecommendedValidatorListRelaychainViewModelFactory.swift in Sources */, 0678271BE1BA5BBC084F478A /* RecommendedValidatorListWireframe.swift in Sources */, F441BE0E263984DD0096B67B /* BondExtraCall.swift in Sources */, + FA8810D52BDCD19D0084CC4B /* UserLiquidityPoolsListViewModelFactory.swift in Sources */, BA7AEE82627CFC0AFD69B299 /* RecommendedValidatorListPresenter.swift in Sources */, FAAA29492B8DCF350089AFE6 /* AsyncStorageRequestFactoryDefault.swift in Sources */, 8472C5B3265CF9C500E2481B /* StakingRewardDestConfirmViewController.swift in Sources */, @@ -18010,12 +18442,12 @@ C7D77690E10875CF1856EBA1 /* StakingRewardPayoutsProtocols.swift in Sources */, FA936BCE286C41DF0059B97A /* StakingRebondConfirmationRelaychainStrategy.swift in Sources */, FA4B928F284493C60003BCEF /* DelegateCall.swift in Sources */, - 070CDD702ACACEDA00F3F20A /* QRMatcherProtocol.swift in Sources */, 2918DCAEB91F8276446873C8 /* StakingRewardPayoutsWireframe.swift in Sources */, AB5E2A2B4CC823E6F6515ADD /* StakingRewardPayoutsPresenter.swift in Sources */, 84100F3C26A60E4C00A5054E /* YourValidatorListWarningSectionView.swift in Sources */, FAADC1A729261F7000DA9903 /* PoolRolesConfirmViewModel.swift in Sources */, FAD429292A865680001D6A16 /* BackupWalletViewController.swift in Sources */, + FA054A9C2BCD1FAF007B8F6D /* AvailableLiquidityPoolsListViewModelFactory.swift in Sources */, FA2E9BB527A133A20023FAD2 /* SwitchFilterItem.swift in Sources */, FA2FC80928B3807C00CC0A42 /* StakingPoolJoinConfigInteractor.swift in Sources */, C648FFC828DC43A70072951B /* EmptyView.swift in Sources */, @@ -18056,7 +18488,6 @@ 5869563D0EA593FBD02C169C /* StakingPayoutConfirmationProtocols.swift in Sources */, FA28A9B229D2E451005AA42E /* MultiassetV9.xcmappingmodel in Sources */, A871B6ABACAE8A811010F792 /* StakingPayoutConfirmationWireframe.swift in Sources */, - 070179782BCA3D4F00908C83 /* AssetManagementTableCell.swift in Sources */, F4D6FF1326B3DDDF002313AF /* AnalyticsRewardsViewController.swift in Sources */, 1795E946F1E386442E96E2BC /* StakingPayoutConfirmationPresenter.swift in Sources */, AEFA82BC4285117096BCBB16 /* StakingPayoutConfirmationInteractor.swift in Sources */, @@ -18126,6 +18557,7 @@ F418E891264D318C00699085 /* AlertsView.swift in Sources */, FAADC19929261F6400DA9903 /* NominationPoolsUpdateRolesCall.swift in Sources */, CCF5A7CED175D5E43B2C9971 /* StakingUnbondSetupViewController.swift in Sources */, + FA1D02002BBE713D005B7071 /* LiquidityPoolListCell.swift in Sources */, FAE39AF12A9DBDDA0011A9D6 /* NftCollectionViewModel.swift in Sources */, 57E20F0723C4748D576C4882 /* StakingUnbondSetupViewFactory.swift in Sources */, F40966CD26B297D6008CD244 /* AnalyticsStakePresenter.swift in Sources */, @@ -18140,7 +18572,6 @@ FA99425728053C8800D771E5 /* SelectExportAccountPresenter.swift in Sources */, FA2FC85A28B389EB00CC0A42 /* AssetSelectionTableViewCellModel.swift in Sources */, F0C3DB0CEE1975626B0014A8 /* StakingUnbondConfirmInteractor.swift in Sources */, - 074D83312BCA49BF00AD1336 /* UIImageView+Shimmered.swift in Sources */, FA936BEE2872E3540059B97A /* TitleSwitchTableViewCell.swift in Sources */, C6A53DEF28A4FB2C00EFF190 /* Array + Divide.swift in Sources */, D3B48F82A875E301D749AC0B /* StakingUnbondConfirmViewController.swift in Sources */, @@ -18158,6 +18589,7 @@ C0B0DDF638915E8259B1CD67 /* StakingRedeemPresenter.swift in Sources */, C4A4D40A08DAB4A71C21C1A8 /* StakingRedeemInteractor.swift in Sources */, FA4B92912844CF750003BCEF /* MetaAccountModelChangedEvent.swift in Sources */, + FA4441342BF75FD90067C633 /* LiquidityPoolListType.swift in Sources */, FABA163C2B0C9510001AF2F0 /* NetworkManagmentTableCell.swift in Sources */, FAC0BBDE291D0EB000E6F106 /* SelectAssetAssembly.swift in Sources */, FA99426D28053CFA00D771E5 /* WalletDetailsViewModelFactory.swift in Sources */, @@ -18228,6 +18660,7 @@ FA2569C0274CE74100875A53 /* EtheriumAddressForRewardView.swift in Sources */, FA4B92AF2844D0E60003BCEF /* SelectCurrencyInteractor.swift in Sources */, C611666C2B3C03B800F483C4 /* NftHeaderCellViewModel.swift in Sources */, + FAD067992C2043FC0050291F /* WalletAssetsObserver.swift in Sources */, 0E6C2939AFB3D125C760D5A0 /* CrowdloanContributionSetupProtocols.swift in Sources */, 4E5CD7B8821FA5298EA1598E /* CrowdloanContributionSetupWireframe.swift in Sources */, 9081D43697D992F51E057ED2 /* CrowdloanContributionSetupPresenter.swift in Sources */, @@ -18295,8 +18728,7 @@ 8BF525D6B5DFB7CF6C03B015 /* AnalyticsValidatorsViewController.swift in Sources */, FA6262662AC2E35A005D3D95 /* WalletConnectProposalAssembly.swift in Sources */, 237AD34CD1C2778834D7B330 /* AnalyticsValidatorsViewFactory.swift in Sources */, - 070CDD772ACAE05D00F3F20A /* CexQRInfo.swift in Sources */, - FA072C16277B023D00731718 /* QRExtractionService.swift in Sources */, + FA2222962BD272A30031DE04 /* SkeletonLoadableView.swift in Sources */, FA37AE2A2859BA1D001DCA96 /* StakingBondMoreConfirmationParachainStrategy.swift in Sources */, 31E260D462BF33CFCDFEBA6C /* AnalyticsRewardDetailsProtocols.swift in Sources */, FA6262482AC2E35A005D3D95 /* WalletConnectActiveSessionsViewController.swift in Sources */, @@ -18313,10 +18745,10 @@ 69EF1DC4093AC9AF06D71CF4 /* AnalyticsRewardDetailsViewFactory.swift in Sources */, 93434E8E407A6C63D8862A21 /* AssetSelectionProtocols.swift in Sources */, CDB78A5A733E4A4F1A2C48C8 /* AssetSelectionWireframe.swift in Sources */, + FA054A9A2BCD1FA3007B8F6D /* AvailableLiquidityPoolsListPresenter.swift in Sources */, 2FCB062A2D873BD72B795DB3 /* AssetSelectionPresenter.swift in Sources */, BEA539EE97A287868FD8BE46 /* AssetSelectionViewFactory.swift in Sources */, 07DFA44B289918E10035A8AB /* ModalSheetBlurPresentationController.swift in Sources */, - 074D83382BCA946200AD1336 /* AccountInfoRemoteService.swift in Sources */, FA2E9BBF27A297CE0023FAD2 /* FilterSectionViewModel.swift in Sources */, FA2FC80A28B3807C00CC0A42 /* StakingPoolJoinConfirmViewModelFactory.swift in Sources */, FA8644302767539400956D8E /* WalletTransactionHistoryViewModel.swift in Sources */, @@ -18382,6 +18814,7 @@ FA99425B28053C8800D771E5 /* SelectExportAccountViewController.swift in Sources */, 69DE177B9D1745FEE848E870 /* WalletTransactionDetailsInteractor.swift in Sources */, 44B20C179522F7E38DAA2441 /* WalletTransactionDetailsViewController.swift in Sources */, + FAD067C02C2044B10050291F /* AssetManagementAssembly.swift in Sources */, F50D9C2CCA49D396E0D6EFDD /* WalletTransactionDetailsViewLayout.swift in Sources */, 1A2A55DCA9403CCE2A98E93E /* WalletTransactionDetailsViewFactory.swift in Sources */, FACD42BD2A5BE91E009975AA /* PortionRewardCalculatorService.swift in Sources */, @@ -18423,7 +18856,6 @@ 9C8AAE31F22421A975A17DF4 /* AddCustomNodeWireframe.swift in Sources */, FA34EEB42B9872240042E73E /* StakingCurrentEraRequest.swift in Sources */, 07DFA456289B78E20035A8AB /* CopyableLabelView.swift in Sources */, - 074D83332BCA4A4200AD1336 /* AssetManagementMigrator.swift in Sources */, 07D05E6728EF0BE500B66C70 /* SelectValidatorsConfirmPoolViewModelFactory.swift in Sources */, AE552BD2B83A94626F109CA9 /* AddCustomNodePresenter.swift in Sources */, FA34EE9A2B98712D0042E73E /* BalanceLocksFetching.swift in Sources */, @@ -18439,6 +18871,7 @@ FA7336C12A0E3B7F0096A291 /* NetworkClientFactory.swift in Sources */, 0BD66304BF73EBDFE1857380 /* WarningAlertPresenter.swift in Sources */, 5712A48A0C8AEFD9355FD9DA /* WarningAlertInteractor.swift in Sources */, + FA5085AC2C33C6D4002DF97D /* SafeArray.swift in Sources */, FABA16462B0C9511001AF2F0 /* NetworkManagmentViewModel.swift in Sources */, EDC72DAB0BDD63E0521E66B5 /* WarningAlertViewController.swift in Sources */, FA6262652AC2E35A005D3D95 /* WalletConnectProposalInteractor.swift in Sources */, @@ -18479,7 +18912,6 @@ FA62625A2AC2E35A005D3D95 /* MultiSelectNetworksInteractor.swift in Sources */, FA34EEDC2B98723C0042E73E /* OnboardingPresenter.swift in Sources */, FA74359929C0735B0085A47E /* ChainSettingsRepositoryFactory.swift in Sources */, - FAADC1C629265C9600DA9903 /* QRCoderFactory.swift in Sources */, 75F3A0D30C8BC050489F4644 /* WalletOptionRouter.swift in Sources */, E6981A506AC931D30E85169E /* WalletOptionPresenter.swift in Sources */, 3245549CB47E65B28A2C01CD /* WalletOptionInteractor.swift in Sources */, @@ -18535,7 +18967,6 @@ 7DFB3D265846A31807E1A663 /* StakingPoolCreateConfirmRouter.swift in Sources */, FA34EEEC2B98723C0042E73E /* BalanceLocksDetailViewController.swift in Sources */, FAAA29442B8DCED90089AFE6 /* ChildStorageResponseDecodingWorker.swift in Sources */, - 074D832F2BCA496300AD1336 /* ChainAssetListBuilder.swift in Sources */, FAFFAE8129AC84B10074AF1F /* SubqueryDelegatorHistoryElement.swift in Sources */, 10B4951F5E0C515EFBDBC32E /* StakingPoolCreateConfirmPresenter.swift in Sources */, FA7254362AC2E48500EC47A6 /* String+EIP55.swift in Sources */, @@ -18543,16 +18974,15 @@ FA2DF99E2A8C9AB10047F440 /* EtherscanNftsResponse.swift in Sources */, 8C3A576CEF21F0A68C8A129F /* StakingPoolCreateConfirmInteractor.swift in Sources */, D22D29F8EC4C7522345C8772 /* StakingPoolCreateConfirmViewController.swift in Sources */, - 0739FD2E2BFB4A71009ADD7C /* LegacyEraStakersFetching.swift in Sources */, 257AF452E202DC6B8A576559 /* StakingPoolCreateConfirmViewLayout.swift in Sources */, 159A8702C30A21988AD76805 /* StakingPoolCreateConfirmAssembly.swift in Sources */, DA62812C23210601F4ECF84D /* ContactsProtocols.swift in Sources */, F6CD0ED1CF9A605222745BEC /* ContactsRouter.swift in Sources */, DAAD3A3FCBA0C0E613167EBF /* ContactsPresenter.swift in Sources */, + FA1D51D92BCFE353001353E7 /* SoraFiatService.swift in Sources */, 705F5EEDD70D6941D138D3F9 /* ContactsInteractor.swift in Sources */, 3336F04749ADC27C81BA9464 /* ContactsViewController.swift in Sources */, 2515863D26C9F862AB800C4C /* ContactsViewLayout.swift in Sources */, - 070179612BC7F91600908C83 /* ChainAssetListViewLayout.swift in Sources */, E29066A3781333DF890E8F9B /* ContactsAssembly.swift in Sources */, 9E2D97A489E8F84A8A0916A8 /* CreateContactProtocols.swift in Sources */, D3C2414CAC720D2D08F0CC4F /* CreateContactRouter.swift in Sources */, @@ -18568,6 +18998,7 @@ 78627BC990DE9C037CE69BB0 /* CreateContactAssembly.swift in Sources */, DD96B37BBEE1535951802B55 /* AllDoneProtocols.swift in Sources */, CD027E4D430D8939A3D64EB6 /* AllDoneRouter.swift in Sources */, + FAD067912C2042F30050291F /* Requests.swift in Sources */, 306E249AD210DFAA8C03D435 /* AllDonePresenter.swift in Sources */, DE9FA0FA5A6B685CBD593025 /* AllDoneInteractor.swift in Sources */, 65E0BC7A96EDE5E52D32A11B /* AllDoneViewController.swift in Sources */, @@ -18594,6 +19025,7 @@ A29F1452BF0AEB885E6460E2 /* SelectMarketPresenter.swift in Sources */, FADBA5F12B5FD0C200CFCF30 /* ClaimCrowdloanRewardViewModelFactory.swift in Sources */, 53DA09F488806FFE86C841AA /* SelectMarketInteractor.swift in Sources */, + FA8810D32BDCCF7E0084CC4B /* UserLiquidityPoolsListPresenter.swift in Sources */, 503DFF0EFCAD0A8B526FEC3A /* SelectMarketViewController.swift in Sources */, E40F3F3C0FE753970B8745DD /* SelectMarketAssembly.swift in Sources */, DBA6A0A26D77E7A587C51792 /* PolkaswapSwapConfirmationProtocols.swift in Sources */, @@ -18604,12 +19036,10 @@ 04A17615051F4A1AE0E63BF8 /* PolkaswapSwapConfirmationViewLayout.swift in Sources */, 6B4F5F4FD7820C70FB51A2F9 /* PolkaswapSwapConfirmationAssembly.swift in Sources */, FA7254212AC2E48500EC47A6 /* WalletConnectPayloadSigner.swift in Sources */, - FAFFAEA829AC85230074AF1F /* ZeroBalancesSettingChanged.swift in Sources */, 96EBE5F57C97C7A7A525E864 /* SwapTransactionDetailProtocols.swift in Sources */, ADF845374BEF73D90D4BF005 /* SwapTransactionDetailRouter.swift in Sources */, A73B076B0E983DA669C1F215 /* SwapTransactionDetailPresenter.swift in Sources */, 41040A200CF5E77C291128DA /* SwapTransactionDetailInteractor.swift in Sources */, - 0768FBBE2BDCEDC300FB126F /* ChainConnectionVisibilityHelper.swift in Sources */, 3B0F51B1D1590FAAE73CD36C /* SwapTransactionDetailViewController.swift in Sources */, 910CEF0535028E629FD9798C /* SwapTransactionDetailViewLayout.swift in Sources */, 02FA6FDF7212F1F8D056BC18 /* SwapTransactionDetailAssembly.swift in Sources */, @@ -18660,6 +19090,47 @@ 7E3FB57A93AFAE39CF3030C8 /* ClaimCrowdloanRewardsViewController.swift in Sources */, C80CF43B1F8307A48D03741D /* ClaimCrowdloanRewardsViewLayout.swift in Sources */, 04F9CF04588676D79EFB8570 /* ClaimCrowdloanRewardsAssembly.swift in Sources */, + 225493AF467A54A56F74FFF5 /* LiquidityPoolsOverviewProtocols.swift in Sources */, + F52C9FF9ABB4ED034D177CF8 /* LiquidityPoolsOverviewRouter.swift in Sources */, + 1E59CE2953F8835954A4E5A7 /* LiquidityPoolsOverviewPresenter.swift in Sources */, + DFF0320CF3AA41142DEAC5F2 /* LiquidityPoolsOverviewInteractor.swift in Sources */, + 4A957B3BAC231B70CBC00EC3 /* LiquidityPoolsOverviewViewController.swift in Sources */, + 02EC6059AEE8C92B4EDD09C0 /* LiquidityPoolsOverviewViewLayout.swift in Sources */, + 61B5A91FBEF633FCC8D965B6 /* LiquidityPoolsOverviewAssembly.swift in Sources */, + CF96BE0B636DA8227E689DDA /* LiquidityPoolDetailsProtocols.swift in Sources */, + FAD067D52C214E7C0050291F /* LiquidityPoolsConstants.swift in Sources */, + 23E30A21620831C600CBC1D6 /* LiquidityPoolDetailsRouter.swift in Sources */, + D2A85A5EE89EAAA856EA5C0F /* LiquidityPoolDetailsPresenter.swift in Sources */, + 7D8D644C5E1695288A0E86C0 /* LiquidityPoolDetailsInteractor.swift in Sources */, + A1C05D0028CD04C16AB6082F /* LiquidityPoolDetailsViewController.swift in Sources */, + 3A4026E96615A1D53DAF12D8 /* LiquidityPoolDetailsViewLayout.swift in Sources */, + 7DCC939E882247E141B1DE34 /* LiquidityPoolDetailsAssembly.swift in Sources */, + 0D7DDA00BBF1D0CFD9A26306 /* LiquidityPoolSupplyProtocols.swift in Sources */, + 66AECEC6A6EB8184114B041E /* LiquidityPoolSupplyRouter.swift in Sources */, + FA5085AD2C33C6D4002DF97D /* SafeDictionary.swift in Sources */, + BC2DF589C6623601C39EF8F4 /* LiquidityPoolSupplyPresenter.swift in Sources */, + 87C1FC2909A8360DDBA625E5 /* LiquidityPoolSupplyInteractor.swift in Sources */, + F31469BD18062A4A008FE39E /* LiquidityPoolSupplyViewController.swift in Sources */, + 5E8504507116E0177D70314B /* LiquidityPoolSupplyViewLayout.swift in Sources */, + DCE13AA9F3BA0EB54F793017 /* LiquidityPoolSupplyAssembly.swift in Sources */, + 6FAC7E8F0DACB3F2AA0BE825 /* LiquidityPoolSupplyConfirmProtocols.swift in Sources */, + FBE4702B7F95484235386631 /* LiquidityPoolSupplyConfirmRouter.swift in Sources */, + 1029947E04F64B616E252949 /* LiquidityPoolSupplyConfirmPresenter.swift in Sources */, + 06826AA6DBAEA5BBF45BB5CA /* LiquidityPoolSupplyConfirmInteractor.swift in Sources */, + 24E6794278FEC01DFFE7C69C /* LiquidityPoolSupplyConfirmViewController.swift in Sources */, + 74A39BC366D85CC5FCA78579 /* LiquidityPoolSupplyConfirmViewLayout.swift in Sources */, + 991DA2DE1E8A45B0A8B187CD /* LiquidityPoolSupplyConfirmAssembly.swift in Sources */, + 51876200A6B1EDC54609DF46 /* LiquidityPoolRemoveLiquidityProtocols.swift in Sources */, + B112AC02371DE4C1DAD48BB1 /* LiquidityPoolRemoveLiquidityRouter.swift in Sources */, + 5A7D43CA17B84C71E8EEF256 /* LiquidityPoolRemoveLiquidityPresenter.swift in Sources */, + FC540426B1BC363842A3677B /* LiquidityPoolRemoveLiquidityInteractor.swift in Sources */, + 466B1E0EEC6438F8835AAF2E /* LiquidityPoolRemoveLiquidityViewController.swift in Sources */, + A5C7F51539B8D93D9186DA2C /* LiquidityPoolRemoveLiquidityViewLayout.swift in Sources */, + 30C7FD6C58F1ED50AFB456FD /* LiquidityPoolRemoveLiquidityAssembly.swift in Sources */, + 5142E2C6609188D529BB558A /* LiquidityPoolRemoveLiquidityConfirmProtocols.swift in Sources */, + 8A957CAF82C856E61054B02F /* LiquidityPoolRemoveLiquidityConfirmViewController.swift in Sources */, + 10DEF797CB3DC5BF0903EC4C /* LiquidityPoolRemoveLiquidityConfirmViewLayout.swift in Sources */, + E667BD4B6BA45B9B3464AD85 /* LiquidityPoolRemoveLiquidityConfirmAssembly.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -18830,6 +19301,12 @@ 9F0457A013858A7ADEB41234 /* NftSendConfirmTests.swift in Sources */, 3E72CF4FCDFE9ED965124D18 /* AssetNetworksTests.swift in Sources */, 99DCBCC3298620721B213012 /* ClaimCrowdloanRewardsTests.swift in Sources */, + 60C22E112CA857A2EA5A129E /* LiquidityPoolsOverviewTests.swift in Sources */, + 6D0E50CEBCB73C23A75A7F46 /* LiquidityPoolDetailsTests.swift in Sources */, + D8C33C4064C3B2F30BB478A5 /* LiquidityPoolSupplyTests.swift in Sources */, + B40863AA7377BFE5F8A30259 /* LiquidityPoolSupplyConfirmTests.swift in Sources */, + 6BF307ADE63FA92389340779 /* LiquidityPoolRemoveLiquidityTests.swift in Sources */, + ECA54AB8148BBA63084353FD /* LiquidityPoolRemoveLiquidityConfirmTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -19122,7 +19599,7 @@ "$(CONFIGURATION_BUILD_DIR)", "$(FRAMEWORK_SEARCH_PATHS)", ); - MARKETING_VERSION = 3.6.1; + MARKETING_VERSION = 2.2.3; OTHER_SWIFT_FLAGS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = jp.co.soramitsu.fearless; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -19149,7 +19626,7 @@ "$(CONFIGURATION_BUILD_DIR)", "$(FRAMEWORK_SEARCH_PATHS)", ); - MARKETING_VERSION = 3.6.1; + MARKETING_VERSION = 2.2.3; PRODUCT_BUNDLE_IDENTIFIER = jp.co.soramitsu.fearless; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -19287,7 +19764,7 @@ "$(CONFIGURATION_BUILD_DIR)", "$(FRAMEWORK_SEARCH_PATHS)", ); - MARKETING_VERSION = 3.6.1; + MARKETING_VERSION = 2.2.3; OTHER_SWIFT_FLAGS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = jp.co.soramitsu.fearless; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -19368,28 +19845,28 @@ /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ - 07F44F012BE4C7FF00570143 /* XCRemoteSwiftPackageReference "Web3.swift" */ = { + FA7254652AC2F12D00EC47A6 /* XCRemoteSwiftPackageReference "WalletConnectSwiftV2" */ = { isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/bnsports/Web3.swift.git"; + repositoryURL = "https://github.com/WalletConnect/WalletConnectSwiftV2"; requirement = { kind = exactVersion; - version = 7.7.7; + version = 1.9.9; }; }; - FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */ = { + FA8810962BDCAF260084CC4B /* XCRemoteSwiftPackageReference "shared-features-spm" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/soramitsu/shared-features-spm.git"; requirement = { - branch = "update-for-fearless-asset-management"; + branch = "fearless-wallet"; kind = branch; }; }; - FA7254652AC2F12D00EC47A6 /* XCRemoteSwiftPackageReference "WalletConnectSwiftV2" */ = { + FA8FD17F2AF4B55100354482 /* XCRemoteSwiftPackageReference "Web3.swift" */ = { isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/WalletConnect/WalletConnectSwiftV2"; + repositoryURL = "https://github.com/bnsports/Web3.swift.git"; requirement = { kind = exactVersion; - version = 1.9.9; + version = 7.7.7; }; }; FA8FD1862AF4BEDD00354482 /* XCRemoteSwiftPackageReference "Swime" */ = { @@ -19403,195 +19880,190 @@ /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ - 07F44F022BE4C7FF00570143 /* Web3 */ = { + FA7254662AC2F12D00EC47A6 /* WalletConnect */ = { isa = XCSwiftPackageProductDependency; - package = 07F44F012BE4C7FF00570143 /* XCRemoteSwiftPackageReference "Web3.swift" */; - productName = Web3; + package = FA7254652AC2F12D00EC47A6 /* XCRemoteSwiftPackageReference "WalletConnectSwiftV2" */; + productName = WalletConnect; }; - 07F44F042BE4C7FF00570143 /* Web3ContractABI */ = { + FA7254682AC2F12D00EC47A6 /* WalletConnectAuth */ = { isa = XCSwiftPackageProductDependency; - package = 07F44F012BE4C7FF00570143 /* XCRemoteSwiftPackageReference "Web3.swift" */; - productName = Web3ContractABI; + package = FA7254652AC2F12D00EC47A6 /* XCRemoteSwiftPackageReference "WalletConnectSwiftV2" */; + productName = WalletConnectAuth; }; - 07F44F062BE4C7FF00570143 /* Web3PromiseKit */ = { + FA72546A2AC2F12D00EC47A6 /* WalletConnectNetworking */ = { isa = XCSwiftPackageProductDependency; - package = 07F44F012BE4C7FF00570143 /* XCRemoteSwiftPackageReference "Web3.swift" */; - productName = Web3PromiseKit; + package = FA7254652AC2F12D00EC47A6 /* XCRemoteSwiftPackageReference "WalletConnectSwiftV2" */; + productName = WalletConnectNetworking; }; - FA53D8962C096F1100173ADB /* IrohaCrypto */ = { + FA72546C2AC2F12D00EC47A6 /* WalletConnectPairing */ = { isa = XCSwiftPackageProductDependency; - package = FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */; - productName = IrohaCrypto; + package = FA7254652AC2F12D00EC47A6 /* XCRemoteSwiftPackageReference "WalletConnectSwiftV2" */; + productName = WalletConnectPairing; + }; + FA72546E2AC2F12D00EC47A6 /* Web3Wallet */ = { + isa = XCSwiftPackageProductDependency; + package = FA7254652AC2F12D00EC47A6 /* XCRemoteSwiftPackageReference "WalletConnectSwiftV2" */; + productName = Web3Wallet; }; - FA53D8982C096F1100173ADB /* MPQRCoreSDK */ = { + FA8810972BDCAF260084CC4B /* IrohaCrypto */ = { isa = XCSwiftPackageProductDependency; - package = FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */; - productName = MPQRCoreSDK; + package = FA8810962BDCAF260084CC4B /* XCRemoteSwiftPackageReference "shared-features-spm" */; + productName = IrohaCrypto; }; - FA53D89A2C096F1100173ADB /* RobinHood */ = { + FA8810992BDCAF260084CC4B /* RobinHood */ = { isa = XCSwiftPackageProductDependency; - package = FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */; + package = FA8810962BDCAF260084CC4B /* XCRemoteSwiftPackageReference "shared-features-spm" */; productName = RobinHood; }; - FA53D89C2C096F1100173ADB /* SSFAccountManagment */ = { + FA88109B2BDCAF260084CC4B /* SSFAccountManagment */ = { isa = XCSwiftPackageProductDependency; - package = FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */; + package = FA8810962BDCAF260084CC4B /* XCRemoteSwiftPackageReference "shared-features-spm" */; productName = SSFAccountManagment; }; - FA53D89E2C096F1100173ADB /* SSFAccountManagmentStorage */ = { + FA88109D2BDCAF260084CC4B /* SSFAccountManagmentStorage */ = { isa = XCSwiftPackageProductDependency; - package = FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */; + package = FA8810962BDCAF260084CC4B /* XCRemoteSwiftPackageReference "shared-features-spm" */; productName = SSFAccountManagmentStorage; }; - FA53D8A02C096F1100173ADB /* SSFAssetManagment */ = { + FA88109F2BDCAF260084CC4B /* SSFAssetManagment */ = { isa = XCSwiftPackageProductDependency; - package = FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */; + package = FA8810962BDCAF260084CC4B /* XCRemoteSwiftPackageReference "shared-features-spm" */; productName = SSFAssetManagment; }; - FA53D8A22C096F1100173ADB /* SSFChainConnection */ = { + FA8810A12BDCAF260084CC4B /* SSFChainConnection */ = { isa = XCSwiftPackageProductDependency; - package = FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */; + package = FA8810962BDCAF260084CC4B /* XCRemoteSwiftPackageReference "shared-features-spm" */; productName = SSFChainConnection; }; - FA53D8A42C096F1100173ADB /* SSFChainRegistry */ = { + FA8810A32BDCAF260084CC4B /* SSFChainRegistry */ = { isa = XCSwiftPackageProductDependency; - package = FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */; + package = FA8810962BDCAF260084CC4B /* XCRemoteSwiftPackageReference "shared-features-spm" */; productName = SSFChainRegistry; }; - FA53D8A62C096F1100173ADB /* SSFCloudStorage */ = { + FA8810A52BDCAF260084CC4B /* SSFCloudStorage */ = { isa = XCSwiftPackageProductDependency; - package = FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */; + package = FA8810962BDCAF260084CC4B /* XCRemoteSwiftPackageReference "shared-features-spm" */; productName = SSFCloudStorage; }; - FA53D8A82C096F1100173ADB /* SSFCrypto */ = { + FA8810A72BDCAF260084CC4B /* SSFCrypto */ = { isa = XCSwiftPackageProductDependency; - package = FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */; + package = FA8810962BDCAF260084CC4B /* XCRemoteSwiftPackageReference "shared-features-spm" */; productName = SSFCrypto; }; - FA53D8AA2C096F1100173ADB /* SSFEraKit */ = { + FA8810A92BDCAF260084CC4B /* SSFEraKit */ = { isa = XCSwiftPackageProductDependency; - package = FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */; + package = FA8810962BDCAF260084CC4B /* XCRemoteSwiftPackageReference "shared-features-spm" */; productName = SSFEraKit; }; - FA53D8AC2C096F1100173ADB /* SSFExtrinsicKit */ = { + FA8810AB2BDCAF260084CC4B /* SSFExtrinsicKit */ = { isa = XCSwiftPackageProductDependency; - package = FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */; + package = FA8810962BDCAF260084CC4B /* XCRemoteSwiftPackageReference "shared-features-spm" */; productName = SSFExtrinsicKit; }; - FA53D8AE2C096F1100173ADB /* SSFHelpers */ = { + FA8810AD2BDCAF260084CC4B /* SSFHelpers */ = { isa = XCSwiftPackageProductDependency; - package = FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */; + package = FA8810962BDCAF260084CC4B /* XCRemoteSwiftPackageReference "shared-features-spm" */; productName = SSFHelpers; }; - FA53D8B02C096F1100173ADB /* SSFKeyPair */ = { + FA8810AF2BDCAF260084CC4B /* SSFKeyPair */ = { isa = XCSwiftPackageProductDependency; - package = FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */; + package = FA8810962BDCAF260084CC4B /* XCRemoteSwiftPackageReference "shared-features-spm" */; productName = SSFKeyPair; }; - FA53D8B22C096F1100173ADB /* SSFLogger */ = { + FA8810B12BDCAF260084CC4B /* SSFLogger */ = { isa = XCSwiftPackageProductDependency; - package = FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */; + package = FA8810962BDCAF260084CC4B /* XCRemoteSwiftPackageReference "shared-features-spm" */; productName = SSFLogger; }; - FA53D8B42C096F1100173ADB /* SSFModels */ = { + FA8810B32BDCAF260084CC4B /* SSFModels */ = { isa = XCSwiftPackageProductDependency; - package = FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */; + package = FA8810962BDCAF260084CC4B /* XCRemoteSwiftPackageReference "shared-features-spm" */; productName = SSFModels; }; - FA53D8B62C096F1100173ADB /* SSFNetwork */ = { + FA8810B52BDCAF260084CC4B /* SSFNetwork */ = { isa = XCSwiftPackageProductDependency; - package = FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */; + package = FA8810962BDCAF260084CC4B /* XCRemoteSwiftPackageReference "shared-features-spm" */; productName = SSFNetwork; }; - FA53D8B82C096F1100173ADB /* SSFPolkaswap */ = { + FA8810B72BDCAF260084CC4B /* SSFPolkaswap */ = { isa = XCSwiftPackageProductDependency; - package = FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */; + package = FA8810962BDCAF260084CC4B /* XCRemoteSwiftPackageReference "shared-features-spm" */; productName = SSFPolkaswap; }; - FA53D8BA2C096F1100173ADB /* SSFPools */ = { + FA8810B92BDCAF260084CC4B /* SSFPools */ = { isa = XCSwiftPackageProductDependency; - package = FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */; + package = FA8810962BDCAF260084CC4B /* XCRemoteSwiftPackageReference "shared-features-spm" */; productName = SSFPools; }; - FA53D8BC2C096F1100173ADB /* SSFPoolsStorage */ = { + FA8810BB2BDCAF260084CC4B /* SSFPoolsStorage */ = { isa = XCSwiftPackageProductDependency; - package = FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */; + package = FA8810962BDCAF260084CC4B /* XCRemoteSwiftPackageReference "shared-features-spm" */; productName = SSFPoolsStorage; }; - FA53D8BE2C096F1100173ADB /* SSFQRService */ = { + FA8810BD2BDCAF260084CC4B /* SSFQRService */ = { isa = XCSwiftPackageProductDependency; - package = FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */; + package = FA8810962BDCAF260084CC4B /* XCRemoteSwiftPackageReference "shared-features-spm" */; productName = SSFQRService; }; - FA53D8C02C096F1100173ADB /* SSFRuntimeCodingService */ = { + FA8810BF2BDCAF260084CC4B /* SSFRuntimeCodingService */ = { isa = XCSwiftPackageProductDependency; - package = FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */; + package = FA8810962BDCAF260084CC4B /* XCRemoteSwiftPackageReference "shared-features-spm" */; productName = SSFRuntimeCodingService; }; - FA53D8C22C096F1100173ADB /* SSFSigner */ = { + FA8810C12BDCAF260084CC4B /* SSFSigner */ = { isa = XCSwiftPackageProductDependency; - package = FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */; + package = FA8810962BDCAF260084CC4B /* XCRemoteSwiftPackageReference "shared-features-spm" */; productName = SSFSigner; }; - FA53D8C42C096F1100173ADB /* SSFSingleValueCache */ = { + FA8810C32BDCAF260084CC4B /* SSFSingleValueCache */ = { isa = XCSwiftPackageProductDependency; - package = FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */; + package = FA8810962BDCAF260084CC4B /* XCRemoteSwiftPackageReference "shared-features-spm" */; productName = SSFSingleValueCache; }; - FA53D8C62C096F1100173ADB /* SSFStorageQueryKit */ = { + FA8810C52BDCAF260084CC4B /* SSFStorageQueryKit */ = { isa = XCSwiftPackageProductDependency; - package = FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */; + package = FA8810962BDCAF260084CC4B /* XCRemoteSwiftPackageReference "shared-features-spm" */; productName = SSFStorageQueryKit; }; - FA53D8C82C096F1100173ADB /* SSFTransferService */ = { + FA8810C72BDCAF260084CC4B /* SSFTransferService */ = { isa = XCSwiftPackageProductDependency; - package = FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */; + package = FA8810962BDCAF260084CC4B /* XCRemoteSwiftPackageReference "shared-features-spm" */; productName = SSFTransferService; }; - FA53D8CA2C096F1100173ADB /* SSFUtils */ = { + FA8810C92BDCAF260084CC4B /* SSFUtils */ = { isa = XCSwiftPackageProductDependency; - package = FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */; + package = FA8810962BDCAF260084CC4B /* XCRemoteSwiftPackageReference "shared-features-spm" */; productName = SSFUtils; }; - FA53D8CC2C096F1100173ADB /* SSFXCM */ = { + FA8810CB2BDCAF260084CC4B /* SSFXCM */ = { isa = XCSwiftPackageProductDependency; - package = FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */; + package = FA8810962BDCAF260084CC4B /* XCRemoteSwiftPackageReference "shared-features-spm" */; productName = SSFXCM; }; - FA53D8CE2C096F1100173ADB /* SoraKeystore */ = { + FA8810CD2BDCAF260084CC4B /* SoraKeystore */ = { isa = XCSwiftPackageProductDependency; - package = FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */; + package = FA8810962BDCAF260084CC4B /* XCRemoteSwiftPackageReference "shared-features-spm" */; productName = SoraKeystore; }; - FA53D8D02C096F1100173ADB /* keccak */ = { + FA8810CF2BDCAF260084CC4B /* keccak */ = { isa = XCSwiftPackageProductDependency; - package = FA53D8952C096F1100173ADB /* XCRemoteSwiftPackageReference "shared-features-spm" */; + package = FA8810962BDCAF260084CC4B /* XCRemoteSwiftPackageReference "shared-features-spm" */; productName = keccak; }; - FA7254662AC2F12D00EC47A6 /* WalletConnect */ = { - isa = XCSwiftPackageProductDependency; - package = FA7254652AC2F12D00EC47A6 /* XCRemoteSwiftPackageReference "WalletConnectSwiftV2" */; - productName = WalletConnect; - }; - FA7254682AC2F12D00EC47A6 /* WalletConnectAuth */ = { + FA8FD1802AF4B55100354482 /* Web3 */ = { isa = XCSwiftPackageProductDependency; - package = FA7254652AC2F12D00EC47A6 /* XCRemoteSwiftPackageReference "WalletConnectSwiftV2" */; - productName = WalletConnectAuth; - }; - FA72546A2AC2F12D00EC47A6 /* WalletConnectNetworking */ = { - isa = XCSwiftPackageProductDependency; - package = FA7254652AC2F12D00EC47A6 /* XCRemoteSwiftPackageReference "WalletConnectSwiftV2" */; - productName = WalletConnectNetworking; + package = FA8FD17F2AF4B55100354482 /* XCRemoteSwiftPackageReference "Web3.swift" */; + productName = Web3; }; - FA72546C2AC2F12D00EC47A6 /* WalletConnectPairing */ = { + FA8FD1822AF4B55100354482 /* Web3ContractABI */ = { isa = XCSwiftPackageProductDependency; - package = FA7254652AC2F12D00EC47A6 /* XCRemoteSwiftPackageReference "WalletConnectSwiftV2" */; - productName = WalletConnectPairing; + package = FA8FD17F2AF4B55100354482 /* XCRemoteSwiftPackageReference "Web3.swift" */; + productName = Web3ContractABI; }; - FA72546E2AC2F12D00EC47A6 /* Web3Wallet */ = { + FA8FD1842AF4B55100354482 /* Web3PromiseKit */ = { isa = XCSwiftPackageProductDependency; - package = FA7254652AC2F12D00EC47A6 /* XCRemoteSwiftPackageReference "WalletConnectSwiftV2" */; - productName = Web3Wallet; + package = FA8FD17F2AF4B55100354482 /* XCRemoteSwiftPackageReference "Web3.swift" */; + productName = Web3PromiseKit; }; FA8FD1872AF4BEDD00354482 /* Swime */ = { isa = XCSwiftPackageProductDependency; @@ -19601,17 +20073,18 @@ /* End XCSwiftPackageProductDependency section */ /* Begin XCVersionGroup section */ - FACE6C5D2BBAC3B000643CEF /* SubstrateDataModel.xcdatamodeld */ = { + FAD0679F2C2044490050291F /* SubstrateDataModel.xcdatamodeld */ = { isa = XCVersionGroup; children = ( - 07BE13CB2C071E7800EC7424 /* SubstrateDataModel_v6.xcdatamodel */, - FACE6C5E2BBAC3B000643CEF /* SubstrateDataModel.xcdatamodel */, - FACE6C5F2BBAC3B000643CEF /* SubstrateDataModel_v4.xcdatamodel */, - FACE6C602BBAC3B000643CEF /* SubstrateDataModel_v2.xcdatamodel */, - FACE6C612BBAC3B000643CEF /* SubstrateDataModel_v5.xcdatamodel */, - FACE6C622BBAC3B000643CEF /* SubstrateDataModel_v3.xcdatamodel */, + FAD067A02C2044490050291F /* SubstrateDataModel.xcdatamodel */, + FAD067A12C2044490050291F /* SubstrateDataModel_v4.xcdatamodel */, + FAD067A22C2044490050291F /* SubstrateDataModel_v2.xcdatamodel */, + FAD067A32C2044490050291F /* SubstrateDataModel_v7.xcdatamodel */, + FAD067A42C2044490050291F /* SubstrateDataModel_v5.xcdatamodel */, + FAD067A52C2044490050291F /* SubstrateDataModel_v6.xcdatamodel */, + FAD067A62C2044490050291F /* SubstrateDataModel_v3.xcdatamodel */, ); - currentVersion = 07BE13CB2C071E7800EC7424 /* SubstrateDataModel_v6.xcdatamodel */; + currentVersion = FAD067A32C2044490050291F /* SubstrateDataModel_v7.xcdatamodel */; path = SubstrateDataModel.xcdatamodeld; sourceTree = ""; versionGroupType = wrapper.xcdatamodel; diff --git a/fearless.xcworkspace/xcshareddata/swiftpm/Package.resolved b/fearless.xcworkspace/xcshareddata/swiftpm/Package.resolved index 6e33b569fe..4ac8d64f60 100644 --- a/fearless.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/fearless.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,4 @@ { - "originHash" : "48bf9205e83b67ed7d81b2a0bcc8ef081189084205112c031b7823572f561e20", "pins" : [ { "identity" : "appauth-ios", @@ -42,8 +41,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/google/google-api-objectivec-client-for-rest.git", "state" : { - "revision" : "d46fb27cf61e08285a727c18a2ae0dbc20d91b2f", - "version" : "3.5.4" + "revision" : "a8c1e0b1173659d0be452680582c28556372ef74", + "version" : "3.5.5" } }, { @@ -60,8 +59,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/google/gtm-session-fetcher.git", "state" : { - "revision" : "0382ca27f22fb3494cf657d8dc356dc282cd1193", - "version" : "3.4.1" + "revision" : "a2ab612cb980066ee56d90d60d8462992c07f24b", + "version" : "3.5.0" } }, { @@ -132,8 +131,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/soramitsu/shared-features-spm.git", "state" : { - "branch" : "update-for-fearless-asset-management", - "revision" : "7beceb7253019a739f4322d74155cb428d308e7e" + "branch" : "fearless-wallet", + "revision" : "bb864277bcf22a6bd02d5abd7c8f07c5aa37236b" } }, { @@ -150,8 +149,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-collections.git", "state" : { - "revision" : "94cf62b3ba8d4bed62680a282d4c25f9c63c2efb", - "version" : "1.1.0" + "revision" : "3d2dc41a01f9e49d84f0a3925fb858bed64f702d", + "version" : "1.1.2" } }, { @@ -159,8 +158,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-http-types", "state" : { - "revision" : "9bee2fdb79cc740081abd8ebd80738063d632286", - "version" : "1.1.0" + "revision" : "1ddbea1ee34354a6a2532c60f98501c35ae8edfa", + "version" : "1.2.0" } }, { @@ -168,8 +167,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-nio.git", "state" : { - "revision" : "359c461e5561d22c6334828806cc25d759ca7aa6", - "version" : "2.65.0" + "revision" : "fc79798d5a150d61361a27ce0c51169b889e23de", + "version" : "2.68.0" } }, { @@ -177,8 +176,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-nio-extras.git", "state" : { - "revision" : "a3b640d7dc567225db7c94386a6e71aded1bfa63", - "version" : "1.22.0" + "revision" : "05c36b57453d23ea63785d58a7dbc7b70ba1745e", + "version" : "1.23.0" } }, { @@ -186,8 +185,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-nio-http2.git", "state" : { - "revision" : "c6afe04165c865faaa687b42c32ed76dfcc91076", - "version" : "1.31.0" + "revision" : "a0224f3d20438635dd59c9fcc593520d80d131d0", + "version" : "1.33.0" } }, { @@ -195,8 +194,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-nio-ssl.git", "state" : { - "revision" : "7c381eb6083542b124a6c18fae742f55001dc2b5", - "version" : "2.26.0" + "revision" : "2b09805797f21c380f7dc9bedaab3157c5508efb", + "version" : "2.27.0" } }, { @@ -222,8 +221,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-system.git", "state" : { - "revision" : "f9266c85189c2751589a50ea5aec72799797e471", - "version" : "1.3.0" + "revision" : "6a9e38e7bd22a3b8ba80bddf395623cf68f57807", + "version" : "1.3.1" } }, { @@ -299,5 +298,5 @@ } } ], - "version" : 3 + "version" : 2 } diff --git a/fearless/ApplicationLayer/Pricing/Model/SoraSubqueryPriceResponse.swift b/fearless/ApplicationLayer/Pricing/Model/SoraSubqueryPriceResponse.swift new file mode 100644 index 0000000000..a995224074 --- /dev/null +++ b/fearless/ApplicationLayer/Pricing/Model/SoraSubqueryPriceResponse.swift @@ -0,0 +1,23 @@ +import Foundation +import SSFUtils + +struct SoraSubqueryPriceResponse: Decodable { + let entities: SoraSubqueryPricePage +} + +struct SoraSubqueryPricePage: Decodable { + let nodes: [SoraSubqueryPrice] + let pageInfo: SubqueryPageInfo +} + +struct SoraSubqueryPrice: Decodable { + enum CodingKeys: String, CodingKey { + case id + case priceUsd = "priceUSD" + case priceChangeDay + } + + let id: String + let priceUsd: String? + let priceChangeDay: Decimal? +} diff --git a/fearless/ApplicationLayer/Pricing/SoraSubqueryPriceFetcher.swift b/fearless/ApplicationLayer/Pricing/SoraSubqueryPriceFetcher.swift new file mode 100644 index 0000000000..6769f3f643 --- /dev/null +++ b/fearless/ApplicationLayer/Pricing/SoraSubqueryPriceFetcher.swift @@ -0,0 +1,100 @@ +import Foundation +import SSFModels +import RobinHood + +final class SoraSubqueryPriceFetcherDefault: SoraSubqueryPriceFetcher { + func fetchPriceOperation( + for chainAssets: [ChainAsset] + ) -> BaseOperation<[PriceData]> { + AwaitOperation { [weak self] in + guard let self else { return [] } + + guard let blockExplorer = chainAssets.first(where: { chainAsset in + chainAsset.chain.knownChainEquivalent == .soraMain + })?.chain.externalApi?.pricing else { + throw SubqueryPriceFetcherError.missingBlockExplorer + } + let priceIds = chainAssets.map { $0.asset.priceProvider?.id }.compactMap { $0 } + let prices = try await self.fetch(priceIds: priceIds, url: blockExplorer.url) + + return prices.compactMap { price in + let chainAsset = chainAssets.first(where: { $0.asset.currencyId == price.id }) + + guard + let chainAsset = chainAsset, + chainAsset.asset.priceProvider?.type == .sorasubquery, + let priceId = chainAsset.asset.priceId + else { + return nil + } + + return PriceData( + currencyId: "usd", + priceId: priceId, + price: "\(price.priceUsd.or("0"))", + fiatDayChange: price.priceChangeDay, + coingeckoPriceId: chainAsset.asset.coingeckoPriceId + ) + } + } + } + + private func fetch( + priceIds: [String], + url: URL + ) async throws -> [SoraSubqueryPrice] { + var prices: [SoraSubqueryPrice] = [] + var cursor: String = "" + var allPricesFetched: Bool = false + + while !allPricesFetched { + let response = try await loadNewPrices(url: url, priceIds: priceIds, cursor: cursor) + prices = prices + response.nodes + allPricesFetched = response.pageInfo.hasNextPage.or(false) == false + cursor = response.pageInfo.endCursor.or("") + } + + return prices + } + + private func loadNewPrices( + url: URL, + priceIds: [String], + cursor: String + ) async throws -> SoraSubqueryPricePage { + let request = try StakingRewardsRequest( + baseURL: url, + query: queryString(priceIds: priceIds, cursor: cursor) + ) + let worker = NetworkWorker() + let response: GraphQLResponse = try await worker.performRequest(with: request) + + switch response { + case let .data(data): + return data.entities + case let .errors(error): + throw error + } + } + + private func queryString(priceIds: [String], cursor: String) -> String { + """ + query FiatPriceQuery { + entities: assets( + first: 100 + after: "\(cursor)", + filter: {id: {in: \(priceIds)}}) { + nodes { + id + priceUSD + priceChangeDay + } + pageInfo { + hasNextPage + endCursor + } + } + } + """ + } +} diff --git a/fearless/ApplicationLayer/Pricing/SubqueryPriceFetcher.swift b/fearless/ApplicationLayer/Pricing/SubqueryPriceFetcher.swift new file mode 100644 index 0000000000..90b9db5e95 --- /dev/null +++ b/fearless/ApplicationLayer/Pricing/SubqueryPriceFetcher.swift @@ -0,0 +1,13 @@ +import Foundation +import SSFModels +import RobinHood + +enum SubqueryPriceFetcherError: Error { + case missingBlockExplorer +} + +protocol SoraSubqueryPriceFetcher { + func fetchPriceOperation( + for chainAssets: [ChainAsset] + ) -> BaseOperation<[PriceData]> +} diff --git a/fearless/ApplicationLayer/Services/Balance/RemoteSubscription/AccountInfoStorageService.swift b/fearless/ApplicationLayer/Services/Balance/RemoteSubscription/AccountInfoStorageService.swift index aa213b39e5..a3baffc339 100644 --- a/fearless/ApplicationLayer/Services/Balance/RemoteSubscription/AccountInfoStorageService.swift +++ b/fearless/ApplicationLayer/Services/Balance/RemoteSubscription/AccountInfoStorageService.swift @@ -6,13 +6,6 @@ import SSFModels import SSFUtils import RobinHood -protocol AccountInfoRemoteService { - func fetchAccountInfos( - for chain: ChainModel, - wallet: MetaAccountModel - ) async throws -> [ChainAssetId: AccountInfo?] -} - final class AccountInfoRemoteServiceDefault: AccountInfoRemoteService { private let runtimeItemRepository: AsyncAnyRepository private let ethereumRemoteBalanceFetching: EthereumRemoteBalanceFetching diff --git a/fearless/ApplicationLayer/Services/Balance/WalletBalanceSubscription/WalletBalanceBuilder.swift b/fearless/ApplicationLayer/Services/Balance/WalletBalanceSubscription/WalletBalanceBuilder.swift index aa9900e894..60d20b37dd 100644 --- a/fearless/ApplicationLayer/Services/Balance/WalletBalanceSubscription/WalletBalanceBuilder.swift +++ b/fearless/ApplicationLayer/Services/Balance/WalletBalanceSubscription/WalletBalanceBuilder.swift @@ -23,7 +23,6 @@ final class WalletBalanceBuilder: WalletBalanceBuilderProtocol { let splitedChainAssets = split(chainAssets, for: wallet) let enabledChainAssets = splitedChainAssets.enabled - let disabledChainAssets = splitedChainAssets.disabled let enabledAssetFiatBalanceInfo = countBalance( for: enabledChainAssets, @@ -32,24 +31,12 @@ final class WalletBalanceBuilder: WalletBalanceBuilderProtocol { prices ) - let disabledAssetFiatBalanceInfo = countBalance( - for: disabledChainAssets, - wallet, - accountInfos, - prices - ) - let enabledAssetFiatBalance = enabledAssetFiatBalanceInfo.totalBalance - let disabledAssetFiatBalance = disabledAssetFiatBalanceInfo.totalBalance - let totalFiatValue = enabledAssetFiatBalance + disabledAssetFiatBalance - + let totalFiatValue = enabledAssetFiatBalance let enabledTotalDayChange = enabledAssetFiatBalanceInfo.totalDayChange - let disabledTotalDayChange = disabledAssetFiatBalanceInfo.totalDayChange - let totalDayChange = enabledTotalDayChange + disabledTotalDayChange - + let totalDayChange = enabledTotalDayChange let dayChangePercent = (totalDayChange / totalFiatValue) - - let isLoaded = enabledAssetFiatBalanceInfo.isLoaded && disabledAssetFiatBalanceInfo.isLoaded + let isLoaded = enabledAssetFiatBalanceInfo.isLoaded guard isLoaded else { return nil diff --git a/fearless/ApplicationLayer/Services/Balance/WalletBalanceSubscription/WalletBalanceSubscriptionAdapter.swift b/fearless/ApplicationLayer/Services/Balance/WalletBalanceSubscription/WalletBalanceSubscriptionAdapter.swift index 0f95d9aacd..d62e6da7ce 100644 --- a/fearless/ApplicationLayer/Services/Balance/WalletBalanceSubscription/WalletBalanceSubscriptionAdapter.swift +++ b/fearless/ApplicationLayer/Services/Balance/WalletBalanceSubscription/WalletBalanceSubscriptionAdapter.swift @@ -43,6 +43,11 @@ protocol WalletBalanceSubscriptionAdapterProtocol { listener: WalletBalanceSubscriptionListener ) + func subscribeNetworkManagementBalance( + wallet: MetaAccountModel, + listener: WalletBalanceSubscriptionListener + ) + func unsubscribe(listener: WalletBalanceSubscriptionListener) } @@ -51,9 +56,10 @@ enum WalletBalanceListenerType { case wallet(wallet: MetaAccountModel) case chainAsset(wallet: MetaAccountModel, chainAsset: ChainAsset) case chainAssets(chainAssets: [ChainAsset], wallet: MetaAccountModel) + case networkManagement(wallet: MetaAccountModel) } -final class WalletBalanceSubscriptionAdapter: WalletBalanceSubscriptionAdapterProtocol { +final class WalletBalanceSubscriptionAdapter: WalletBalanceSubscriptionAdapterProtocol, ChainAssetListBuilder { static let shared = createWalletBalanceAdapter() // MARK: - PriceLocalStorageSubscriber @@ -164,6 +170,27 @@ final class WalletBalanceSubscriptionAdapter: WalletBalanceSubscriptionAdapterPr } } + func subscribeNetworkManagementBalance( + wallet: MetaAccountModel, + listener: WalletBalanceSubscriptionListener + ) { + let weakListener = WeakWrapper(target: listener) + listenersLock.exclusivelyWrite { [weak self] in + self?.listeners.append(weakListener) + } + updateWalletsIfNeeded(with: wallet) + let selectedChainAssets = filterChainAssets( + with: NetworkManagmentFilter(identifier: wallet.networkManagmentFilter), + chainAssets: chainAssets, + wallet: wallet, + search: nil + ) + + if let balances = buildBalance(for: [wallet], chainAssets: selectedChainAssets) { + notify(listener: listener, result: .success(balances)) + } + } + func unsubscribe(listener: WalletBalanceSubscriptionListener) { listenersLock.exclusivelyWrite { [weak self] in guard let strongSelf = self else { @@ -195,7 +222,7 @@ final class WalletBalanceSubscriptionAdapter: WalletBalanceSubscriptionAdapterPr self.chainAssets = chainAssets self.wallets = (self.wallets + wallets).uniq(predicate: { $0.metaId }) subscribeToAccountInfo(for: wallets, chainAssets) - let currencies = wallets.map { $0.selectedCurrency } + let currencies = self.wallets.map { $0.selectedCurrency } subscribeToPrices(for: chainAssets, currencies: currencies) } @@ -203,11 +230,12 @@ final class WalletBalanceSubscriptionAdapter: WalletBalanceSubscriptionAdapterPr Task { do { async let wallets = self.walletRepository.fetchAll() - async let chainAssets = chainAssetFetcher.fetchAwait(shouldUseCache: false, filters: [], sortDescriptors: []) + async let chainAssets = chainAssetFetcher.fetchAwait(shouldUseCache: false, filters: [.enabledChains], sortDescriptors: []) try await handle(wallets, chainAssets) let accountInfos = try await fetchAccountInfos(wallets: wallets, chainAssets: chainAssets) self.accountInfos = accountInfos + self.buildAndNotifyIfNeeded(with: try await wallets.map { $0.metaId }, updatedChainAssets: try await chainAssets) } catch { let unwrappedListeners = listenersLock.concurrentlyRead { listeners.compactMap { @@ -319,6 +347,17 @@ final class WalletBalanceSubscriptionAdapter: WalletBalanceSubscriptionAdapterPr let balances = buildBalance(for: [wallet], chainAssets: chainAssets) { notify(listener: listener, result: .success(balances)) } + case let .networkManagement(wallet): + let selectedChainAssets = filterChainAssets( + with: NetworkManagmentFilter(identifier: wallet.networkManagmentFilter), + chainAssets: chainAssets, + wallet: wallet, + search: nil + ) + if updatedWalletsIds.contains(wallet.metaId), + let balances = buildBalance(for: [wallet], chainAssets: selectedChainAssets) { + notify(listener: listener, result: .success(balances)) + } } } } @@ -359,6 +398,10 @@ extension WalletBalanceSubscriptionAdapter: EventVisitorProtocol { let currencies = wallets.map { $0.selectedCurrency } subscribeToPrices(for: chainAssets, currencies: currencies) } + if wallet.networkManagmentFilter != event.account.networkManagmentFilter { + wallets[index] = event.account + buildAndNotifyIfNeeded(with: [wallet.metaId], updatedChainAssets: chainAssets) + } wallets[index] = event.account } } @@ -383,7 +426,7 @@ extension WalletBalanceSubscriptionAdapter: EventVisitorProtocol { Task { let chainAssets = try await chainAssetFetcher.fetchAwait( shouldUseCache: false, - filters: [], + filters: [.enabledChains], sortDescriptors: [] ) subscribeToAccountInfo(for: wallets, chainAssets) @@ -450,6 +493,7 @@ extension WalletBalanceSubscriptionAdapter: PriceLocalSubscriptionHandler { private extension WalletBalanceSubscriptionAdapter { static func createWalletBalanceAdapter() -> WalletBalanceSubscriptionAdapter { let chainRepository = ChainRepositoryFactory().createRepository( + for: NSPredicate.enabledCHain(), sortDescriptors: [NSSortDescriptor.chainsByAddressPrefix] ) let accountRepositoryFactory = AccountRepositoryFactory(storageFacade: UserDataStorageFacade.shared) diff --git a/fearless/ApplicationLayer/Services/FeatureToggle/FeatureToggleConfig.swift b/fearless/ApplicationLayer/Services/FeatureToggle/FeatureToggleConfig.swift index 25e9465d6b..c2732eed31 100644 --- a/fearless/ApplicationLayer/Services/FeatureToggle/FeatureToggleConfig.swift +++ b/fearless/ApplicationLayer/Services/FeatureToggle/FeatureToggleConfig.swift @@ -2,8 +2,9 @@ import Foundation struct FeatureToggleConfig: Decodable { let pendulumCaseEnabled: Bool? + let nftEnabled: Bool? static var defaultConfig: FeatureToggleConfig { - FeatureToggleConfig(pendulumCaseEnabled: false) + FeatureToggleConfig(pendulumCaseEnabled: false, nftEnabled: true) } } diff --git a/fearless/ApplicationLayer/Services/Onboarding/OnboardingService.swift b/fearless/ApplicationLayer/Services/Onboarding/OnboardingService.swift index a5cb7d05a4..089a7472c8 100644 --- a/fearless/ApplicationLayer/Services/Onboarding/OnboardingService.swift +++ b/fearless/ApplicationLayer/Services/Onboarding/OnboardingService.swift @@ -34,7 +34,8 @@ extension OnboardingService: OnboardingServiceProtocol { method: .get, endpoint: nil, headers: nil, - body: nil + body: nil, + timeout: 5 ) let worker = NetworkWorker() return try await worker.performRequest(with: request) diff --git a/fearless/ApplicationLayer/Services/QRService/QRExtractionService.swift b/fearless/ApplicationLayer/Services/QRService/QRExtractionService.swift deleted file mode 100644 index 16c513600a..0000000000 --- a/fearless/ApplicationLayer/Services/QRService/QRExtractionService.swift +++ /dev/null @@ -1,78 +0,0 @@ -import Foundation -import UIKit - -protocol QRExtractionServiceProtocol { - func extract( - from image: UIImage, - dispatchCompletionIn queue: DispatchQueue?, - completionBlock: @escaping (Result) -> Void - ) -} - -enum QRExtractionServiceError: Error { - case invalidImage - case detectorUnavailable - case noFeatures - case plainAddress(address: String) -} - -final class QRExtractionService { - private let processingQueue: DispatchQueue - - init(processingQueue: DispatchQueue) { - self.processingQueue = processingQueue - } - - private func proccess(image: UIImage) -> Result { - var optionalImage: CIImage? - - if let ciImage = CIImage(image: image) { - optionalImage = ciImage - } else if let cgImage = image.cgImage { - optionalImage = CIImage(cgImage: cgImage) - } - - guard let ciImage = optionalImage else { - return .failure(QRExtractionServiceError.invalidImage) - } - - let options = [CIDetectorAccuracy: CIDetectorAccuracyHigh] - guard let detector = CIDetector( - ofType: CIDetectorTypeQRCode, - context: nil, - options: options - ) else { - return .failure(QRExtractionServiceError.detectorUnavailable) - } - - let features = detector.features(in: ciImage) - - let receivedString = features.compactMap { ($0 as? CIQRCodeFeature)?.messageString }.first - - guard let receivedString = receivedString else { - return .failure(QRExtractionServiceError.noFeatures) - } - - return .success(receivedString) - } -} - -extension QRExtractionService: QRExtractionServiceProtocol { - func extract( - from image: UIImage, - dispatchCompletionIn queue: DispatchQueue?, - completionBlock: @escaping (Result) -> Void - ) { - processingQueue.async { - let result = self.proccess(image: image) - - if let queue = queue { - queue.async { - completionBlock(result) - } - } else { - completionBlock(result) - } - } - } -} diff --git a/fearless/ApplicationLayer/Services/SoraFiatService/SoraFiatService.swift b/fearless/ApplicationLayer/Services/SoraFiatService/SoraFiatService.swift new file mode 100644 index 0000000000..fa3bae1630 --- /dev/null +++ b/fearless/ApplicationLayer/Services/SoraFiatService/SoraFiatService.swift @@ -0,0 +1,73 @@ +import Foundation +import RobinHood +import sorawallet + +protocol FiatServiceObserverProtocol: AnyObject { + func processFiat(data: [FiatData]) +} + +protocol FiatServiceProtocol: AnyObject { + func getFiat() async -> [FiatData] +} + +struct FiatServiceObserver { + weak var observer: FiatServiceObserverProtocol? +} + +final class FiatService { + static let shared = FiatService() + private let operationManager = OperationManager() + private var expiredDate = Date() + private var fiatData: [FiatData] = [] + private var observers: [FiatServiceObserver] = [] + private let syncQueue = DispatchQueue(label: "co.jp.soramitsu.sora.fiat.service") + + private func updateFiatData() { + let queryOperation = SubqueryFiatInfoOperation<[FiatData]>(baseUrl: ApplicationConfig.shared.soraSubqueryUrl) + queryOperation.completionBlock = { [weak self] in + guard let self, let response = try? queryOperation.extractNoCancellableResultData() else { + return + } + self.fiatData = response + self.expiredDate = Date().addingTimeInterval(20) + } + operationManager.enqueue(operations: [queryOperation], in: .transient) + } + + private func updateFiatDataAwait() async -> [FiatData] { + let queryOperation = SubqueryFiatInfoOperation<[FiatData]>(baseUrl: ApplicationConfig.shared.soraSubqueryUrl) + operationManager.enqueue(operations: [queryOperation], in: .transient) + + return await withCheckedContinuation { continuation in + queryOperation.completionBlock = { + guard let response = try? queryOperation.extractNoCancellableResultData() else { + continuation.resume(returning: []) + return + } + continuation.resume(returning: response) + } + } + } + + private func updateFiatData(with data: [FiatData]) async { + fiatData = data + expiredDate = Date().addingTimeInterval(600) + } +} + +extension FiatService: FiatServiceProtocol { + func getFiat() async -> [FiatData] { + if expiredDate < Date() { + updateFiatData() + } + + if !fiatData.isEmpty { + return fiatData + } + + let response = await updateFiatDataAwait() + await updateFiatData(with: response) + + return response + } +} diff --git a/fearless/ApplicationLayer/Services/SoraFiatService/SubqueryFiatInfoOperation.swift b/fearless/ApplicationLayer/Services/SoraFiatService/SubqueryFiatInfoOperation.swift new file mode 100644 index 0000000000..5621b5653d --- /dev/null +++ b/fearless/ApplicationLayer/Services/SoraFiatService/SubqueryFiatInfoOperation.swift @@ -0,0 +1,57 @@ +import RobinHood +import sorawallet +import Foundation + +public final class SubqueryFiatInfoOperation: BaseOperation { + private let httpProvider: SoramitsuHttpClientProviderImpl + private let soraNetworkClient: SoramitsuNetworkClient + private let subQueryClient: SoraWalletBlockExplorerInfo + private let baseUrl: URL + + public init(baseUrl: URL) { + self.baseUrl = baseUrl + httpProvider = SoramitsuHttpClientProviderImpl() + soraNetworkClient = SoramitsuNetworkClient(timeout: 60000, logging: true, provider: httpProvider) + let provider = SoraRemoteConfigProvider( + client: soraNetworkClient, + commonUrl: "https://config.polkaswap2.io/prod/common.json", + mobileUrl: "https://config.polkaswap2.io/prod/mobile.json" + ) + let configBuilder = provider.provide() + + subQueryClient = SoraWalletBlockExplorerInfo(networkClient: soraNetworkClient, soraRemoteConfigBuilder: configBuilder) + + super.init() + } + + override public func main() { + super.main() + + if isCancelled { + return + } + + if result != nil { + return + } + + let semaphore = DispatchSemaphore(value: 0) + + var optionalCallResult: Result? + + DispatchQueue.main.async { + self.subQueryClient.getFiat(completionHandler: { [self] requestResult, _ in + + if let data = requestResult as? ResultType { + optionalCallResult = .success(data) + } + + semaphore.signal() + + result = optionalCallResult + }) + } + + semaphore.wait() + } +} diff --git a/fearless/ApplicationLayer/Services/TransactionObserver/SubstrateTransactionObserver.swift b/fearless/ApplicationLayer/Services/TransactionObserver/SubstrateTransactionObserver.swift new file mode 100644 index 0000000000..24a612b242 --- /dev/null +++ b/fearless/ApplicationLayer/Services/TransactionObserver/SubstrateTransactionObserver.swift @@ -0,0 +1,46 @@ +import Foundation +import SSFChainConnection +import SSFUtils + +final class SubstrateTransactionObserver: TransactionObserver { + private let engine: SubstrateConnection + private var activeRequestIds: [UInt16] = [] + + init(engine: SubstrateConnection) { + self.engine = engine + } + + deinit { + activeRequestIds.forEach { try? engine.unsubsribe($0) } + } + + func subscribe(transactionHash: String) async throws -> AsyncThrowingStream { + AsyncThrowingStream { continuation in + let updateClosure: (JSONRPCSubscriptionUpdate) -> Void = { statusUpdate in + let state = statusUpdate.params.result + continuation.yield(state) + } + + let failureClosure: (Error, Bool) -> Void = { error, _ in + continuation.finish(throwing: error) + } + + let requestId = engine.generateRequestId() + activeRequestIds.append(requestId) + let subscription = JSONRPCSubscription( + requestId: requestId, + requestData: .init(), + requestOptions: .init(resendOnReconnect: true), + updateClosure: updateClosure, + failureClosure: failureClosure + ) + + subscription.remoteId = transactionHash + engine.addSubscription(subscription) + } + } + + private func cancelSubscription(requestId: UInt16) { + engine.cancelForIdentifier(requestId) + } +} diff --git a/fearless/ApplicationLayer/Services/TransactionObserver/TransactionObserver.swift b/fearless/ApplicationLayer/Services/TransactionObserver/TransactionObserver.swift new file mode 100644 index 0000000000..da32363f19 --- /dev/null +++ b/fearless/ApplicationLayer/Services/TransactionObserver/TransactionObserver.swift @@ -0,0 +1,5 @@ +import Foundation + +protocol TransactionObserver { + func subscribe(transactionHash: String) async throws -> AsyncThrowingStream +} diff --git a/fearless/ApplicationLayer/Services/Transfer/Tokens/EthereumTransferService.swift b/fearless/ApplicationLayer/Services/Transfer/Tokens/EthereumTransferService.swift index 1eaf14dd2c..b3df8682ab 100644 --- a/fearless/ApplicationLayer/Services/Transfer/Tokens/EthereumTransferService.swift +++ b/fearless/ApplicationLayer/Services/Transfer/Tokens/EthereumTransferService.swift @@ -107,7 +107,14 @@ final class EthereumTransferService: BaseEthereumService, TransferServiceProtoco try subscribe() } } catch { - listener.didReceiveFeeError(feeError: error) + Task { + do { + let fee = try await estimateFee(for: transfer) + listener.didReceiveFee(fee: fee) + } catch { + listener.didReceiveFeeError(feeError: error) + } + } } } diff --git a/fearless/ApplicationLayer/Services/WalletConnect/Model/WalletConnectExtrinsic.swift b/fearless/ApplicationLayer/Services/WalletConnect/Model/WalletConnectExtrinsic.swift index ee2414c74f..8715f38cdd 100644 --- a/fearless/ApplicationLayer/Services/WalletConnect/Model/WalletConnectExtrinsic.swift +++ b/fearless/ApplicationLayer/Services/WalletConnect/Model/WalletConnectExtrinsic.swift @@ -1,6 +1,7 @@ import Foundation import SSFUtils import BigInt +import SSFModels struct WalletConnectExtrinsic: Codable { let address: String @@ -21,6 +22,15 @@ enum WalletConnectPolkadotCall: Codable { case raw(bytes: Data) case callable(value: RuntimeCall) + var payloadType: ExtrinsicBuilder.PayloadType { + switch self { + case .callable: + return .regular + case .raw: + return .rawData + } + } + func encode(to encoder: Encoder) throws { switch self { case let .raw(bytes): diff --git a/fearless/ApplicationLayer/Services/WalletConnect/Model/WalletConnectPayload.swift b/fearless/ApplicationLayer/Services/WalletConnect/Model/WalletConnectPayload.swift index 3fb2172e4c..714bef2f89 100644 --- a/fearless/ApplicationLayer/Services/WalletConnect/Model/WalletConnectPayload.swift +++ b/fearless/ApplicationLayer/Services/WalletConnect/Model/WalletConnectPayload.swift @@ -1,6 +1,7 @@ import Foundation import Commons import SSFUtils +import SSFModels struct WalletConnectPayload { let address: String? diff --git a/fearless/ApplicationLayer/Services/WalletConnect/WalletConnectPolkadorSigner.swift b/fearless/ApplicationLayer/Services/WalletConnect/WalletConnectPolkadorSigner.swift index 55156cb618..79e7edfa15 100644 --- a/fearless/ApplicationLayer/Services/WalletConnect/WalletConnectPolkadorSigner.swift +++ b/fearless/ApplicationLayer/Services/WalletConnect/WalletConnectPolkadorSigner.swift @@ -55,11 +55,11 @@ final class WalletConnectPolkadorSigner: WalletConnectPayloadSigner { let transaction = try params.get(TransactionPayload.self) let builder = try await createBuilder(for: transaction) let coderFactory = try await fetchCoderFactory() - let signature = try builder.buildSignature( + let signaturePayload = try builder.buildSignaturePayload( encodingBy: coderFactory.createEncoder(), metadata: coderFactory.metadata ) - let signedRawData = try transactionSigner.sign(signature).rawData() + let signedRawData = try transactionSigner.sign(signaturePayload).rawData() let encoded = try encode(rawData: signedRawData, encoder: coderFactory.createEncoder()) let result = WalletConnectPolkadotSignature( id: UInt.random(in: 0 ..< UInt.max), @@ -101,6 +101,7 @@ final class WalletConnectPolkadorSigner: WalletConnectPayloadSigner { .with(address: transaction.address) .with(nonce: UInt32(transaction.nonce)) .with(era: transaction.era, blockHash: transaction.blockHash) + .with(payloadType: transaction.method.payloadType) switch transaction.method { case let .callable(value): diff --git a/fearless/ApplicationLayer/Services/WalletConnect/WalletConnectPolkadotParser.swift b/fearless/ApplicationLayer/Services/WalletConnect/WalletConnectPolkadotParser.swift index 75fe971631..9bd1c6d6f0 100644 --- a/fearless/ApplicationLayer/Services/WalletConnect/WalletConnectPolkadotParser.swift +++ b/fearless/ApplicationLayer/Services/WalletConnect/WalletConnectPolkadotParser.swift @@ -15,10 +15,6 @@ final class WalletConnectPolkadorParserImpl: WalletConnectPolkadotParser { ChainRegistryFacade.sharedRegistry }() - private lazy var operationQueue = { - OperationQueue() - }() - func parse( transactionPayload: TransactionPayload, chain: ChainModel @@ -68,27 +64,16 @@ final class WalletConnectPolkadorParserImpl: WalletConnectPolkadotParser { guard let runtimeProvider = chainRegistry.getRuntimeProvider(for: chain.chainId) else { throw RuntimeProviderError.providerUnavailable } - let fetchCoderFactoryOperation = runtimeProvider.fetchCoderFactoryOperation() - operationQueue.addOperation(fetchCoderFactoryOperation) - - return try await withCheckedThrowingContinuation { continuation in - fetchCoderFactoryOperation.completionBlock = { - do { - let codingFactory = try fetchCoderFactoryOperation.extractNoCancellableResultData() - let methodData = try Data(hexStringSSF: transactionPayload.method) - let methodDecoder = try codingFactory.createDecoder(from: methodData) + let codingFactory = try await runtimeProvider.fetchCoderFactory() + let methodData = try Data(hexStringSSF: transactionPayload.method) + let methodDecoder = try codingFactory.createDecoder(from: methodData) - let call: WalletConnectPolkadotCall - if let callableMethod: RuntimeCall = try? methodDecoder.read(of: KnownType.call.rawValue) { - call = .callable(value: callableMethod) - } else { - call = .raw(bytes: methodData) - } - continuation.resume(returning: call) - } catch { - continuation.resume(throwing: error) - } - } + let call: WalletConnectPolkadotCall + if let callableMethod: RuntimeCall = try? methodDecoder.read(of: KnownType.call.rawValue) { + call = .callable(value: callableMethod) + } else { + call = .raw(bytes: methodData) } + return call } } diff --git a/fearless/ApplicationLayer/StakingRewards/Requests/StakingRewardsRequest.swift b/fearless/ApplicationLayer/StakingRewards/Requests/StakingRewardsRequest.swift index e1a5e1b846..bc23af7a6d 100644 --- a/fearless/ApplicationLayer/StakingRewards/Requests/StakingRewardsRequest.swift +++ b/fearless/ApplicationLayer/StakingRewards/Requests/StakingRewardsRequest.swift @@ -1,6 +1,7 @@ import Foundation import SSFUtils import RobinHood +import SSFModels class StakingRewardsRequest: RequestConfig { init( diff --git a/fearless/Assets.xcassets/colors/colorColdGreen.colorset/Contents.json b/fearless/Assets.xcassets/colors/colorColdGreen.colorset/Contents.json index 90bfbb4389..9e966c9717 100644 --- a/fearless/Assets.xcassets/colors/colorColdGreen.colorset/Contents.json +++ b/fearless/Assets.xcassets/colors/colorColdGreen.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "161", - "green" : "200", - "red" : "9" + "blue" : "0xA1", + "green" : "0xC8", + "red" : "0x09" } }, "idiom" : "universal" diff --git a/fearless/Assets.xcassets/iconAddTokenPair.imageset/Contents.json b/fearless/Assets.xcassets/iconAddTokenPair.imageset/Contents.json new file mode 100644 index 0000000000..af118dbf0c --- /dev/null +++ b/fearless/Assets.xcassets/iconAddTokenPair.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "icon_add_token_pair.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/fearless/Assets.xcassets/iconAddTokenPair.imageset/icon_add_token_pair.pdf b/fearless/Assets.xcassets/iconAddTokenPair.imageset/icon_add_token_pair.pdf new file mode 100644 index 0000000000..ebde11c543 Binary files /dev/null and b/fearless/Assets.xcassets/iconAddTokenPair.imageset/icon_add_token_pair.pdf differ diff --git a/fearless/Assets.xcassets/iconChevronRight.imageset/Chevron.pdf b/fearless/Assets.xcassets/iconChevronRight.imageset/Chevron.pdf new file mode 100644 index 0000000000..dcd514aaab Binary files /dev/null and b/fearless/Assets.xcassets/iconChevronRight.imageset/Chevron.pdf differ diff --git a/fearless/Assets.xcassets/iconChevronRight.imageset/Contents.json b/fearless/Assets.xcassets/iconChevronRight.imageset/Contents.json new file mode 100644 index 0000000000..710e93101a --- /dev/null +++ b/fearless/Assets.xcassets/iconChevronRight.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "Chevron.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/fearless/Assets.xcassets/iconLpBanner.imageset/Banner.pdf b/fearless/Assets.xcassets/iconLpBanner.imageset/Banner.pdf new file mode 100644 index 0000000000..8cab036f3f Binary files /dev/null and b/fearless/Assets.xcassets/iconLpBanner.imageset/Banner.pdf differ diff --git a/fearless/Assets.xcassets/iconLpBanner.imageset/Contents.json b/fearless/Assets.xcassets/iconLpBanner.imageset/Contents.json new file mode 100644 index 0000000000..b6a4904df5 --- /dev/null +++ b/fearless/Assets.xcassets/iconLpBanner.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "Banner.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/fearless/Common/AddressChainDefiner/AddressChainDefiner.swift b/fearless/Common/AddressChainDefiner/AddressChainDefiner.swift index 28d21cdb5a..7f7413bcfd 100644 --- a/fearless/Common/AddressChainDefiner/AddressChainDefiner.swift +++ b/fearless/Common/AddressChainDefiner/AddressChainDefiner.swift @@ -56,6 +56,9 @@ final class AddressChainDefiner { let chains = try? fetchOperation.extractNoCancellableResultData() let posssibleChains = chains?.filter { [weak self, address] chain in guard let strongSelf = self else { return false } + guard strongSelf.chainIsEnabled(chain: chain) else { + return false + } return strongSelf.validate(address: address, for: chain).isValidOrSame } continuation.resume(returning: posssibleChains) @@ -72,4 +75,15 @@ final class AddressChainDefiner { } return .valid(address) } + + private func chainIsEnabled(chain: ChainModel) -> Bool { + let chainAssets = chain.chainAssets + let enabledAssetIds: [String] = wallet.assetsVisibility + .filter { !$0.hidden } + .map { $0.assetId } + let enabled = chainAssets.filter { + enabledAssetIds.contains($0.identifier) + } + return enabled.isNotEmpty + } } diff --git a/fearless/Common/Configs/ApplicationConfigs.swift b/fearless/Common/Configs/ApplicationConfigs.swift index 3627881f75..1762211e46 100644 --- a/fearless/Common/Configs/ApplicationConfigs.swift +++ b/fearless/Common/Configs/ApplicationConfigs.swift @@ -162,9 +162,9 @@ extension ApplicationConfig: ApplicationConfigProtocol, XcmConfigProtocol { var chainsSourceUrl: URL { #if F_DEV - GitHubUrl.url(suffix: "chains/v9/chains_dev.json", branch: .developFree) + GitHubUrl.url(suffix: "chains/v10/chains_dev.json", branch: .developFree) #else - GitHubUrl.url(suffix: "chains/v9/chains.json") + GitHubUrl.url(suffix: "chains/v10/chains.json") #endif } @@ -215,7 +215,15 @@ extension ApplicationConfig: ApplicationConfigProtocol, XcmConfigProtocol { } var onboardingConfig: URL? { - GitHubUrl.url(suffix: "appConfigs/onboarding/mobile v2.json", branch: .developFree) + #if F_DEV + GitHubUrl.url(suffix: "appConfigs/onboarding/mobile v2.json", branch: .developFree) + #else + GitHubUrl.url(suffix: "appConfigs/onboarding/mobile v2.json") + #endif + } + + var soraSubqueryUrl: URL { + URL(string: "https://api.subquery.network/sq/sora-xor/sora-prod")! } } diff --git a/fearless/Common/DataProvider/ExistentialDeposit.swift b/fearless/Common/DataProvider/ExistentialDeposit.swift index 7159ff2d77..a6a345bf05 100644 --- a/fearless/Common/DataProvider/ExistentialDeposit.swift +++ b/fearless/Common/DataProvider/ExistentialDeposit.swift @@ -41,46 +41,23 @@ final class ExistentialDepositService: RuntimeConstantFetching, ExistentialDepos return } - if - let existentialDeposit = chainAsset.asset.existentialDeposit, - let result = BigUInt(string: existentialDeposit) { - completion(.success(result)) - return - } - switch chainAsset.chainAssetType { - case .normal, .ormlChain, .soraAsset: + case .equilibrium: fetchConstant( - for: .existentialDeposit, + for: .equilibriumExistentialDeposit, runtimeCodingService: runtimeService, operationManager: operationManager ) { result in completion(result) } - case - .ormlAsset, - .foreignAsset, - .stableAssetPoolToken, - .liquidCrowdloan, - .vToken, - .vsToken, - .stable, - .assetId, - .token2, - .xcm: - fetchSubAssetsExistentialDeposit(chainAsset: chainAsset, completion: completion) - case .equilibrium: + default: fetchConstant( - for: .equilibriumExistentialDeposit, + for: .existentialDeposit, runtimeCodingService: runtimeService, operationManager: operationManager ) { result in completion(result) } - case .assets: - fetchAssetsExistentialDeposit(chainAsset: chainAsset, completion: completion) - case .none: - break } } diff --git a/fearless/Common/DataProvider/PriceProviderFactory.swift b/fearless/Common/DataProvider/PriceProviderFactory.swift index 530a5efa72..8cf614e5ff 100644 --- a/fearless/Common/DataProvider/PriceProviderFactory.swift +++ b/fearless/Common/DataProvider/PriceProviderFactory.swift @@ -4,61 +4,28 @@ import SSFModels import SSFSingleValueCache protocol PriceProviderFactoryProtocol { - func getPricesProvider(currencies: [Currency]?) -> AnySingleValueProvider<[PriceData]> + func getPricesProvider(currencies: [Currency]?, chainAssets: [ChainAsset]) -> AnySingleValueProvider<[PriceData]> } -class PriceProviderFactory { - static let shared = PriceProviderFactory(storageFacade: SubstrateDataStorageFacade.shared) - - private var providers: [AssetModel.PriceId: WeakWrapper] = [:] - private var remoteFetchTimer: Timer? - - private let storageFacade: StorageFacadeProtocol +final class PriceProviderFactory: PriceProviderFactoryProtocol { private lazy var executionQueue: OperationQueue = { let queue = OperationQueue() queue.qualityOfService = .userInitiated return queue }() - private init(storageFacade: StorageFacadeProtocol) { - self.storageFacade = storageFacade - } - - private func clearIfNeeded() { - providers = providers.filter { $0.value.target != nil } - } -} - -extension PriceProviderFactory: PriceProviderFactoryProtocol { - func getPricesProvider(currencies: [Currency]?) -> AnySingleValueProvider<[SSFModels.PriceData]> { - let identifier = currencies?.compactMap { $0.id }.sorted().joined(separator: ".") ?? PriceDataSource.defaultIdentifier - - if let provider = providers[identifier]?.target as? SingleValueProvider<[PriceData]> { - if remoteFetchTimer == nil { - DispatchQueue.main.async { - self.remoteFetchTimer = Timer.scheduledTimer(withTimeInterval: 10, repeats: false, block: { [weak self] timer in - timer.invalidate() - self?.remoteFetchTimer = nil - }) - } - provider.refresh() - } - return AnySingleValueProvider(provider) - } - + func getPricesProvider(currencies: [Currency]?, chainAssets: [ChainAsset]) -> AnySingleValueProvider<[SSFModels.PriceData]> { let repository: CoreDataRepository = SingleValueCacheRepositoryFactoryDefault().createSingleValueCacheRepository() - let source = PriceDataSource(currencies: currencies) - let trigger: DataProviderEventTrigger = [.onInitialization, .onFetchPage] + let source = PriceDataSource(currencies: currencies, chainAssets: chainAssets) + let trigger: DataProviderEventTrigger = [.onFetchPage] let provider = SingleValueProvider( - targetIdentifier: source.identifier, + targetIdentifier: PriceDataSource.defaultIdentifier, source: AnySingleValueProviderSource(source), repository: AnyDataProviderRepository(repository), updateTrigger: trigger, executionQueue: executionQueue ) - providers[identifier] = WeakWrapper(target: provider) - return AnySingleValueProvider(provider) } } diff --git a/fearless/Common/DataProvider/Sources/PriceDataSource.swift b/fearless/Common/DataProvider/Sources/PriceDataSource.swift index ed872221dd..e1e57260b2 100644 --- a/fearless/Common/DataProvider/Sources/PriceDataSource.swift +++ b/fearless/Common/DataProvider/Sources/PriceDataSource.swift @@ -1,10 +1,13 @@ import Foundation - -import Foundation +import sorawallet import RobinHood import SoraKeystore import SSFModels +enum PriceDataSourceError: Swift.Error { + case memoryError +} + final class PriceDataSource: SingleValueProviderSourceProtocol { static let defaultIdentifier: String = "all-chainAsset-prices-usd" typealias Model = [PriceData] @@ -27,78 +30,165 @@ final class PriceDataSource: SingleValueProviderSourceProtocol { ChainlinkOperationFactoryImpl() }() - private lazy var chainAssets: [ChainAsset] = { - ChainRegistryFacade.sharedRegistry.availableChains.map { $0.chainAssets }.reduce([], +) + private lazy var soraOperationFactory: SoraSubqueryPriceFetcher = { + SoraSubqueryPriceFetcherDefault() }() - init(currencies: [Currency]?) { + private let chainRegistry = ChainRegistryFacade.sharedRegistry + + private lazy var chainAssets: [ChainAsset] = [] + + init(currencies: [Currency]?, chainAssets: [ChainAsset]) { self.currencies = currencies + self.chainAssets = chainAssets + setup() } func fetchOperation() -> CompoundOperationWrapper<[PriceData]?> { + guard chainAssets.isNotEmpty else { + return CompoundOperationWrapper.createWithResult([]) + } + let coingeckoOperation = createCoingeckoOperation() let chainlinkOperations = createChainlinkOperations() + let soraSubqueryOperation = createSoraSubqueryOperation() let targetOperation: BaseOperation<[PriceData]?> = ClosureOperation { [weak self] in - var coingeckoPrices = try coingeckoOperation.extractNoCancellableResultData() + guard let self else { + throw PriceDataSourceError.memoryError + } + + var prices: [PriceData] = [] + let coingeckoPrices = try coingeckoOperation.extractNoCancellableResultData() let chainlinkPrices = chainlinkOperations.compactMap { try? $0.extractNoCancellableResultData() } + let soraSubqueryPrices = (try? soraSubqueryOperation.extractNoCancellableResultData()) ?? [] - let replacedFiatDayChange: [PriceData] = chainlinkPrices.compactMap { chainlinkPrice in - let coingeckoPrice = coingeckoPrices.first(where: { $0.coingeckoPriceId == chainlinkPrice.coingeckoPriceId }) - return chainlinkPrice.replaceFiatDayChange(fiatDayChange: coingeckoPrice?.fiatDayChange) - } + prices = self.merge(coingeckoPrices: coingeckoPrices, chainlinkPrices: chainlinkPrices) + prices = self.merge(coingeckoPrices: prices, soraSubqueryPrices: soraSubqueryPrices) - if chainlinkPrices.count != chainlinkOperations.count || chainlinkOperations.isEmpty { - let chainlinkPriceChainAsset = self?.chainAssets.filter { $0.asset.priceProvider?.type == .chainlink } - let failedPriceId = chainlinkPriceChainAsset?.compactMap { $0.asset.coingeckoPriceId }.diff(from: chainlinkPrices.map { $0.coingeckoPriceId }) - let replacedPrices = coingeckoPrices.compactMap { price in - if failedPriceId?.contains(price.coingeckoPriceId) == true { - guard let failedChainlinkCHainAsset = chainlinkPriceChainAsset?.first(where: { $0.asset.coingeckoPriceId == price.coingeckoPriceId }) else { - return price - } - return PriceData( - currencyId: price.currencyId, - priceId: failedChainlinkCHainAsset.asset.priceProvider?.id ?? price.priceId, - price: price.price, - fiatDayChange: price.fiatDayChange, - coingeckoPriceId: price.coingeckoPriceId - ) - } - return nil - } - coingeckoPrices = coingeckoPrices + replacedPrices - } - - return coingeckoPrices + replacedFiatDayChange + return prices } targetOperation.addDependency(coingeckoOperation) + targetOperation.addDependency(soraSubqueryOperation) chainlinkOperations.forEach { targetOperation.addDependency($0) } return CompoundOperationWrapper( targetOperation: targetOperation, - dependencies: [coingeckoOperation] + chainlinkOperations + dependencies: [coingeckoOperation, soraSubqueryOperation] + chainlinkOperations ) } // MARK: - Private methods + private func merge(coingeckoPrices: [PriceData], chainlinkPrices: [PriceData]) -> [PriceData] { + if chainlinkPrices.isEmpty { + let prices = makePrices(from: coingeckoPrices, for: .chainlink) + return coingeckoPrices + prices + } + let caPriceIds = Set(chainAssets.compactMap { $0.asset.coingeckoPriceId }) + let sqPriceIds = Set(chainlinkPrices.compactMap { $0.coingeckoPriceId }) + + let replacedFiatDayChange: [PriceData] = chainlinkPrices.compactMap { chainlinkPrice in + let coingeckoPrice = coingeckoPrices.first(where: { $0.coingeckoPriceId == chainlinkPrice.coingeckoPriceId }) + return chainlinkPrice.replaceFiatDayChange(fiatDayChange: coingeckoPrice?.fiatDayChange) + } + + let filtered = coingeckoPrices.filter { coingeckoPrice in + guard let coingeckoPriceId = coingeckoPrice.coingeckoPriceId else { + return true + } + return !caPriceIds.intersection(sqPriceIds).contains(coingeckoPriceId) + } + + return filtered + replacedFiatDayChange + } + + private func merge(coingeckoPrices: [PriceData], soraSubqueryPrices: [PriceData]) -> [PriceData] { + if soraSubqueryPrices.isEmpty { + let prices = makePrices(from: coingeckoPrices, for: .sorasubquery) + return coingeckoPrices + prices + } + let caPriceIds = Set(chainAssets.compactMap { $0.asset.priceId }) + let sqPriceIds = Set(soraSubqueryPrices.compactMap { $0.priceId }) + + let replacedFiatDayChange: [PriceData] = soraSubqueryPrices.compactMap { soraSubqueryPrice in + let coingeckoPrice = coingeckoPrices.first(where: { $0.priceId == soraSubqueryPrice.priceId }) + return soraSubqueryPrice.replaceFiatDayChange(fiatDayChange: coingeckoPrice?.fiatDayChange) + } + + let filtered = coingeckoPrices.filter { coingeckoPrice in + let chainAsset = chainAssets.first { $0.asset.coingeckoPriceId == coingeckoPrice.priceId } + guard let priceId = chainAsset?.asset.priceId else { + return true + } + return !caPriceIds.intersection(sqPriceIds).contains(priceId) + } + + return filtered + replacedFiatDayChange + } + + private func makePrices(from coingeckoPrices: [PriceData], for type: PriceProviderType) -> [PriceData] { + let typePriceChainAsset = chainAssets + .filter { $0.asset.priceProvider?.type == type } + + let prices = coingeckoPrices.filter { coingeckoPrice in + typePriceChainAsset.contains { chainAsset in + chainAsset.asset.coingeckoPriceId == coingeckoPrice.coingeckoPriceId + } + } + + let newPrices: [PriceData] = prices.compactMap { price in + guard let chainAsset = typePriceChainAsset.first(where: { $0.asset.coingeckoPriceId == price.coingeckoPriceId }) else { + return nil + } + return PriceData( + currencyId: price.currencyId, + priceId: chainAsset.asset.priceId ?? price.priceId, + price: price.price, + fiatDayChange: price.fiatDayChange, + coingeckoPriceId: price.coingeckoPriceId + ) + } + return newPrices + } + + // MARK: - Operations + + private func createSoraSubqueryOperation() -> BaseOperation<[PriceData]> { + guard currencies?.count == 1, currencies?.first?.id == Currency.defaultCurrency().id else { + return BaseOperation.createWithResult([]) + } + + let chainAssets = chainAssets.filter { $0.asset.priceProvider?.type == .sorasubquery } + guard chainAssets.isNotEmpty else { + return BaseOperation.createWithResult([]) + } + + let operation = soraOperationFactory.fetchPriceOperation(for: chainAssets) + return operation + } + private func createCoingeckoOperation() -> BaseOperation<[PriceData]> { let currencies = self.currencies ?? [SelectedWalletSettings.shared.value?.selectedCurrency].compactMap { $0 } let priceIds = chainAssets .map { $0.asset.coingeckoPriceId } .compactMap { $0 } .uniq(predicate: { $0 }) + guard priceIds.isNotEmpty else { + return BaseOperation.createWithResult([]) + } let operation = coingeckoOperationFactory.fetchPriceOperation(for: priceIds, currencies: currencies) return operation } private func createChainlinkOperations() -> [BaseOperation] { + return [] guard currencies?.count == 1, currencies?.first?.id == Currency.defaultCurrency().id else { return [] } diff --git a/fearless/Common/DataProvider/Sources/Rewards/SubqueryRewardsSource.swift b/fearless/Common/DataProvider/Sources/Rewards/SubqueryRewardsSource.swift index d4f0f5590e..18d7970842 100644 --- a/fearless/Common/DataProvider/Sources/Rewards/SubqueryRewardsSource.swift +++ b/fearless/Common/DataProvider/Sources/Rewards/SubqueryRewardsSource.swift @@ -2,6 +2,7 @@ import Foundation import RobinHood import SSFUtils import BigInt +import SSFModels final class ParachainSubqueryRewardsSource { typealias Model = [SubqueryRewardItemData] diff --git a/fearless/Common/DataProvider/Sources/Rewards/SubqueryStakeSource.swift b/fearless/Common/DataProvider/Sources/Rewards/SubqueryStakeSource.swift index de45574d58..ed26b04fdc 100644 --- a/fearless/Common/DataProvider/Sources/Rewards/SubqueryStakeSource.swift +++ b/fearless/Common/DataProvider/Sources/Rewards/SubqueryStakeSource.swift @@ -2,6 +2,7 @@ import Foundation import RobinHood import SSFUtils import BigInt +import SSFModels final class SubqueryStakeSource { typealias Model = [SubqueryStakeChangeData] diff --git a/fearless/Common/DataProvider/Sources/SubqueryEraStakersInfoSource.swift b/fearless/Common/DataProvider/Sources/SubqueryEraStakersInfoSource.swift index 133839e8e9..3e6f7997e4 100644 --- a/fearless/Common/DataProvider/Sources/SubqueryEraStakersInfoSource.swift +++ b/fearless/Common/DataProvider/Sources/SubqueryEraStakersInfoSource.swift @@ -1,6 +1,7 @@ import RobinHood import Foundation import SSFUtils +import SSFModels final class SubqueryEraStakersInfoSource { let url: URL diff --git a/fearless/Common/DataProvider/Subscription/PriceLocalStorageSubscriber.swift b/fearless/Common/DataProvider/Subscription/PriceLocalStorageSubscriber.swift index 535cf48014..47ae63aeae 100644 --- a/fearless/Common/DataProvider/Subscription/PriceLocalStorageSubscriber.swift +++ b/fearless/Common/DataProvider/Subscription/PriceLocalStorageSubscriber.swift @@ -10,21 +10,47 @@ protocol PriceLocalStorageSubscriber where Self: AnyObject { } struct PriceLocalStorageSubscriberListener { + enum Handler { + case price + case prices + } + let listener: WeakWrapper let chainAssets: [ChainAsset] let currencies: [Currency] + let handler: Handler } final class PriceLocalStorageSubscriberImpl: PriceLocalStorageSubscriber { static let shared = PriceLocalStorageSubscriberImpl() + private let eventCenter = EventCenter.shared + private lazy var provider: AnySingleValueProvider<[PriceData]> = { + setupProvider() + }() private lazy var priceLocalSubscriber: PriceProviderFactoryProtocol = { - PriceProviderFactory.shared + PriceProviderFactory() }() + private var remoteFetchTimer: Timer? + private var fetchOperation: CompoundOperationWrapper<[PriceData]?>? + private var isAlreadyRefrishing: Bool = false + private var listeners: [PriceLocalStorageSubscriberListener] = [] + private var sourcedCurrencies: Set = [] + + private var chainAssets: [ChainAsset] = [] + private let chainsRepository: AsyncCoreDataRepositoryDefault - private init() {} + private init() { + chainsRepository = ChainRepositoryFactory().createAsyncRepository() + setup() + } + + private func setup() { + eventCenter.add(observer: self) + refreshChainsAndSubscribe() + } // MARK: - PriceLocalStorageSubscriber @@ -47,49 +73,81 @@ final class PriceLocalStorageSubscriberImpl: PriceLocalStorageSubscriber { currencies: [Currency]?, listener: PriceLocalSubscriptionHandler ) -> AnySingleValueProvider<[PriceData]> { - appendLisnenerIfNeeded(listener, chainAssets: [chainAsset], currencies: currencies) - let providerCurrencies = listeners.map { $0.currencies }.compactMap { $0 }.reduce([], +).uniq(predicate: { $0.id }) - let priceProvider = priceLocalSubscriber.getPricesProvider(currencies: providerCurrencies) + appendLisnenerIfNeeded( + listener, + chainAssets: [chainAsset], + currencies: currencies, + handler: .price + ) + guard !didUpdateProvider(for: currencies) else { + return provider + } + refreshProviderIfPossible() + return provider + } - let updateClosure = { [weak self] (changes: [DataProviderChange<[PriceData]>]) in + func subscribeToPrices( + for chainAssets: [ChainAsset], + currencies: [Currency]?, + listener: PriceLocalSubscriptionHandler + ) -> AnySingleValueProvider<[PriceData]> { + appendLisnenerIfNeeded( + listener, + chainAssets: chainAssets, + currencies: currencies, + handler: .prices + ) + guard !didUpdateProvider(for: currencies) else { + return provider + } + refreshProviderIfPossible() + return provider + } - self?.listeners.forEach { wrapper in - guard - let listener = wrapper.listener.target as? PriceLocalSubscriptionHandler, - let finalValue = changes.reduceToLastChange()? - .first(where: { price in - wrapper.chainAssets.contains(where: { $0.asset.priceId == price.priceId }) == true - && wrapper.currencies.contains(where: { $0.id == price.currencyId }) == true - }) - else { - return + // MARK: - Private methods + + private func refreshProviderIfPossible() { + if remoteFetchTimer == nil { + DispatchQueue.main.async { + self.remoteFetchTimer = Timer.scheduledTimer(withTimeInterval: 30, repeats: false, block: { [weak self] timer in + timer.invalidate() + self?.remoteFetchTimer = nil + }) + } + isAlreadyRefrishing = true + provider.refresh() + } else if fetchOperation == nil, !isAlreadyRefrishing { + fetchOperation = provider.fetch { [weak self] result in + guard let result else { return } + DispatchQueue.main.async { + self?.handleResult(for: result) } + self?.fetchOperation = nil + } + } + } + + private func setupProvider() -> AnySingleValueProvider<[PriceData]> { + let providerCurrencies = listeners.map { $0.currencies }.compactMap { $0 }.reduce([], +).uniq(predicate: { $0.id }) + let priceProvider = priceLocalSubscriber.getPricesProvider(currencies: providerCurrencies, chainAssets: chainAssets) - listener.handlePrice(result: .success(finalValue), chainAsset: chainAsset) + let updateClosure = { [weak self] (changes: [DataProviderChange<[PriceData]>]) in + guard let prices: [PriceData] = changes.reduceToLastChange() else { + return } + self?.handleResult(for: .success(prices)) self?.clearListenersIfNeeded() } let failureClosure = { [weak self] (error: Error) in - self?.listeners.forEach { wrapper in - guard - let listener = wrapper.listener.target as? PriceLocalSubscriptionHandler, - let chainAsset = wrapper.chainAssets.first - else { - return - } - listener.handlePrice(result: .failure(error), chainAsset: chainAsset) - } + self?.handleResult(for: .failure(error)) self?.clearListenersIfNeeded() - return } let options = DataProviderObserverOptions( - alwaysNotifyOnRefresh: true, - waitsInProgressSyncOnAdd: false + notifyIfNoDiff: true ) - priceProvider.removeObserver(self) priceProvider.addObserver( self, deliverOn: .main, @@ -101,62 +159,65 @@ final class PriceLocalStorageSubscriberImpl: PriceLocalStorageSubscriber { return priceProvider } - func subscribeToPrices( - for chainAssets: [ChainAsset], - currencies: [Currency]?, - listener: PriceLocalSubscriptionHandler - ) -> AnySingleValueProvider<[PriceData]> { - appendLisnenerIfNeeded(listener, chainAssets: chainAssets, currencies: currencies) - let providerCurrencies = listeners.map { $0.currencies }.compactMap { $0 }.reduce([], +).uniq(predicate: { $0.id }) - let priceProvider = priceLocalSubscriber.getPricesProvider(currencies: providerCurrencies) + private func didUpdateProvider(for currencies: [Currency]?) -> Bool { + let set = Set(currencies ?? []) + let symmetricDifference = sourcedCurrencies.symmetricDifference(set) + if symmetricDifference.isNotEmpty { + remoteFetchTimer?.invalidate() + remoteFetchTimer = nil + provider = setupProvider() + } + return symmetricDifference.isNotEmpty + } - let updateClosure = { [weak self] (changes: [DataProviderChange<[PriceData]>]) in - self?.listeners.forEach { wrapper in - guard - let listener = wrapper.listener.target as? PriceLocalSubscriptionHandler, - let finalValue = changes.reduceToLastChange()? - .filter({ price in - wrapper.chainAssets.contains(where: { $0.asset.priceId == price.priceId }) == true - && wrapper.currencies.contains(where: { $0.id == price.currencyId }) == true - }) - else { + private func handleResult(for pricesResult: Result<[PriceData]?, Error>) { + switch pricesResult { + case let .success(prices): + handleSuccess(prices: prices) + case let .failure(error): + handleFailure(error: error) + } + isAlreadyRefrishing = false + } + + private func handleSuccess(prices: [PriceData]?) { + listeners.forEach { wrapper in + guard + let listener = wrapper.listener.target as? PriceLocalSubscriptionHandler, + let prices + else { + return + } + let finalValue = prices.filter { price in + wrapper.chainAssets.contains(where: { $0.asset.priceId == price.priceId }) == true + && wrapper.currencies.contains(where: { $0.id == price.currencyId }) == true + } + + switch wrapper.handler { + case .price: + guard let chainAsset = wrapper.chainAssets.first, let priceData = finalValue.first else { return } + listener.handlePrice(result: .success(priceData), chainAsset: chainAsset) + case .prices: listener.handlePrices(result: .success(finalValue)) } - self?.clearListenersIfNeeded() } + } - let failureClosure = { [weak self] (error: Error) in - self?.listeners.forEach { wrapper in - guard let listener = wrapper.listener.target as? PriceLocalSubscriptionHandler else { - return - } + private func handleFailure(error: Error) { + listeners.forEach { wrapper in + guard let listener = wrapper.listener.target as? PriceLocalSubscriptionHandler else { + return + } + if wrapper.chainAssets.count == 1, let chainAsset = wrapper.chainAssets.first { + listener.handlePrice(result: .failure(error), chainAsset: chainAsset) + } else { listener.handlePrices(result: .failure(error)) } - self?.clearListenersIfNeeded() - return } - - let options = DataProviderObserverOptions( - alwaysNotifyOnRefresh: true, - waitsInProgressSyncOnAdd: false - ) - - priceProvider.removeObserver(self) - priceProvider.addObserver( - self, - deliverOn: .main, - executing: updateClosure, - failing: failureClosure, - options: options - ) - - return priceProvider } - // MARK: - Private methods - private func clearListenersIfNeeded() { listeners = listeners.filter { $0.listener.target != nil } } @@ -164,7 +225,8 @@ final class PriceLocalStorageSubscriberImpl: PriceLocalStorageSubscriber { private func appendLisnenerIfNeeded( _ listener: PriceLocalSubscriptionHandler, chainAssets: [ChainAsset], - currencies: [Currency]? + currencies: [Currency]?, + handler: PriceLocalStorageSubscriberListener.Handler ) { let existListener = listeners.first { wrapper in wrapper.listener.target === listener @@ -176,8 +238,31 @@ final class PriceLocalStorageSubscriberImpl: PriceLocalStorageSubscriber { let listener = PriceLocalStorageSubscriberListener( listener: WeakWrapper(target: listener), chainAssets: chainAssets, - currencies: currencies ?? [wallet.selectedCurrency] + currencies: currencies ?? [wallet.selectedCurrency], + handler: handler ) listeners.append(listener) } + + private func refreshChainsAndSubscribe() { + Task { + let chains = try await chainsRepository.fetchAll() + chainAssets = chains.map { $0.chainAssets }.reduce([], +) + + remoteFetchTimer?.invalidate() + remoteFetchTimer = nil + provider = setupProvider() + refreshProviderIfPossible() + } + } +} + +extension PriceLocalStorageSubscriberImpl: EventVisitorProtocol { + func processChainSyncDidComplete(event: ChainSyncDidComplete) { + guard event.newOrUpdatedChains.isNotEmpty else { + return + } + + refreshChainsAndSubscribe() + } } diff --git a/fearless/Common/EventCenter/EventVisitor.swift b/fearless/Common/EventCenter/EventVisitor.swift index 36ac4e0825..51fce74e99 100644 --- a/fearless/Common/EventCenter/EventVisitor.swift +++ b/fearless/Common/EventCenter/EventVisitor.swift @@ -24,7 +24,6 @@ protocol EventVisitorProtocol: AnyObject { func processMetaAccountChanged(event: MetaAccountModelChangedEvent) func processStakingUpdatedEvent() - func processZeroBalancesSettingChanged() func processRemoteSubscriptionWasUpdated(event: WalletRemoteSubscriptionWasUpdatedEvent) func processChainsSetupCompleted() func processLogout() @@ -54,7 +53,6 @@ extension EventVisitorProtocol { func processMetaAccountChanged(event _: MetaAccountModelChangedEvent) {} func processStakingUpdatedEvent() {} - func processZeroBalancesSettingChanged() {} func processRemoteSubscriptionWasUpdated(event _: WalletRemoteSubscriptionWasUpdatedEvent) {} func processChainsSetupCompleted() {} func processLogout() {} diff --git a/fearless/Common/EventCenter/Events/ZeroBalancesSettingChanged.swift b/fearless/Common/EventCenter/Events/ZeroBalancesSettingChanged.swift deleted file mode 100644 index dd24faf7c1..0000000000 --- a/fearless/Common/EventCenter/Events/ZeroBalancesSettingChanged.swift +++ /dev/null @@ -1,7 +0,0 @@ -import Foundation - -struct ZeroBalancesSettingChanged: EventProtocol { - func accept(visitor: EventVisitorProtocol) { - visitor.processZeroBalancesSettingChanged() - } -} diff --git a/fearless/Common/Extension/JSONRPCOperation+Result.swift b/fearless/Common/Extension/JSONRPCOperation+Result.swift index 1d77890e46..6f8c25afee 100644 --- a/fearless/Common/Extension/JSONRPCOperation+Result.swift +++ b/fearless/Common/Extension/JSONRPCOperation+Result.swift @@ -3,8 +3,7 @@ import SSFUtils extension JSONRPCOperation { static func failureOperation(_ error: Error) -> JSONRPCOperation { - let mockEngine = WebSocketEngine(connectionName: nil, url: ApplicationConfig.shared.wiki, autoconnect: false) - let operation = JSONRPCOperation(engine: mockEngine, method: "") + let operation = JSONRPCOperation(engine: nil, method: "") operation.result = .failure(error) return operation } diff --git a/fearless/Common/Extension/Model/CryptoType+Extrinsic.swift b/fearless/Common/Extension/Model/CryptoType+Extrinsic.swift new file mode 100644 index 0000000000..a838720594 --- /dev/null +++ b/fearless/Common/Extension/Model/CryptoType+Extrinsic.swift @@ -0,0 +1,39 @@ +import Foundation +import SSFModels + +extension CryptoType { + init?(version: UInt8) { + switch version { + case 0: + self = .ed25519 + case 1: + self = .sr25519 + case 2: + self = .ecdsa + default: + return nil + } + } + + var version: UInt8 { + switch self { + case .ed25519: + return 0 + case .sr25519: + return 1 + case .ecdsa: + return 2 + } + } + + var signatureLength: Int { + switch self { + case .sr25519: + return 64 + case .ed25519: + return 64 + case .ecdsa: + return 65 + } + } +} diff --git a/fearless/Common/Extension/Model/WalletAssetId+Display.swift b/fearless/Common/Extension/Model/WalletAssetId+Display.swift index fa03486dcc..ea193e6d99 100644 --- a/fearless/Common/Extension/Model/WalletAssetId+Display.swift +++ b/fearless/Common/Extension/Model/WalletAssetId+Display.swift @@ -7,7 +7,7 @@ extension WalletAssetId { case .kusama: return R.image.iconKsmSmallBg() case .westend: return R.image.iconWestendSmallBg() case .roc: return R.image.iconKsmSmallBg() - case .usd: return nil + case .usd, .pswap: return nil } } @@ -17,7 +17,7 @@ extension WalletAssetId { case .kusama: return R.image.iconKsmAsset() case .westend: return R.image.iconWestendAsset() case .roc: return R.image.iconKsmAsset() - case .usd: return nil + case .usd, .pswap: return nil } } @@ -28,6 +28,7 @@ extension WalletAssetId { case .westend: return "Westend" case .roc: return "Rococo" case .usd: return "Usd" + case .pswap: return "Pswap" } } } diff --git a/fearless/Common/Extension/SafeArray.swift b/fearless/Common/Extension/SafeArray.swift new file mode 100644 index 0000000000..5da1b14b8a --- /dev/null +++ b/fearless/Common/Extension/SafeArray.swift @@ -0,0 +1,57 @@ +import Foundation + +final class SafeArray: Collection { + private var array: [T] + private let concurrentQueue = DispatchQueue( + label: "jp.co.soramitsu.fearless.safe.array.queue.\(UUID().uuidString)", + attributes: .concurrent + ) + + var startIndex: Array.Index { + concurrentQueue.sync { + self.array.startIndex + } + } + + var endIndex: Array.Index { + concurrentQueue.sync { + self.array.endIndex + } + } + + init(array: [T] = [T]()) { + self.array = array + } + + func replace(array: [T]) { + concurrentQueue.async(flags: .barrier) { + self.array = array + } + } + + func append(_ newElement: T) { + concurrentQueue.async(flags: .barrier) { + self.array.append(newElement) + } + } + + func index(after i: Int) -> Int { + concurrentQueue.sync { + self.array.index(after: i) + } + } + + func remove(where predicate: @escaping (Element) -> Bool) { + concurrentQueue.async(flags: .barrier) { + while let index = self.array.firstIndex(where: predicate) { + self.array.remove(at: index) + } + } + } + + subscript(position: Int) -> T { + concurrentQueue.sync { + self.array[position] + } + } +} diff --git a/fearless/Common/Extension/SafeDictionary.swift b/fearless/Common/Extension/SafeDictionary.swift new file mode 100644 index 0000000000..95c5103c08 --- /dev/null +++ b/fearless/Common/Extension/SafeDictionary.swift @@ -0,0 +1,80 @@ +import Foundation + +final class SafeDictionary: Collection { + private(set) var dictionary: [V: T] + private let concurrentQueue = DispatchQueue( + label: "jp.co.soramitsu.fearless.safe.dict.queue.\(UUID().uuidString)", + attributes: .concurrent + ) + + var keys: Dictionary.Keys { + concurrentQueue.sync { + self.dictionary.keys + } + } + + var values: Dictionary.Values { + concurrentQueue.sync { + self.dictionary.values + } + } + + var startIndex: Dictionary.Index { + concurrentQueue.sync { + self.dictionary.startIndex + } + } + + var endIndex: Dictionary.Index { + concurrentQueue.sync { + self.dictionary.endIndex + } + } + + init(dict: [V: T] = [V: T]()) { + dictionary = dict + } + + func replace(dict: [V: T]) { + concurrentQueue.async(flags: .barrier) { [weak self] in + self?.dictionary = dict + } + } + + func index(after i: Dictionary.Index) -> Dictionary.Index { + concurrentQueue.sync { + self.dictionary.index(after: i) + } + } + + func removeValue(forKey key: V) { + concurrentQueue.async(flags: .barrier) { [weak self] in + self?.dictionary.removeValue(forKey: key) + } + } + + func removeAll() { + concurrentQueue.async(flags: .barrier) { [weak self] in + self?.dictionary.removeAll() + } + } + + subscript(key: V) -> T? { + set(newValue) { + concurrentQueue.async(flags: .barrier) { [weak self] in + self?.dictionary[key] = newValue + } + } + get { + concurrentQueue.sync { + self.dictionary[key] + } + } + } + + subscript(index: Dictionary.Index) -> Dictionary.Element { + concurrentQueue.sync { + self.dictionary[index] + } + } +} diff --git a/fearless/Common/Extension/UIKit/SkeletonRow+View.swift b/fearless/Common/Extension/UIKit/SkeletonRow+View.swift index 52a2603068..e906b4caf5 100644 --- a/fearless/Common/Extension/UIKit/SkeletonRow+View.swift +++ b/fearless/Common/Extension/UIKit/SkeletonRow+View.swift @@ -62,4 +62,11 @@ extension SingleSkeleton { return SingleSkeleton(position: spaceSize.skrullMap(point: position), size: mappedSize).round() } + + static func createRow( + position: CGPoint, + size _: CGSize + ) -> SingleSkeleton { + SingleSkeleton(position: position, size: CGSize(width: 1, height: 1)).round() + } } diff --git a/fearless/Common/Extension/Wallet/AssetTransactionData+ArrowsquidHistory.swift b/fearless/Common/Extension/Wallet/AssetTransactionData+ArrowsquidHistory.swift index 375fabda6c..33e01b3a7a 100644 --- a/fearless/Common/Extension/Wallet/AssetTransactionData+ArrowsquidHistory.swift +++ b/fearless/Common/Extension/Wallet/AssetTransactionData+ArrowsquidHistory.swift @@ -37,7 +37,7 @@ extension AssetTransactionData { return AssetTransactionData( transactionId: item.identifier, status: .pending, - assetId: asset.identifier, + assetId: asset.id, peerId: "", peerFirstName: nil, peerLastName: nil, @@ -79,8 +79,8 @@ extension AssetTransactionData { let feeDecimal = Decimal.fromSubstrateAmount(feeValue, precision: Int16(utilityAsset.precision)) ?? .zero let fee = AssetTransactionFee( - identifier: asset.identifier, - assetId: asset.identifier, + identifier: asset.id, + assetId: asset.id, amount: AmountDecimal(value: feeDecimal), context: nil ) @@ -91,7 +91,7 @@ extension AssetTransactionData { return AssetTransactionData( transactionId: item.extrinsicHash ?? item.identifier, status: status, - assetId: asset.identifier, + assetId: asset.id, peerId: peerId, peerFirstName: nil, peerLastName: nil, @@ -131,7 +131,7 @@ extension AssetTransactionData { return AssetTransactionData( transactionId: item.identifier, status: status, - assetId: asset.identifier, + assetId: asset.id, peerId: peerId, peerFirstName: reward.validator, peerLastName: nil, diff --git a/fearless/Common/Extension/Wallet/AssetTransactionData+EtherscanHistory.swift b/fearless/Common/Extension/Wallet/AssetTransactionData+EtherscanHistory.swift index 3bf6ffdb2e..c6ca132004 100644 --- a/fearless/Common/Extension/Wallet/AssetTransactionData+EtherscanHistory.swift +++ b/fearless/Common/Extension/Wallet/AssetTransactionData+EtherscanHistory.swift @@ -29,8 +29,8 @@ extension AssetTransactionData { let feeDecimal = Decimal.fromSubstrateAmount(feeValue, precision: Int16(utilityAsset.precision)) ?? .zero let fee = AssetTransactionFee( - identifier: asset.identifier, - assetId: asset.identifier, + identifier: asset.id, + assetId: asset.id, amount: AmountDecimal(value: feeDecimal), context: nil ) diff --git a/fearless/Common/Extension/Wallet/AssetTransactionData+GiantsquidHistory.swift b/fearless/Common/Extension/Wallet/AssetTransactionData+GiantsquidHistory.swift index 8146555f3f..dfeb95380f 100644 --- a/fearless/Common/Extension/Wallet/AssetTransactionData+GiantsquidHistory.swift +++ b/fearless/Common/Extension/Wallet/AssetTransactionData+GiantsquidHistory.swift @@ -31,8 +31,8 @@ extension AssetTransactionData { if let feeAmountString = transfer.feeAmount, let feeSubstrateAmount = BigUInt(string: feeAmountString), let feeDecimalAmount = Decimal.fromSubstrateAmount(feeSubstrateAmount, precision: Int16(asset.precision)) { let fee = AssetTransactionFee( - identifier: asset.identifier, - assetId: asset.identifier, + identifier: asset.id, + assetId: asset.id, amount: AmountDecimal(value: feeDecimalAmount), context: nil ) @@ -42,14 +42,18 @@ extension AssetTransactionData { if let signedData = transfer.signedData, let fee = signedData.fee, let partialFee = fee.partialFee, let partialFeeDecimal = Decimal.fromSubstrateAmount(partialFee, precision: Int16(asset.precision)) { let fee = AssetTransactionFee( - identifier: asset.identifier, - assetId: asset.identifier, + identifier: asset.id, + assetId: asset.id, amount: AmountDecimal(value: partialFeeDecimal), context: nil ) fees.append(fee) } + var context: [String: String] = [:] + if let blockHash = transfer.blockHash { + context["reefBlockHash"] = blockHash + } return AssetTransactionData( transactionId: transfer.identifier, @@ -65,7 +69,7 @@ extension AssetTransactionData { timestamp: timestamp, type: type.rawValue, reason: nil, - context: nil + context: context ) } @@ -207,8 +211,8 @@ extension AssetTransactionData { let partialFeeDecimal = Decimal.fromSubstrateAmount(partialFee, precision: Int16(asset.precision)) { let fee = AssetTransactionFee( - identifier: asset.identifier, - assetId: asset.identifier, + identifier: asset.id, + assetId: asset.id, amount: AmountDecimal(value: partialFeeDecimal), context: nil ) @@ -219,7 +223,7 @@ extension AssetTransactionData { return AssetTransactionData( transactionId: extrinsic.hash ?? extrinsic.id, status: status, - assetId: asset.identifier, + assetId: asset.id, peerId: address, peerFirstName: extrinsic.section, peerLastName: extrinsic.method, diff --git a/fearless/Common/Extension/Wallet/AssetTransactionData+OklinkHistory.swift b/fearless/Common/Extension/Wallet/AssetTransactionData+OklinkHistory.swift index c4252e2beb..713f1e5a4a 100644 --- a/fearless/Common/Extension/Wallet/AssetTransactionData+OklinkHistory.swift +++ b/fearless/Common/Extension/Wallet/AssetTransactionData+OklinkHistory.swift @@ -22,8 +22,8 @@ extension AssetTransactionData { let feeDecimal = Decimal(string: item.txFee, locale: Locale(identifier: "en_EN")) ?? .zero let fee = AssetTransactionFee( - identifier: asset.identifier, - assetId: asset.identifier, + identifier: asset.id, + assetId: asset.id, amount: AmountDecimal(value: feeDecimal), context: nil ) diff --git a/fearless/Common/Extension/Wallet/AssetTransactionData+SubqueryHistory.swift b/fearless/Common/Extension/Wallet/AssetTransactionData+SubqueryHistory.swift index e71d96447d..08572fd278 100644 --- a/fearless/Common/Extension/Wallet/AssetTransactionData+SubqueryHistory.swift +++ b/fearless/Common/Extension/Wallet/AssetTransactionData+SubqueryHistory.swift @@ -45,7 +45,7 @@ extension AssetTransactionData { return AssetTransactionData( transactionId: item.identifier, status: .pending, - assetId: asset.identifier, + assetId: asset.id, peerId: "", peerFirstName: nil, peerLastName: nil, @@ -82,15 +82,21 @@ extension AssetTransactionData { BigUInt(string: transfer.amount) ?? 0, precision: Int16(asset.precision) ) ?? .zero - let feeValue = BigUInt(string: transfer.fee) ?? BigUInt(0) - let feeDecimal = Decimal.fromSubstrateAmount(feeValue, precision: Int16(asset.precision)) ?? .zero - let fee = AssetTransactionFee( - identifier: asset.identifier, - assetId: asset.identifier, - amount: AmountDecimal(value: feeDecimal), - context: nil - ) + var fees: [AssetTransactionFee] = [] + + if let fee = transfer.fee { + let feeValue = BigUInt(string: fee) ?? BigUInt(0) + let feeDecimal = Decimal.fromSubstrateAmount(feeValue, precision: Int16(asset.precision)) ?? .zero + + let fee = AssetTransactionFee( + identifier: asset.id, + assetId: asset.id, + amount: AmountDecimal(value: feeDecimal), + context: nil + ) + fees.append(fee) + } let type = transfer.sender == address ? TransactionType.outgoing : TransactionType.incoming @@ -100,14 +106,14 @@ extension AssetTransactionData { return AssetTransactionData( transactionId: item.identifier, status: status, - assetId: asset.identifier, + assetId: asset.id, peerId: peerId, peerFirstName: nil, peerLastName: nil, peerName: peerAddress, details: "", amount: AmountDecimal(value: amount), - fees: [fee], + fees: fees, timestamp: timestamp, type: type.rawValue, reason: "", @@ -145,8 +151,8 @@ extension AssetTransactionData { let feeDecimal = Decimal.fromSubstrateAmount(feeValue, precision: Int16(asset.precision)) ?? .zero let fee = AssetTransactionFee( - identifier: asset.identifier, - assetId: asset.identifier, + identifier: asset.id, + assetId: asset.id, amount: AmountDecimal(value: feeDecimal), context: nil ) @@ -157,7 +163,7 @@ extension AssetTransactionData { return AssetTransactionData( transactionId: item.hash, status: status, - assetId: asset.identifier, + assetId: asset.id, peerId: peerId, peerFirstName: nil, peerLastName: nil, @@ -199,7 +205,7 @@ extension AssetTransactionData { return AssetTransactionData( transactionId: item.identifier, status: status, - assetId: asset.identifier, + assetId: asset.id, peerId: peerId, peerFirstName: reward.validator, peerLastName: nil, @@ -233,7 +239,7 @@ extension AssetTransactionData { return AssetTransactionData( transactionId: item.identifier, status: status, - assetId: asset.identifier, + assetId: asset.id, peerId: item.extrinsicHash, peerFirstName: nil, peerLastName: nil, @@ -267,7 +273,7 @@ extension AssetTransactionData { return AssetTransactionData( transactionId: item.identifier, status: status, - assetId: asset.identifier, + assetId: asset.id, peerId: peerId, peerFirstName: extrinsic.module, peerLastName: extrinsic.call, @@ -310,7 +316,7 @@ extension AssetTransactionData { return AssetTransactionData( transactionId: item.identifier, status: status, - assetId: asset.identifier, + assetId: asset.id, peerId: peerId, peerFirstName: item.callModule, peerLastName: item.callFunction, @@ -369,8 +375,8 @@ extension AssetTransactionData { ) ?? .zero let fee = AssetTransactionFee( - identifier: asset.identifier, - assetId: asset.identifier, + identifier: asset.id, + assetId: asset.id, amount: AmountDecimal(value: feeDecimal), context: nil ) @@ -391,7 +397,7 @@ extension AssetTransactionData { return AssetTransactionData( transactionId: item.txHash, status: item.status.walletValue, - assetId: asset.identifier, + assetId: asset.id, peerId: peerId, peerFirstName: nil, peerLastName: nil, @@ -427,7 +433,7 @@ extension AssetTransactionData { return AssetTransactionData( transactionId: item.identifier, status: item.status.walletValue, - assetId: asset.identifier, + assetId: asset.id, peerId: peerId, peerFirstName: item.callPath.moduleName, peerLastName: item.callPath.callName, diff --git a/fearless/Common/Extension/Wallet/AssetTransactionData+SubsquidHistory.swift b/fearless/Common/Extension/Wallet/AssetTransactionData+SubsquidHistory.swift index a3c9b03db5..457c09f3c8 100644 --- a/fearless/Common/Extension/Wallet/AssetTransactionData+SubsquidHistory.swift +++ b/fearless/Common/Extension/Wallet/AssetTransactionData+SubsquidHistory.swift @@ -45,7 +45,7 @@ extension AssetTransactionData { return AssetTransactionData( transactionId: item.identifier, status: .pending, - assetId: asset.identifier, + assetId: asset.id, peerId: "", peerFirstName: nil, peerLastName: nil, @@ -87,8 +87,8 @@ extension AssetTransactionData { let feeDecimal = Decimal.fromSubstrateAmount(feeValue, precision: Int16(utilityAsset.precision)) ?? .zero let fee = AssetTransactionFee( - identifier: asset.identifier, - assetId: asset.identifier, + identifier: asset.id, + assetId: asset.id, amount: AmountDecimal(value: feeDecimal), context: nil ) @@ -99,7 +99,7 @@ extension AssetTransactionData { return AssetTransactionData( transactionId: item.extrinsicHash ?? item.identifier, status: status, - assetId: asset.identifier, + assetId: asset.id, peerId: peerId, peerFirstName: nil, peerLastName: nil, @@ -139,7 +139,7 @@ extension AssetTransactionData { return AssetTransactionData( transactionId: item.identifier, status: status, - assetId: asset.identifier, + assetId: asset.id, peerId: peerId, peerFirstName: reward.validator, peerLastName: nil, @@ -171,7 +171,7 @@ extension AssetTransactionData { return AssetTransactionData( transactionId: item.identifier, status: status, - assetId: asset.identifier, + assetId: asset.id, peerId: peerId, peerFirstName: extrinsic.module, peerLastName: extrinsic.call, diff --git a/fearless/Common/Extension/Wallet/AssetTransactionData+Zeta.swift b/fearless/Common/Extension/Wallet/AssetTransactionData+Zeta.swift index 5b36362b58..6c9e938b52 100644 --- a/fearless/Common/Extension/Wallet/AssetTransactionData+Zeta.swift +++ b/fearless/Common/Extension/Wallet/AssetTransactionData+Zeta.swift @@ -27,8 +27,8 @@ extension AssetTransactionData { let feeDecimal = Decimal.fromSubstrateAmount(feeValue, precision: Int16(utilityAsset.precision)) ?? .zero let fee = AssetTransactionFee( - identifier: asset.identifier, - assetId: asset.identifier, + identifier: asset.id, + assetId: asset.id, amount: AmountDecimal(value: feeDecimal), context: nil ) diff --git a/fearless/Common/Helpers/ChainAssetsFetching.swift b/fearless/Common/Helpers/ChainAssetsFetching.swift index 9e5c36cdef..dec5afd601 100644 --- a/fearless/Common/Helpers/ChainAssetsFetching.swift +++ b/fearless/Common/Helpers/ChainAssetsFetching.swift @@ -35,6 +35,7 @@ final class ChainAssetsFetching: ChainAssetFetchingProtocol { case chainIds([ChainModel.Id]) case supportNfts case enabled(wallet: MetaAccountModel) + case enabledChains var searchText: String? { switch self { @@ -243,6 +244,8 @@ private extension ChainAssetsFetching { .filter { !$0.hidden } .map { $0.assetId } return chainAssets.filter { enabled.contains($0.identifier) } + case .enabledChains: + return chainAssets.filter { !$0.chain.disabled } } } diff --git a/fearless/Common/Helpers/ChainRepositoryFactory.swift b/fearless/Common/Helpers/ChainRepositoryFactory.swift index abc1c5040f..eae337fa47 100644 --- a/fearless/Common/Helpers/ChainRepositoryFactory.swift +++ b/fearless/Common/Helpers/ChainRepositoryFactory.swift @@ -20,4 +20,16 @@ final class ChainRepositoryFactory { mapper: AnyCoreDataMapper(mapper) ) } + + func createAsyncRepository( + for filter: NSPredicate? = nil, + sortDescriptors: [NSSortDescriptor] = [] + ) -> AsyncCoreDataRepositoryDefault { + let mapper = ChainModelMapper() + return storageFacade.createAsyncRepository( + filter: filter, + sortDescriptors: sortDescriptors, + mapper: AnyCoreDataMapper(mapper) + ) + } } diff --git a/fearless/Common/Helpers/EthereumNodeFetching.swift b/fearless/Common/Helpers/EthereumNodeFetching.swift index ca890796cd..c6c6499cc7 100644 --- a/fearless/Common/Helpers/EthereumNodeFetching.swift +++ b/fearless/Common/Helpers/EthereumNodeFetching.swift @@ -99,21 +99,19 @@ enum EthereumChain: String { final class EthereumNodeFetching { func getNode(for chain: ChainModel) throws -> Web3.Eth { - guard let ethereumChain = EthereumChain(rawValue: chain.chainId) else { - return try getHttps(for: chain) - } - let randomWssNode = chain.nodes.filter { $0.url.absoluteString.contains("wss") }.randomElement() let hasSelectedWssNode = chain.selectedNode?.url.absoluteString.contains("wss") == true let node = hasSelectedWssNode ? chain.selectedNode : randomWssNode - guard let wssURL = node?.url else { + guard var wssURL = node?.url else { return try getHttps(for: chain) } - let finalURL = ethereumChain.apiKeyInjectedURL(baseURL: wssURL) + if let ethereumChain = EthereumChain(rawValue: chain.chainId) { + wssURL = ethereumChain.apiKeyInjectedURL(baseURL: wssURL) + } - let provider = try Web3WebSocketProvider(wsUrl: finalURL.absoluteString, timeout: .seconds(10)) + let provider = try Web3WebSocketProvider(wsUrl: wssURL.absoluteString, timeout: .seconds(10)) let web3 = Web3(provider: provider, rpcId: Int(chain.chainId) ?? 1) return web3.eth } diff --git a/fearless/Common/Helpers/WalletAssetsObserver.swift b/fearless/Common/Helpers/WalletAssetsObserver.swift index 5473241fba..f1fbfa2a48 100644 --- a/fearless/Common/Helpers/WalletAssetsObserver.swift +++ b/fearless/Common/Helpers/WalletAssetsObserver.swift @@ -5,6 +5,10 @@ import SoraKeystore protocol WalletAssetsObserver: ApplicationServiceProtocol { func update(wallet: MetaAccountModel) + func updateVisibility( + wallet: MetaAccountModel?, + chainAssets: [ChainAsset] + ) async -> MetaAccountModel } final class WalletAssetsObserverImpl: WalletAssetsObserver { @@ -19,8 +23,6 @@ final class WalletAssetsObserverImpl: WalletAssetsObserver { DispatchQueue(label: "co.jp.soramitsu.asset.observer.deliveryQueue") }() - private var currentTask: Task? - init( wallet: MetaAccountModel, chainRegistry: ChainRegistryProtocol, @@ -46,12 +48,23 @@ final class WalletAssetsObserverImpl: WalletAssetsObserver { setup() } + func updateVisibility( + wallet: MetaAccountModel?, + chainAssets: [ChainAsset] + ) async -> MetaAccountModel { + if let wallet { + self.wallet = wallet + } + let chains = chainAssets + .map { $0.chain } + .uniq(predicate: { $0.chainId }) + let updatedWallet = await updateVisibility(for: chains) + return updatedWallet + } + // MARK: - ApplicationServiceProtocol func setup() { - guard wallet.assetsVisibility.isEmpty else { - return - } chainRegistry.chainsSubscribe( self, runningInQueue: walletAssetsObserverQueue @@ -61,35 +74,24 @@ final class WalletAssetsObserverImpl: WalletAssetsObserver { } func throttle() { - currentTask?.cancel() chainRegistry.chainsUnsubscribe(self) } // MARK: - Private methods private func handleChains(changes: [DataProviderChange], accounts: [ChainAccountModel]?) { - currentTask = Task { + Task { let result = await withTaskGroup( of: (ChainModel, [ChainAssetId: AccountInfo?]).self, returning: [ChainModel: [ChainAssetId: AccountInfo?]].self, - body: { [wallet] group in + body: { group in changes.forEach { change in switch change { case let .insert(chain): - if let accounts { - if accounts.contains(where: { $0.chainId == chain.chainId }) { - group.addTask { - await self.fetchAccountInfos(chain: chain, wallet: wallet) - } - } else { - return - } - } else { - group.addTask { - await self.fetchAccountInfos(chain: chain, wallet: wallet) - } - } - case .update, .delete: + self.handleChange(for: chain, accounts: accounts, group: &group) + case let .update(chain): + self.handleChange(for: chain, accounts: accounts, group: &group) + case .delete: break } } @@ -109,6 +111,62 @@ final class WalletAssetsObserverImpl: WalletAssetsObserver { } } + private func handleChange( + for chain: ChainModel, + accounts: [ChainAccountModel]?, + group: inout TaskGroup<(ChainModel, [ChainAssetId: AccountInfo?])> + ) { + let chainAssetsIds = chain.chainAssets.map { $0.identifier } + let existVisibility = wallet.assetsVisibility.map { $0.assetId } + let perhapsExistVisibility = existVisibility.filter { chainAssetsIds.contains($0) } + + guard !chain.disabled, chainAssetsIds.count > perhapsExistVisibility.count else { + return + } + if let accounts { + if accounts.contains(where: { $0.chainId == chain.chainId }) { + group.addTask { [wallet] in + await self.fetchAccountInfos(chain: chain, wallet: wallet) + } + } else { + return + } + } else { + group.addTask { [wallet] in + await self.fetchAccountInfos(chain: chain, wallet: wallet) + } + } + } + + private func updateVisibility(for chains: [ChainModel]) async -> MetaAccountModel { + let result = await withTaskGroup( + of: (ChainModel, [ChainAssetId: AccountInfo?])?.self, + returning: [ChainModel: [ChainAssetId: AccountInfo?]].self + ) { group in + chains.forEach { chain in + group.addTask { + do { + let accountInfos = try await self.accountInfoRemote.fetchAccountInfos(for: chain, wallet: self.wallet) + return (chain, accountInfos) + } catch { + return nil + } + } + } + + var taskResults = [ChainModel: [ChainAssetId: AccountInfo?]]() + for await result in group { + guard let result else { + continue + } + taskResults[result.0] = result.1 + } + return taskResults + } + updateCurrentWallet(with: result) + return wallet + } + private func fetchAccountInfos(chain: ChainModel, wallet: MetaAccountModel) async -> (ChainModel, [ChainAssetId: AccountInfo?]) { do { let accountInfos = try await accountInfoRemote.fetchAccountInfos(for: chain, wallet: wallet) diff --git a/fearless/Common/Model/AssetVisibility.swift b/fearless/Common/Model/AssetVisibility.swift index 543917411f..28a15710b6 100644 --- a/fearless/Common/Model/AssetVisibility.swift +++ b/fearless/Common/Model/AssetVisibility.swift @@ -1,11 +1,11 @@ import Foundation import RobinHood -struct AssetVisibility: Codable, Equatable, Hashable, Identifiable { - var identifier: String { - assetId - } - - let assetId: String - var hidden: Bool -} +// struct AssetVisibility: Codable, Equatable, Hashable, Identifiable { +// var identifier: String { +// assetId +// } +// +// let assetId: String +// var hidden: Bool +// } diff --git a/fearless/Common/Model/Chain.swift b/fearless/Common/Model/Chain.swift deleted file mode 100644 index d97d5c7f37..0000000000 --- a/fearless/Common/Model/Chain.swift +++ /dev/null @@ -1,85 +0,0 @@ -import Foundation -import IrohaCrypto - -enum Chain: String, Codable, CaseIterable { - case kusama = "Kusama" - case polkadot = "Polkadot" - case westend = "Westend" - case rococo = "Rococo" - case moonbeam = "Moonbeam" - case moonriver = "Moonriver" - case moonbaseAlpha = "Moonbase Alpha" - case soraMain = "SORA Mainnet" - case soraTest = "SORA Test" - case ternoa = "Ternoa Mainnet" - case equilibrium = "Equilibrium" - case reef = "Reef Mainnet" - case scuba = "Reef Scuba Testnet" - - init?(rawValue: String) { - switch rawValue { - case Self.kusama.rawValue: self = .kusama - case Self.polkadot.rawValue: self = .polkadot - case Self.westend.rawValue: self = .westend - case Self.rococo.rawValue: self = .rococo - case Self.moonbeam.rawValue: self = .moonbeam - case Self.moonriver.rawValue: self = .moonriver - case Self.moonbaseAlpha.rawValue: self = .moonbaseAlpha - case Self.soraMain.rawValue: self = .soraMain - case Self.ternoa.rawValue: self = .ternoa - case Self.equilibrium.rawValue: self = .equilibrium - case Self.reef.rawValue: self = .reef - case Self.scuba.rawValue: self = .scuba - - #if F_DEV - case "Polkatrain": self = .polkadot - #endif - - default: return nil - } - } - - init?(chainId: String) { - switch chainId { - case Self.kusama.genesisHash: self = .kusama - case Self.polkadot.genesisHash: self = .polkadot - case Self.westend.genesisHash: self = .westend - case Self.rococo.genesisHash: self = .rococo - case Self.moonbeam.genesisHash: self = .moonbeam - case Self.moonriver.genesisHash: self = .moonriver - case Self.moonbaseAlpha.genesisHash: self = .moonbaseAlpha - case Self.soraMain.genesisHash: self = .soraMain - case Self.ternoa.genesisHash: self = .ternoa - case Self.equilibrium.genesisHash: self = .equilibrium - case Self.reef.genesisHash: self = .reef - case Self.scuba.genesisHash: self = .scuba - default: return nil - } - } - - var genesisHash: String { - switch self { - case .polkadot: return "91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3" - case .kusama: return "b0a8d493285c2df73290dfb7e61f870f17b41801197a149ca93654499ea3dafe" - case .westend: return "e143f23803ac50e8f6f8e62695d1ce9e4e1d68aa36c1cd2cfd15340213f3423e" - case .rococo: return "1ab7fbd1d7c3532386268ec23fe4ff69f5bb6b3e3697947df3a2ec2786424de3" - case .moonbeam: return "fe58ea77779b7abda7da4ec526d14db9b1e9cd40a217c34892af80a9b332b76d" - case .moonriver: return "401a1f9dca3da46f5c4091016c8a2f26dcea05865116b286f60f668207d1474b" - case .moonbaseAlpha: return "91bc6e169807aaa54802737e1c504b2577d4fafedd5a02c10293b1cd60e39527" - case .soraMain: return "7e4e32d0feafd4f9c9414b0be86373f9a1efa904809b683453a9af6856d38ad5" - case .soraTest: return "3266816be9fa51b32cfea58d3e33ca77246bc9618595a4300e44c8856a8d8a17" - case .ternoa: return "6859c81ca95ef624c9dfe4dc6e3381c33e5d6509e35e147092bfbc780f777c4e" - case .equilibrium: return "89d3ec46d2fb43ef5a9713833373d5ea666b092fa8fd68fbc34596036571b907" - case .reef: return "7834781d38e4798d548e34ec947d19deea29df148a7bf32484b7b24dacf8d4b7" - case .scuba: return "b414a8602b2251fa538d38a9322391500bd0324bc7ac6048845d57c37dd83fe6" - } - } - - var erasPerDay: Int { - switch self { - case .polkadot, .ternoa, .equilibrium, .reef, .scuba: return 1 - case .kusama, .westend, .rococo, .moonbeam, .soraMain, .soraTest: return 4 - case .moonriver, .moonbaseAlpha: return 12 - } - } -} diff --git a/fearless/Common/Model/ChainAsset.swift b/fearless/Common/Model/ChainAsset.swift index 8fcece8adc..9d3cb44232 100644 --- a/fearless/Common/Model/ChainAsset.swift +++ b/fearless/Common/Model/ChainAsset.swift @@ -6,7 +6,7 @@ extension ChainAsset { var assetDisplayInfo: AssetBalanceDisplayInfo { asset.displayInfo(with: chain.icon) } var identifier: String { - [chain.identifier, asset.identifier].joined(separator: " : ") + [chain.identifier, asset.id].joined(separator: " : ") } var storagePath: StorageCodingPath { diff --git a/fearless/Common/Model/ChainRegistry/AssetModel.swift b/fearless/Common/Model/ChainRegistry/AssetModel.swift index bfa1fa431b..7cdc1874be 100644 --- a/fearless/Common/Model/ChainRegistry/AssetModel.swift +++ b/fearless/Common/Model/ChainRegistry/AssetModel.swift @@ -3,10 +3,8 @@ import RobinHood import SSFModels import SoraFoundation -extension AssetModel: Identifiable { - public var identifier: String { id } - - public var displayInfo: AssetBalanceDisplayInfo { +public extension AssetModel { + var displayInfo: AssetBalanceDisplayInfo { AssetBalanceDisplayInfo( displayPrecision: 5, assetPrecision: Int16(bitPattern: precision), @@ -17,7 +15,7 @@ extension AssetModel: Identifiable { ) } - public func displayInfo(with chainIcon: URL?) -> AssetBalanceDisplayInfo { + func displayInfo(with chainIcon: URL?) -> AssetBalanceDisplayInfo { AssetBalanceDisplayInfo( displayPrecision: 5, assetPrecision: Int16(bitPattern: precision), @@ -28,7 +26,7 @@ extension AssetModel: Identifiable { ) } - public func normalizedSymbol() -> String { + func normalizedSymbol() -> String { guard symbol.hasPrefix("xc") else { return symbol } diff --git a/fearless/Common/Model/ChainRegistry/ChainAccountModel.swift b/fearless/Common/Model/ChainRegistry/ChainAccountModel.swift index 6275784364..d22ce7405a 100644 --- a/fearless/Common/Model/ChainRegistry/ChainAccountModel.swift +++ b/fearless/Common/Model/ChainRegistry/ChainAccountModel.swift @@ -1,12 +1,13 @@ import Foundation +import SSFModels -struct ChainAccountModel: Equatable, Hashable, Codable { - let chainId: String - let accountId: AccountId - let publicKey: Data - let cryptoType: UInt8 - let ethereumBased: Bool -} +// struct ChainAccountModel: Equatable, Hashable, Codable { +// let chainId: String +// let accountId: AccountId +// let publicKey: Data +// let cryptoType: UInt8 +// let ethereumBased: Bool +// } extension ChainAccountModel { func toAddress(addressPrefix: UInt16) -> AccountAddress? { diff --git a/fearless/Common/Model/ChainRegistry/MetaAccountModel.swift b/fearless/Common/Model/ChainRegistry/MetaAccountModel.swift index 2a8ae48abf..c39654f65a 100644 --- a/fearless/Common/Model/ChainRegistry/MetaAccountModel.swift +++ b/fearless/Common/Model/ChainRegistry/MetaAccountModel.swift @@ -21,6 +21,10 @@ struct MetaAccountModel: Equatable, Codable { let assetsVisibility: [AssetVisibility] let hasBackup: Bool let favouriteChainIds: [ChainModel.Id] + + var utilsModel: SSFModels.MetaAccountModel { + SSFModels.MetaAccountModel(metaId: metaId, name: name, substrateAccountId: substrateAccountId, substrateCryptoType: substrateCryptoType, substratePublicKey: substratePublicKey, ethereumAddress: ethereumAddress, ethereumPublicKey: ethereumPublicKey, chainAccounts: chainAccounts, assetKeysOrder: assetKeysOrder, assetFilterOptions: [], canExportEthereumMnemonic: canExportEthereumMnemonic, unusedChainIds: unusedChainIds, selectedCurrency: selectedCurrency, networkManagmentFilter: networkManagmentFilter, assetsVisibility: assetsVisibility, zeroBalanceAssetsHidden: false, hasBackup: hasBackup, favouriteChainIds: favouriteChainIds) + } } extension MetaAccountModel { @@ -34,6 +38,10 @@ extension MetaAccountModel: Identifiable { } extension MetaAccountModel { + func isVisible(chainAsset: ChainAsset) -> Bool { + assetsVisibility.first(where: { $0.assetId == chainAsset.identifier })?.hidden == false + } + func insertingChainAccount(_ newChainAccount: ChainAccountModel) -> MetaAccountModel { var newChainAccounts = chainAccounts.filter { $0.chainId != newChainAccount.chainId diff --git a/fearless/Common/Model/Currency.swift b/fearless/Common/Model/Currency.swift index e0786fb766..82583e939b 100644 --- a/fearless/Common/Model/Currency.swift +++ b/fearless/Common/Model/Currency.swift @@ -1,29 +1,29 @@ import Foundation -struct Currency: Codable, Equatable, Hashable { - let id: String - let symbol: String - let name: String - let icon: String - var isSelected: Bool? - - static func defaultCurrency() -> Currency { - Currency( - id: "usd", - symbol: "$", - name: "US Dollar", - icon: "https://raw.githubusercontent.com/soramitsu/fearless-utils/android/2.0.2/icons/fiat/usd.svg", - isSelected: true - ) - } - - static func euro() -> Currency { - Currency( - id: "eur", - symbol: "€", - name: "Euro", - icon: "https://raw.githubusercontent.com/soramitsu/fearless-utils/android/2.0.2/icons/fiat/eur.svg", - isSelected: false - ) - } -} +// struct Currency: Codable, Equatable, Hashable { +// let id: String +// let symbol: String +// let name: String +// let icon: String +// var isSelected: Bool? +// +// static func defaultCurrency() -> Currency { +// Currency( +// id: "usd", +// symbol: "$", +// name: "US Dollar", +// icon: "https://raw.githubusercontent.com/soramitsu/fearless-utils/android/2.0.2/icons/fiat/usd.svg", +// isSelected: true +// ) +// } +// +// static func euro() -> Currency { +// Currency( +// id: "eur", +// symbol: "€", +// name: "Euro", +// icon: "https://raw.githubusercontent.com/soramitsu/fearless-utils/android/2.0.2/icons/fiat/eur.svg", +// isSelected: false +// ) +// } +// } diff --git a/fearless/Common/Model/WalletAssetId.swift b/fearless/Common/Model/WalletAssetId.swift index 4bbb2b9986..8bb4aa67fc 100644 --- a/fearless/Common/Model/WalletAssetId.swift +++ b/fearless/Common/Model/WalletAssetId.swift @@ -6,4 +6,5 @@ enum WalletAssetId: String { case westend case usd case roc + case pswap = "0x0200050000000000000000000000000000000000000000000000000000000000" } diff --git a/fearless/Common/Network/BlockExplorer/Giantsquid/GiantsquidTransfer.swift b/fearless/Common/Network/BlockExplorer/Giantsquid/GiantsquidTransfer.swift index 3754921b4b..69bf6101d6 100644 --- a/fearless/Common/Network/BlockExplorer/Giantsquid/GiantsquidTransfer.swift +++ b/fearless/Common/Network/BlockExplorer/Giantsquid/GiantsquidTransfer.swift @@ -27,6 +27,7 @@ struct GiantsquidTransfer: Decodable { let type: String? let feeAmount: String? let signedData: GiantsquidSignedData? + let blockHash: String? var timestampInSeconds: Int64 { let locale = LocalizationManager.shared.selectedLocale diff --git a/fearless/Common/Network/BlockExplorer/Subquery/Data/GraphQLResponse.swift b/fearless/Common/Network/BlockExplorer/Subquery/Data/GraphQLResponse.swift deleted file mode 100644 index 1abc64c72d..0000000000 --- a/fearless/Common/Network/BlockExplorer/Subquery/Data/GraphQLResponse.swift +++ /dev/null @@ -1,34 +0,0 @@ -import Foundation -import SSFUtils - -struct SubqueryErrors: Error, Decodable { - struct SubqueryError: Error, Decodable { - let message: String - } - - let errors: [SubqueryError] -} - -enum GraphQLResponse: Decodable { - case data(_ value: D) - case errors(_ value: SubqueryErrors) - - init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - - let json = try container.decode(JSON.self) - - if let data = json.data { - let value = try data.map(to: D.self) - self = .data(value) - } else if let errors = json.errors { - let values = try errors.map(to: [SubqueryErrors.SubqueryError].self) - self = .errors(SubqueryErrors(errors: values)) - } else { - throw DecodingError.dataCorruptedError( - in: container, - debugDescription: "unexpected value" - ) - } - } -} diff --git a/fearless/Common/Network/BlockExplorer/Subquery/Data/SubqueryEraValidatorInfo.swift b/fearless/Common/Network/BlockExplorer/Subquery/Data/SubqueryEraValidatorInfo.swift index f4b3b27b27..a3fea03ee2 100644 --- a/fearless/Common/Network/BlockExplorer/Subquery/Data/SubqueryEraValidatorInfo.swift +++ b/fearless/Common/Network/BlockExplorer/Subquery/Data/SubqueryEraValidatorInfo.swift @@ -1,4 +1,5 @@ import SSFUtils +import SSFModels struct SubqueryEraValidatorInfo { let address: AccountAddress diff --git a/fearless/Common/Network/BlockExplorer/Subquery/Data/SubqueryRewardData.swift b/fearless/Common/Network/BlockExplorer/Subquery/Data/SubqueryRewardData.swift index 769b538409..f3607b7f37 100644 --- a/fearless/Common/Network/BlockExplorer/Subquery/Data/SubqueryRewardData.swift +++ b/fearless/Common/Network/BlockExplorer/Subquery/Data/SubqueryRewardData.swift @@ -1,6 +1,7 @@ import Foundation import SSFUtils import BigInt +import SSFModels struct SubqueryRewardItemData: Equatable, Codable { let eventId: String diff --git a/fearless/Common/Network/BlockExplorer/Subquery/Data/SubqueryStakeData.swift b/fearless/Common/Network/BlockExplorer/Subquery/Data/SubqueryStakeData.swift index 5c53c19c98..ecc78b605a 100644 --- a/fearless/Common/Network/BlockExplorer/Subquery/Data/SubqueryStakeData.swift +++ b/fearless/Common/Network/BlockExplorer/Subquery/Data/SubqueryStakeData.swift @@ -1,6 +1,7 @@ import Foundation import SSFUtils import BigInt +import SSFModels struct SubqueryStakeChangeData { let eventId: String diff --git a/fearless/Common/Network/BlockExplorer/Subquery/Data/SubqueryTransfer.swift b/fearless/Common/Network/BlockExplorer/Subquery/Data/SubqueryTransfer.swift index 4c59e0085a..9d276bb9ad 100644 --- a/fearless/Common/Network/BlockExplorer/Subquery/Data/SubqueryTransfer.swift +++ b/fearless/Common/Network/BlockExplorer/Subquery/Data/SubqueryTransfer.swift @@ -16,7 +16,7 @@ struct SubqueryTransfer: Decodable { let amount: String let receiver: String let sender: String - let fee: String + let fee: String? let block: String? let extrinsicId: String? let extrinsicHash: String? diff --git a/fearless/Common/Network/Misc/SubstrateOperationFactory.swift b/fearless/Common/Network/Misc/SubstrateOperationFactory.swift index 56165d87f0..7e37d33f8f 100644 --- a/fearless/Common/Network/Misc/SubstrateOperationFactory.swift +++ b/fearless/Common/Network/Misc/SubstrateOperationFactory.swift @@ -14,12 +14,15 @@ final class SubstrateOperationFactory: SubstrateOperationFactoryProtocol { } func fetchChainOperation(_ url: URL) -> BaseOperation { + guard let connectionStrategy = ConnectionStrategyImpl( + urls: [url], + callbackQueue: .global() + ) else { + return BaseOperation.createWithError(WebSocketEngineError.emptyUrls) + } let engine = WebSocketEngine( connectionName: nil, - url: url, - reachabilityManager: nil, - reconnectionStrategy: nil, - logger: nil + connectionStrategy: connectionStrategy ) return JSONRPCListOperation(engine: engine, method: RPCMethod.chain) diff --git a/fearless/Common/Network/Operations/ManualOperation.swift b/fearless/Common/Network/Operations/ManualOperation.swift index 11900baa9b..836aee8bce 100644 --- a/fearless/Common/Network/Operations/ManualOperation.swift +++ b/fearless/Common/Network/Operations/ManualOperation.swift @@ -61,7 +61,9 @@ final class ManualOperation: BaseOperation { } func finish() { - isExecuting = false - isFinished = true + if isExecuting { + isExecuting = false + isFinished = true + } } } diff --git a/fearless/Common/Network/Subscan/Data/SubscanRawExtrinsicData.swift b/fearless/Common/Network/Subscan/Data/SubscanRawExtrinsicData.swift index 324c4f0f5e..47c88adca7 100644 --- a/fearless/Common/Network/Subscan/Data/SubscanRawExtrinsicData.swift +++ b/fearless/Common/Network/Subscan/Data/SubscanRawExtrinsicData.swift @@ -1,5 +1,6 @@ import Foundation import SSFUtils +import SSFModels struct SubscanRawExtrinsicsData: Decodable { let count: Int diff --git a/fearless/Common/Operation/StorageDecodingOperation.swift b/fearless/Common/Operation/StorageDecodingOperation.swift index b76fade666..3834e7a05b 100644 --- a/fearless/Common/Operation/StorageDecodingOperation.swift +++ b/fearless/Common/Operation/StorageDecodingOperation.swift @@ -2,6 +2,7 @@ import Foundation import SSFUtils import RobinHood import SSFRuntimeCodingService +import SSFModels enum StorageDecodingOperationError: Error { case missingRequiredParams diff --git a/fearless/Common/Protocols/BaseErrorPresentable.swift b/fearless/Common/Protocols/BaseErrorPresentable.swift index edebe67081..4a65898beb 100644 --- a/fearless/Common/Protocols/BaseErrorPresentable.swift +++ b/fearless/Common/Protocols/BaseErrorPresentable.swift @@ -30,8 +30,8 @@ protocol BaseErrorPresentable { ) func presentSoraBridgeLowAmountError( from view: ControllerBackedProtocol, - originChainId: ChainModel.Id, - locale: Locale + locale: Locale, + assetAmount: String ) func presentWarning( for title: String, @@ -224,20 +224,10 @@ extension BaseErrorPresentable where Self: SheetAlertPresentable & ErrorPresenta func presentSoraBridgeLowAmountError( from view: ControllerBackedProtocol, - originChainId: ChainModel.Id, - locale: Locale + locale: Locale, + assetAmount: String ) { - let originKnownChain = Chain(chainId: originChainId) - let message: String? - switch originKnownChain { - case .kusama: - message = R.string.localizable.soraBridgeLowAmountAlert(preferredLanguages: locale.rLanguages) - case .polkadot, .soraMain: - message = R.string.localizable.soraBridgeLowAmauntPolkadotAlert(preferredLanguages: locale.rLanguages) - default: - message = nil - } - + let message: String? = R.string.localizable.xcmLowAmauntAssetSymbolAlert(assetAmount, preferredLanguages: locale.rLanguages) let title = R.string.localizable.commonAttention(preferredLanguages: locale.rLanguages) let closeTitle = R.string.localizable.commonCancel(preferredLanguages: locale.rLanguages) present(message: message, title: title, closeAction: closeTitle, from: view, actions: []) diff --git a/fearless/Common/PurchaseProvider/MoonpayProvider.swift b/fearless/Common/PurchaseProvider/MoonpayProvider.swift index c6ebeaed31..2ecd88653f 100644 --- a/fearless/Common/PurchaseProvider/MoonpayProvider.swift +++ b/fearless/Common/PurchaseProvider/MoonpayProvider.swift @@ -33,7 +33,7 @@ final class MoonpayProvider: PurchaseProviderProtocol { } func buildPurchaseActions(asset: AssetModel, address: String) -> [PurchaseAction] { - if let url = buildURLForToken(asset.id, address: address) { + if let url = buildURLForToken(asset.symbol, address: address) { return [PurchaseAction(title: Constants.title, url: url, icon: Constants.icon!)] } return [] diff --git a/fearless/Common/PurchaseProvider/PurchaseAggregator+Default.swift b/fearless/Common/PurchaseProvider/PurchaseAggregator+Default.swift index 4cd3c7b41c..cf3a21610c 100644 --- a/fearless/Common/PurchaseProvider/PurchaseAggregator+Default.swift +++ b/fearless/Common/PurchaseProvider/PurchaseAggregator+Default.swift @@ -1,19 +1,19 @@ import Foundation extension PurchaseAggregator { - static func defaultAggregator() -> PurchaseAggregator { + static func defaultAggregator(with purchaseProviders: [PurchaseProviderProtocol]?) -> PurchaseAggregator { let config: ApplicationConfigProtocol = ApplicationConfig.shared let moonpaySecretKeyData = Data(MoonPayKeys.secretKey.utf8) - let purchaseProviders: [PurchaseProviderProtocol] = [ + let defaultProviders: [PurchaseProviderProtocol] = [ RampProvider(), MoonpayProviderFactory().createProvider( with: moonpaySecretKeyData, apiKey: config.moonPayApiKey ) ] - return PurchaseAggregator(providers: purchaseProviders) + return PurchaseAggregator(providers: purchaseProviders ?? defaultProviders) .with(appName: config.purchaseAppName) .with(logoUrl: config.logoURL) .with(colorCode: R.color.colorPink()!.hexRGB) diff --git a/fearless/Common/QRCoding/BokoloCashQRInfo.swift b/fearless/Common/QRCoding/BokoloCashQRInfo.swift deleted file mode 100644 index 61e9686953..0000000000 --- a/fearless/Common/QRCoding/BokoloCashQRInfo.swift +++ /dev/null @@ -1,68 +0,0 @@ -import Foundation -import SSFQRService -#if F_RELEASE - import MPQRCoreSDK -#endif - -struct BokoloCashQRInfo: QRInfo { - let address: String - let assetId: String? - let transactionAmount: String? -} - -final class BokoloCashDecoder: QRDecoderProtocol { - #if F_RELEASE - func decode(data: Data) throws -> QRInfoType { - guard - let incomingURL = URL(dataRepresentation: data, relativeTo: nil, isAbsolute: true), - let payload = fetchPayloadData(url: incomingURL) - else { - throw QRDecoderError.brokenFormat - } - - let payloadData = try MPQRParser.parse(string: payload) - - var maiData: MAIData? - for value in EMVQRConstants.availableIDTags { - if let item = try? payloadData.getMAIData(forTagString: value) { - maiData = item - break - } - } - - guard let accountId = maiData?.AID else { - throw QRDecoderError.accountIdMismatch - } - - let qrInfo = BokoloCashQRInfo( - address: accountId, - assetId: payloadData.transactionCurrencyCode, - transactionAmount: payloadData.transactionAmount - ) - return .bokoloCash(qrInfo) - } - #else - func decode(data _: Data) throws -> QRInfoType { - throw ConvenienceError(error: "Not available on simulator") - } - #endif - - private func fetchPayloadData(url: URL?) -> String? { - guard - let url = url, - let longComponents = URLComponents(url: url, resolvingAgainstBaseURL: false), - let queryItems = longComponents.queryItems, - let qr = queryItems.first(where: { component in - component.name == "qr" - }) - else { - return nil - } - - return qr.value?.replacingOccurrences(of: "+", with: " ") - } -} - -enum EMVQRConstants { - static let availableIDTags = Array(26 ... 51).map { String($0) } -} diff --git a/fearless/Common/QRCoding/CexQRInfo.swift b/fearless/Common/QRCoding/CexQRInfo.swift deleted file mode 100644 index e4f73478a0..0000000000 --- a/fearless/Common/QRCoding/CexQRInfo.swift +++ /dev/null @@ -1,32 +0,0 @@ -import Foundation -import SSFQRService - -struct CexQRInfo: QRInfo, Equatable { - let address: String -} - -final class CexQREncoder { - func encode(address: String) throws -> Data { - guard let data = address.data(using: .utf8) else { - throw QREncoderError.brokenData - } - return data - } -} - -final class CexQRDecoder: QRDecoderProtocol { - func decode(data: Data) throws -> QRInfoType { - guard let address = String(data: data, encoding: .utf8) else { - throw QRDecoderError.brokenFormat - } - - let substrateAccountId = try? address.toAccountIdWithTryExtractPrefix() - let ethereumAccountId = try? address.toAccountIdWithTryExtractPrefix() - - guard substrateAccountId != nil || ethereumAccountId != nil else { - throw QRDecoderError.brokenFormat - } - - return .cex(CexQRInfo(address: address)) - } -} diff --git a/fearless/Common/QRCoding/QRCoderFactory.swift b/fearless/Common/QRCoding/QRCoderFactory.swift deleted file mode 100644 index e35ea53b03..0000000000 --- a/fearless/Common/QRCoding/QRCoderFactory.swift +++ /dev/null @@ -1,68 +0,0 @@ -import Foundation - -protocol QRCoderFactoryProtocol { - func createEncoder() -> QREncoderProtocol - func createDecoder() -> QRDecoderProtocol -} - -protocol QREncoderProtocol { - func encode(with type: QRType) throws -> Data -} - -enum QRInfoType { - case bokoloCash(BokoloCashQRInfo) - case sora(SoraQRInfo) - case cex(CexQRInfo) -} - -protocol QRDecoderProtocol { - func decode(data: Data) throws -> QRInfoType -} - -enum QRType { - case address(String) - case addressInfo(SoraQRInfo) -} - -final class QRCoderFactory: QRCoderFactoryProtocol { - func createEncoder() -> QREncoderProtocol { - QREncoder() - } - - func createDecoder() -> QRDecoderProtocol { - QRDecoder() - } -} - -final class QREncoder: QREncoderProtocol { - func encode(with type: QRType) throws -> Data { - switch type { - case let .address(address): - return try CexQREncoder().encode(address: address) - case let .addressInfo(addressInfo): - return try SoraQREncoder().encode(addressInfo: addressInfo) - } - } -} - -final class QRDecoder: QRDecoderProtocol { - private lazy var qrDecoders: [QRDecoderProtocol] = [ - BokoloCashDecoder(), - SoraQRDecoder(), - CexQRDecoder() - ] - - func decode(data: Data) throws -> QRInfoType { - let types = qrDecoders.compactMap { - try? $0.decode(data: data) - } - guard - types.count == 1, - let infoType = types.first - else { - throw ConvenienceError(error: "Qr must have one coincidence") - } - - return infoType - } -} diff --git a/fearless/Common/QRCoding/QRCreationOperation.swift b/fearless/Common/QRCoding/QRCreationOperation.swift deleted file mode 100644 index a6a1187e86..0000000000 --- a/fearless/Common/QRCoding/QRCreationOperation.swift +++ /dev/null @@ -1,70 +0,0 @@ -import UIKit -import CoreImage -import RobinHood - -enum QRCreationOperationError: Error { - case generatorUnavailable - case generatedImageInvalid - case bitmapImageCreationFailed -} - -public final class QRCreationOperation: BaseOperation { - let payload: Data - let qrSize: CGSize - - init(payload: Data, qrSize: CGSize) { - self.payload = payload - self.qrSize = qrSize - - super.init() - } - - override public func main() { - super.main() - - guard let filter = CIFilter(name: "CIQRCodeGenerator") else { - if !isCancelled { - result = .failure(QRCreationOperationError.generatorUnavailable) - } - - return - } - - filter.setValue(payload, forKey: "inputMessage") - filter.setValue("Q", forKey: "inputCorrectionLevel") - - guard let qrImage = filter.outputImage else { - if !isCancelled { - result = .failure(QRCreationOperationError.generatedImageInvalid) - } - - return - } - - let transformedImage: CIImage - - if qrImage.extent.size.width * qrImage.extent.height > 0.0 { - let transform = CGAffineTransform( - scaleX: qrSize.width / qrImage.extent.width, - y: qrSize.height / qrImage.extent.height - ) - transformedImage = qrImage.transformed(by: transform) - } else { - transformedImage = qrImage - } - - let context = CIContext() - - guard let cgImage = context.createCGImage(transformedImage, from: transformedImage.extent) else { - if !isCancelled { - result = .failure(QRCreationOperationError.bitmapImageCreationFailed) - } - - return - } - - if !isCancelled { - result = .success(UIImage(cgImage: cgImage)) - } - } -} diff --git a/fearless/Common/QRCoding/QRService.swift b/fearless/Common/QRCoding/QRService.swift deleted file mode 100644 index 8d316cd120..0000000000 --- a/fearless/Common/QRCoding/QRService.swift +++ /dev/null @@ -1,60 +0,0 @@ -import RobinHood -import UIKit - -protocol QROperationFactoryProtocol: AnyObject { - func createCreationOperation(for payload: Data, qrSize: CGSize) -> QRCreationOperation -} - -final class QROperationFactory: QROperationFactoryProtocol { - func createCreationOperation(for payload: Data, qrSize: CGSize) -> QRCreationOperation { - QRCreationOperation(payload: payload, qrSize: qrSize) - } -} - -protocol QRServiceProtocol: AnyObject { - @discardableResult - func generate( - with qrType: QRType, - qrSize: CGSize, - runIn queue: DispatchQueue, - completionBlock: @escaping (Result?) -> Void - ) throws -> Operation -} - -final class QRService { - private let operationFactory: QROperationFactoryProtocol - private let operationQueue: OperationQueue - private let encoder: QREncoderProtocol - - init( - operationFactory: QROperationFactoryProtocol, - encoder: QREncoderProtocol = QREncoder(), - operationQueue: OperationQueue = OperationQueue() - ) { - self.operationFactory = operationFactory - self.encoder = encoder - self.operationQueue = operationQueue - } -} - -extension QRService: QRServiceProtocol { - @discardableResult - func generate( - with qrType: QRType, - qrSize: CGSize, - runIn queue: DispatchQueue, - completionBlock: @escaping (Result?) -> Void - ) throws -> Operation { - let payload = try encoder.encode(with: qrType) - let operation = operationFactory.createCreationOperation(for: payload, qrSize: qrSize) - - operation.completionBlock = { - queue.async { - completionBlock(operation.result) - } - } - - operationQueue.addOperation(operation) - return operation - } -} diff --git a/fearless/Common/QRCoding/SoraQRInfo.swift b/fearless/Common/QRCoding/SoraQRInfo.swift deleted file mode 100644 index 39151e1850..0000000000 --- a/fearless/Common/QRCoding/SoraQRInfo.swift +++ /dev/null @@ -1,94 +0,0 @@ -import Foundation -import SSFQRService - -struct SoraQRInfo: QRInfo, Equatable { - let prefix: String - let address: String - let rawPublicKey: Data - let username: String - let assetId: String - let amount: String? - - init( - prefix: String = SubstrateQRConstants.prefix, - address: String, - rawPublicKey: Data, - username: String, - assetId: String, - amount: String? - ) { - self.prefix = prefix - self.address = address - self.rawPublicKey = rawPublicKey - self.username = username - self.assetId = assetId - self.amount = amount - } -} - -final class SoraQREncoder { - private let separator: String - - init(separator: String = SubstrateQRConstants.fieldsSeparator) { - self.separator = separator - } - - func encode(addressInfo: SoraQRInfo) throws -> Data { - let fields: [String] = [ - addressInfo.prefix, - addressInfo.address, - addressInfo.rawPublicKey.toHex(includePrefix: true), - addressInfo.username, - addressInfo.assetId, - addressInfo.amount - ].compactMap { $0 } - - guard let data = fields.joined(separator: separator).data(using: .utf8) else { - throw QREncoderError.brokenData - } - - return data - } -} - -final class SoraQRDecoder: QRDecoderProtocol { - public func decode(data: Data) throws -> QRInfoType { - guard let decodedString = String(data: data, encoding: .utf8) else { - throw QRDecoderError.brokenFormat - } - - let fields = decodedString.components(separatedBy: SubstrateQRConstants.fieldsSeparator) - - guard fields.count >= 3 else { - throw QRDecoderError.unexpectedNumberOfFields - } - - let prefix = fields[0] - let address = fields[1] - let publicKey = try Data(hexStringSSF: fields[2]) - let username = fields[3] - let assetId = fields[4] - let amount = fields[safe: 5] - - if address.hasPrefix("0x") { - let qrInfo = SoraQRInfo( - address: address, - rawPublicKey: publicKey, - username: username, - assetId: assetId, - amount: amount - ) - return .sora(qrInfo) - } - - let qrInfo = SoraQRInfo( - prefix: prefix, - address: address, - rawPublicKey: publicKey, - username: username, - assetId: assetId, - amount: amount - ) - return .sora(qrInfo) - } -} diff --git a/fearless/Common/Services/ChainRegistry/ChainRegistry.swift b/fearless/Common/Services/ChainRegistry/ChainRegistry.swift index dc6d316f70..e15388df5d 100644 --- a/fearless/Common/Services/ChainRegistry/ChainRegistry.swift +++ b/fearless/Common/Services/ChainRegistry/ChainRegistry.swift @@ -17,6 +17,7 @@ protocol ChainRegistryProtocol: AnyObject { func getConnection(for chainId: ChainModel.Id) -> ChainConnection? func getRuntimeProvider(for chainId: ChainModel.Id) -> RuntimeProviderProtocol? func getChain(for chainId: ChainModel.Id) -> ChainModel? + func getChainUnsafe(for chainId: ChainModel.Id) -> ChainModel? func chainsSubscribe( _ target: AnyObject, runningInQueue: DispatchQueue, @@ -306,7 +307,7 @@ extension ChainRegistry: ChainRegistryProtocol { return nil } - return readLock.concurrentlyRead { substrateConnectionPool.getConnection(for: chainId) } + return substrateConnectionPool.getConnection(for: chainId) } func getEthereumConnection(for chainId: ChainModel.Id) -> Web3.Eth? { @@ -326,6 +327,10 @@ extension ChainRegistry: ChainRegistryProtocol { readLock.concurrentlyRead { chains.first(where: { $0.chainId == chainId }) } } + func getChainUnsafe(for chainId: ChainModel.Id) -> ChainModel? { + chains.first(where: { $0.chainId == chainId }) + } + func getRuntimeProvider(for chainId: ChainModel.Id) -> RuntimeProviderProtocol? { runtimeProviderPool.getRuntimeProvider(for: chainId) } @@ -385,63 +390,26 @@ extension ChainRegistry: ChainRegistryProtocol { func retryConnection(for chainId: ChainModel.Id) { guard let chain = chains.first(where: { $0.chainId == chainId }), - let currentConnection = getConnection(for: chainId), - let currentURL = currentConnection.url + let currentConnection = getConnection(for: chainId) else { return } - connectionNeedsReconnect(for: chain, previusUrl: currentURL) + currentConnection.connectIfNeeded() } } // MARK: - ConnectionPoolDelegate extension ChainRegistry: ConnectionPoolDelegate { - func webSocketDidChangeState(url: URL, state: WebSocketEngine.State) { + func webSocketDidChangeState(chainId: SSFModels.ChainModel.Id, state: SSFUtils.WebSocketEngine.State) { guard let changedStateChain = chains.first(where: { chain in - chain.nodes.first { node in - node.url == url - } != nil + chain.chainId == chainId }) else { return } - if case .connected = state { - let reconnectedEvent = ChainReconnectingEvent(chain: changedStateChain, state: state) - eventCenter.notify(with: reconnectedEvent) - } - - switch state { - case let .waitingReconnection(attempt: attempt): - if attempt > NetworkConstants.websocketReconnectAttemptsLimit { - connectionNeedsReconnect(for: changedStateChain, previusUrl: url) - } - case .notConnected: - connectionNeedsReconnect(for: changedStateChain, previusUrl: url) - default: - break - } - } - - func connectionNeedsReconnect(for chain: ChainModel, previusUrl: URL) { - guard chain.selectedNode == nil else { - return - } - - do { - if chain.isEthereum { - // TODO: Ethereum reconnect - } else { - _ = try substrateConnectionPool?.setupConnection(for: chain, ignoredUrl: previusUrl) - } - - let event = ChainsUpdatedEvent(updatedChains: [chain]) - eventCenter.notify(with: event) - } catch { - logger?.error("\(chain.name) error: \(error.localizedDescription)") - let reconnectedEvent = ChainReconnectingEvent(chain: chain, state: .notConnected) - eventCenter.notify(with: reconnectedEvent) - } + let reconnectedEvent = ChainReconnectingEvent(chain: changedStateChain, state: state) + eventCenter.notify(with: reconnectedEvent) } } @@ -461,10 +429,12 @@ extension ChainRegistry: SSFChainRegistry.ChainRegistryProtocol { usedRuntimePaths _: [String: [String]], runtimeItem _: SSFModels.RuntimeMetadataItemProtocol? ) async throws -> SSFRuntimeCodingService.RuntimeProviderProtocol { - let runtimeProvider = readLock.concurrentlyRead { runtimeProviderPool.getRuntimeProvider(for: chainId) } - guard let runtimeProvider else { - throw ChainRegistryError.runtimeMetadaUnavailable + guard let chain = chains.first(where: { $0.chainId == chainId }) else { + throw ChainRegistryError.chainUnavailable(chainId: chainId) } + let chainTypes = chainsTypesMap[chainId] + + let runtimeProvider = runtimeProviderPool.setupRuntimeProvider(for: chain, chainTypes: chainTypes) return runtimeProvider } diff --git a/fearless/Common/Services/ChainRegistry/ChainRegistryFactory.swift b/fearless/Common/Services/ChainRegistry/ChainRegistryFactory.swift index 198034c4d0..908e49c759 100644 --- a/fearless/Common/Services/ChainRegistry/ChainRegistryFactory.swift +++ b/fearless/Common/Services/ChainRegistry/ChainRegistryFactory.swift @@ -1,4 +1,5 @@ import Foundation +import SoraFoundation import RobinHood import SSFModels import SSFNetwork @@ -82,7 +83,8 @@ final class ChainRegistryFactory { repository: AnyDataProviderRepository(chainRepository), eventCenter: EventCenter.shared, operationQueue: OperationManagerFacade.syncQueue, - logger: Logger.shared + logger: Logger.shared, + applicationHandler: ApplicationHandler() ) let specVersionSubscriptionFactory = SpecVersionSubscriptionFactory( @@ -109,10 +111,8 @@ final class ChainRegistryFactory { logger: Logger.shared ) - let queue = OperationQueue() let substrateConnectionPool = ConnectionPool( - connectionFactory: ConnectionFactory(logger: Logger.shared), - operationQueue: queue + connectionFactory: ConnectionFactory(logger: Logger.shared) ) let ethereumConnectionPool = EthereumConnectionPool() diff --git a/fearless/Common/Services/ChainRegistry/ChainSyncService.swift b/fearless/Common/Services/ChainRegistry/ChainSyncService.swift index 16cb0cfc80..4f974e47be 100644 --- a/fearless/Common/Services/ChainRegistry/ChainSyncService.swift +++ b/fearless/Common/Services/ChainRegistry/ChainSyncService.swift @@ -1,4 +1,5 @@ import Foundation +import SoraFoundation import RobinHood import SSFUtils import SSFModels @@ -24,12 +25,14 @@ final class ChainSyncService { private let repository: AnyDataProviderRepository private let eventCenter: EventCenterProtocol private let retryStrategy: ReconnectionStrategyProtocol + private let applicationHandler: ApplicationHandlerProtocol private let operationQueue: OperationQueue private let logger: LoggerProtocol? private var retryAttempt: Int = 0 private var isSyncing: Bool = false private let mutex = NSLock() + private var timer = CountdownTimer(notificationInterval: 300) private lazy var scheduler = Scheduler(with: self, callbackQueue: DispatchQueue.global()) @@ -39,7 +42,8 @@ final class ChainSyncService { eventCenter: EventCenterProtocol, operationQueue: OperationQueue, retryStrategy: ReconnectionStrategyProtocol = ExponentialReconnection(), - logger: LoggerProtocol? = nil + logger: LoggerProtocol? = nil, + applicationHandler: ApplicationHandlerProtocol ) { self.syncService = syncService self.repository = repository @@ -47,6 +51,8 @@ final class ChainSyncService { self.operationQueue = operationQueue self.retryStrategy = retryStrategy self.logger = logger + self.applicationHandler = applicationHandler + timer.delegate = self } private func performSyncUpIfNeeded() { @@ -55,7 +61,9 @@ final class ChainSyncService { return } - isSyncing = true + DispatchQueue.main.async { + self.timer.start(with: 300) + } retryAttempt += 1 logger?.debug("Will start chain sync with attempt \(retryAttempt)") @@ -66,6 +74,13 @@ final class ChainSyncService { executeSync() } + private func setApplicationDelegateIfNeeded() { + guard applicationHandler.delegate == nil else { + return + } + applicationHandler.delegate = self + } + private func executeSync() { if Self.fetchLocalData { do { @@ -186,17 +201,28 @@ final class ChainSyncService { return try JSONDecoder().decode([ChainModel].self, from: data) } - private func complete(result: Result?) { - isSyncing = false - + private func complete(result: Result) { switch result { case let .success(changes): - logger?.debug( - """ - Sync completed: \(changes.newOrUpdatedItems) (new or updated), - \(changes.removedItems) (removed) - """ - ) + if changes.newOrUpdatedItems.isNotEmpty { + logger?.warning( + """ + !!!! Make shure what chains.json was changed, if you see this message without chains.json changes, equatable ChainModel is broken !!!! + """ + ) + logger?.debug( + """ + Sync completed: \(changes.newOrUpdatedItems.map { $0.name }) (new or updated) + """ + ) + } + if changes.removedItems.isNotEmpty { + logger?.debug( + """ + Sync completed: \(changes.removedItems.map { $0.name }) (removed) + """ + ) + } retryAttempt = 0 @@ -208,17 +234,10 @@ final class ChainSyncService { eventCenter.notify(with: event) case let .failure(error): logger?.error("Sync failed with error: \(error)") - + timer.stop() let event = ChainSyncDidFail(error: error) eventCenter.notify(with: event) - retry() - case .none: - logger?.error("Sync failed with no result") - - let event = ChainSyncDidFail(error: BaseOperationError.unexpectedDependentResult) - eventCenter.notify(with: event) - retry() } } @@ -244,6 +263,7 @@ extension ChainSyncService: ChainSyncServiceProtocol { scheduler.cancel() } + setApplicationDelegateIfNeeded() performSyncUpIfNeeded() } } @@ -259,3 +279,21 @@ extension ChainSyncService: SchedulerDelegate { performSyncUpIfNeeded() } } + +extension ChainSyncService: CountdownTimerDelegate { + func didStart(with _: TimeInterval) { + isSyncing = true + } + + func didCountdown(remainedInterval _: TimeInterval) {} + + func didStop(with _: TimeInterval) { + isSyncing = false + } +} + +extension ChainSyncService: ApplicationHandlerDelegate { + func didReceiveDidBecomeActive(notification _: Notification) { + performSyncUpIfNeeded() + } +} diff --git a/fearless/Common/Services/ChainRegistry/ConnectionPool/ConnectionFactory.swift b/fearless/Common/Services/ChainRegistry/ConnectionPool/ConnectionFactory.swift index 426c06b336..15432088ab 100644 --- a/fearless/Common/Services/ChainRegistry/ConnectionPool/ConnectionFactory.swift +++ b/fearless/Common/Services/ChainRegistry/ConnectionPool/ConnectionFactory.swift @@ -6,9 +6,9 @@ typealias ChainConnection = JSONRPCEngine protocol ConnectionFactoryProtocol { func createConnection( connectionName: String?, - for url: URL, + for urls: [URL], delegate: WebSocketEngineDelegate - ) -> ChainConnection + ) throws -> ChainConnection } final class ConnectionFactory { @@ -25,14 +25,19 @@ final class ConnectionFactory { extension ConnectionFactory: ConnectionFactoryProtocol { func createConnection( connectionName: String?, - for url: URL, + for urls: [URL], delegate: WebSocketEngineDelegate - ) -> ChainConnection { + ) throws -> ChainConnection { + guard let connectionStrategy = ConnectionStrategyImpl( + urls: urls, + callbackQueue: processingQueue + ) else { + throw ConnectionPoolError.noConnection + } let engine = WebSocketEngine( connectionName: connectionName, - url: url, - processingQueue: processingQueue, - logger: nil + connectionStrategy: connectionStrategy, + processingQueue: processingQueue ) engine.delegate = delegate return engine diff --git a/fearless/Common/Services/ChainRegistry/ConnectionPool/ConnectionPool.swift b/fearless/Common/Services/ChainRegistry/ConnectionPool/ConnectionPool.swift index a8b4aec439..d22d521631 100644 --- a/fearless/Common/Services/ChainRegistry/ConnectionPool/ConnectionPool.swift +++ b/fearless/Common/Services/ChainRegistry/ConnectionPool/ConnectionPool.swift @@ -5,43 +5,42 @@ import SSFModels enum ConnectionPoolError: Error { case onlyOneNode + case noConnection } protocol ConnectionPoolProtocol { associatedtype T func setupConnection(for chain: ChainModel) throws -> T - func setupConnection(for chain: ChainModel, ignoredUrl: URL?) throws -> T func getConnection(for chainId: ChainModel.Id) -> T? func setDelegate(_ delegate: ConnectionPoolDelegate) func resetConnection(for chainId: ChainModel.Id) } protocol ConnectionPoolDelegate: AnyObject { - func webSocketDidChangeState(url: URL, state: WebSocketEngine.State) + func webSocketDidChangeState(chainId: ChainModel.Id, state: WebSocketEngine.State) } final class ConnectionPool { + struct ConnectionWrapper { + let chainId: String + let connection: WeakWrapper + } + private let connectionFactory: ConnectionFactoryProtocol private let applicationHandler = ApplicationHandler() + private lazy var injector = NodeApiKeyInjector() private weak var delegate: ConnectionPoolDelegate? - private let operationQueue: OperationQueue - - private lazy var lock = ReaderWriterLock() - private lazy var connectionLock = ReaderWriterLock() - private(set) var connectionsByChainIds: [ChainModel.Id: WeakWrapper] = [:] - private var failedUrls: [ChainModel.Id: Set] = [:] + private(set) var connections: SafeArray = .init() - private func clearUnusedConnections() { - connectionLock.exclusivelyWrite { - self.connectionsByChainIds = self.connectionsByChainIds.filter { $0.value.target != nil } - } + init(connectionFactory: ConnectionFactoryProtocol) { + self.connectionFactory = connectionFactory } - init(connectionFactory: ConnectionFactoryProtocol, operationQueue: OperationQueue) { - self.connectionFactory = connectionFactory - self.operationQueue = operationQueue + private func clearUnusedConnections() { + let filtred = connections.filter { $0.connection.target != nil } + connections.replace(array: filtred) } } @@ -50,84 +49,42 @@ final class ConnectionPool { extension ConnectionPool: ConnectionPoolProtocol { typealias T = ChainConnection - func setDelegate(_ delegate: ConnectionPoolDelegate) { - self.delegate = delegate - } - func setupConnection(for chain: ChainModel) throws -> ChainConnection { - try setupConnection(for: chain, ignoredUrl: nil) - } - - func setupConnection(for chain: ChainModel, ignoredUrl: URL?) throws -> ChainConnection { - if ignoredUrl == nil, - let connection = getConnection(for: chain.chainId) { + if let connection = getConnection(for: chain.chainId) { return connection } - - var chainFailedUrls = getFailedUrls(for: chain.chainId).or([]) - chainFailedUrls.insert(ignoredUrl) - -// If all available nodes are in blacklist => Remove all nodes except last one checked - if chainFailedUrls.count == chain.nodes.count { - lock.exclusivelyWrite { [weak self] in - self?.failedUrls[chain.chainId] = [ignoredUrl] - } - } - let node = chain.selectedNode ?? chain.nodes.first(where: { - ($0.url != ignoredUrl) && !chainFailedUrls.contains($0.url) - }) - - lock.exclusivelyWrite { [weak self] in - self?.failedUrls[chain.chainId] = chainFailedUrls + let nodesForPreparing: [ChainNodeModel] + if let selectedNode = chain.selectedNode { + nodesForPreparing = [selectedNode] + } else { + nodesForPreparing = Array(chain.nodes) } - guard let node = node else { - throw ConnectionPoolError.onlyOneNode - } - let url = DwillerApiKeyInjector().apiKeyInjectedURL(node: node) - - clearUnusedConnections() - - if let connection = getConnection(for: chain.chainId) { - if connection.url == url { - return connection - } else if ignoredUrl != nil { - connection.reconnect(url: url) - return connection - } - } - - let connection = connectionFactory.createConnection( - connectionName: chain.name, - for: url, + let preparedUrls = injector.injectKey(nodes: nodesForPreparing) + let connection = try connectionFactory.createConnection( + connectionName: chain.chainId, + for: preparedUrls, delegate: self ) - let wrapper = WeakWrapper(target: connection) - - connectionLock.exclusivelyWrite { [weak self] in - self?.connectionsByChainIds[chain.chainId] = wrapper - } + let wrapper = ConnectionWrapper(chainId: chain.chainId, connection: WeakWrapper(target: connection)) + connections.append(wrapper) return connection } - func getFailedUrls(for chainId: ChainModel.Id) -> Set? { - lock.concurrentlyRead { failedUrls[chainId] } + func getConnection(for chainId: ChainModel.Id) -> ChainConnection? { + connections.first(where: { $0.chainId == chainId })?.connection.target as? ChainConnection } - func getConnection(for chainId: ChainModel.Id) -> ChainConnection? { - connectionLock.concurrentlyRead { connectionsByChainIds[chainId]?.target as? ChainConnection } + func setDelegate(_ delegate: any ConnectionPoolDelegate) { + self.delegate = delegate } func resetConnection(for chainId: ChainModel.Id) { if let connection = getConnection(for: chainId) { connection.disconnectIfNeeded() } - - connectionLock.exclusivelyWrite { - self.connectionsByChainIds = self.connectionsByChainIds.filter { $0.key != chainId } - self.failedUrls[chainId] = nil - } + connections.remove(where: { $0.chainId == chainId }) } } @@ -136,27 +93,12 @@ extension ConnectionPool: ConnectionPoolProtocol { extension ConnectionPool: WebSocketEngineDelegate { func webSocketDidChangeState( engine: WebSocketEngine, - from _: WebSocketEngine.State, to newState: WebSocketEngine.State ) { - guard let previousUrl = engine.url else { + guard let chainId = engine.connectionName else { return } - delegate?.webSocketDidChangeState(url: previousUrl, state: newState) - } -} - -struct DwillerApiKeyInjector { - func apiKeyInjectedURL(node: ChainNodeModel) -> URL { - guard node.name.lowercased().contains("dwellir") else { - return node.url - } - #if DEBUG - return node.url - #else - let apiKey = DwellirNodeApiKey.dwellirApiKey - return node.url.appendingPathComponent("/\(apiKey)") - #endif + delegate?.webSocketDidChangeState(chainId: chainId, state: newState) } } diff --git a/fearless/Common/Services/ChainRegistry/ConnectionPool/EthereumConnectionPool.swift b/fearless/Common/Services/ChainRegistry/ConnectionPool/EthereumConnectionPool.swift index ac76855389..474610408c 100644 --- a/fearless/Common/Services/ChainRegistry/ConnectionPool/EthereumConnectionPool.swift +++ b/fearless/Common/Services/ChainRegistry/ConnectionPool/EthereumConnectionPool.swift @@ -27,14 +27,6 @@ final class EthereumConnectionPool: ConnectionPoolProtocol { return ws } - func setupConnection(for chain: SSFModels.ChainModel, ignoredUrl _: URL?) throws -> Web3.Eth { - // TODO: Ignored URL handling - let ws = try EthereumNodeFetching().getNode(for: chain) - connectionsByChainIds[chain.chainId] = ws - - return ws - } - func getConnection(for chainId: ChainModel.Id) -> Web3.Eth? { lock.lock() defer { diff --git a/fearless/Common/Services/ChainRegistry/ConnectionPool/NodeApiKeyInjector.swift b/fearless/Common/Services/ChainRegistry/ConnectionPool/NodeApiKeyInjector.swift new file mode 100644 index 0000000000..ed13b3749b --- /dev/null +++ b/fearless/Common/Services/ChainRegistry/ConnectionPool/NodeApiKeyInjector.swift @@ -0,0 +1,18 @@ +import Foundation +import SSFModels + +struct NodeApiKeyInjector { + func injectKey(nodes: [ChainNodeModel]) -> [URL] { + nodes.map { + guard $0.name.lowercased().contains("dwellir") else { + return $0.url + } + #if DEBUG + return $0.url + #else + let apiKey = DwellirNodeApiKey.dwellirApiKey + return $0.url.appendingPathComponent("/\(apiKey)") + #endif + } + } +} diff --git a/fearless/Common/Services/ChainRegistry/RuntimeProviderPool/ChainsTypesSyncService.swift b/fearless/Common/Services/ChainRegistry/RuntimeProviderPool/ChainsTypesSyncService.swift index 3a72e80207..3719d2409d 100644 --- a/fearless/Common/Services/ChainRegistry/RuntimeProviderPool/ChainsTypesSyncService.swift +++ b/fearless/Common/Services/ChainRegistry/RuntimeProviderPool/ChainsTypesSyncService.swift @@ -1,6 +1,7 @@ import Foundation import SSFUtils import RobinHood +import SSFModels enum ChainsTypesSyncError: Error { case missingChainId diff --git a/fearless/Common/Services/ChainRegistry/RuntimeProviderPool/RuntimeProvider.swift b/fearless/Common/Services/ChainRegistry/RuntimeProviderPool/RuntimeProvider.swift index 07d4b4b244..e9c1a42856 100644 --- a/fearless/Common/Services/ChainRegistry/RuntimeProviderPool/RuntimeProvider.swift +++ b/fearless/Common/Services/ChainRegistry/RuntimeProviderPool/RuntimeProvider.swift @@ -202,6 +202,25 @@ final class RuntimeProvider { } } +// <<<<<<< HEAD +// func fetchCoderFactoryOperation( +// with _: TimeInterval, +// closure _: RuntimeMetadataClosure? +// ) -> BaseOperation { +// AwaitOperation { [weak self] in +// try await withCheckedThrowingContinuation { continuation in +// self?.fetchCoderFactory(runCompletionIn: nil) { factory in +// guard let factory = factory else { +// continuation.resume(with: .failure(RuntimeProviderError.providerUnavailable)) +// return +// } +// +// continuation.resume(with: .success(factory)) +// } +// } +// } +//======= + // MARK: - RuntimeProviderProtocol extension RuntimeProvider: RuntimeProviderProtocol { diff --git a/fearless/Common/Services/ChainRegistry/RuntimeProviderPool/RuntimeProviderPool.swift b/fearless/Common/Services/ChainRegistry/RuntimeProviderPool/RuntimeProviderPool.swift index cb0ca26aa1..9cd036ec7f 100644 --- a/fearless/Common/Services/ChainRegistry/RuntimeProviderPool/RuntimeProviderPool.swift +++ b/fearless/Common/Services/ChainRegistry/RuntimeProviderPool/RuntimeProviderPool.swift @@ -78,7 +78,7 @@ extension RuntimeProviderPool: RuntimeProviderPoolProtocol { } func destroyRuntimeProvider(for chainId: ChainModel.Id) { - let runtimeProvider = runtimeProviders[chainId] + let runtimeProvider = lock.concurrentlyRead { runtimeProviders[chainId] } runtimeProvider?.cleanup() lock.exclusivelyWrite { [weak self] in diff --git a/fearless/Common/Services/ChainRegistry/RuntimeProviderPool/RuntimeSnapshot.swift b/fearless/Common/Services/ChainRegistry/RuntimeProviderPool/RuntimeSnapshot.swift new file mode 100644 index 0000000000..a7a62c2032 --- /dev/null +++ b/fearless/Common/Services/ChainRegistry/RuntimeProviderPool/RuntimeSnapshot.swift @@ -0,0 +1,16 @@ +import Foundation +import SSFUtils +import SSFModels + +// struct RuntimeSnapshot { +// let localCommonHash: String? +// let localChainTypes: Data? +// let typeRegistryCatalog: TypeRegistryCatalogProtocol +// let specVersion: UInt32 +// let txVersion: UInt32 +// let metadata: RuntimeMetadata +// +// func runtimeSpecVersion(for chain: ChainModel) -> RuntimeSpecVersion { +// RuntimeSpecVersion.version(for: chain, rawValue: specVersion) ?? RuntimeSpecVersion.defaultVersion(for: chain) +// } +// } diff --git a/fearless/Common/Services/ChainRegistry/RuntimeProviderPool/RuntimeSpecVersion.swift b/fearless/Common/Services/ChainRegistry/RuntimeProviderPool/RuntimeSpecVersion.swift new file mode 100644 index 0000000000..9f5f9818ea --- /dev/null +++ b/fearless/Common/Services/ChainRegistry/RuntimeProviderPool/RuntimeSpecVersion.swift @@ -0,0 +1,45 @@ +import Foundation +import SSFModels + +// enum RuntimeSpecVersion: UInt32, CaseIterable { +// case v9370 = 9370 +// case v9380 = 9380 +// case v9390 = 9390 +// case v9420 = 9420 +// case v9430 = 9430 +// +// static func defaultVersion(for chain: ChainModel) -> RuntimeSpecVersion { +// if chain.isPolkadotOrKusama || chain.isWestend { +// return RuntimeSpecVersion.allCases.last ?? .v9430 +// } else { +// return .v9370 +// } +// } +// +// static func version(for chain: ChainModel, rawValue: UInt32) -> RuntimeSpecVersion? { +// switch rawValue { +// case 9370: +// return .v9370 +// case 9380: +// return .v9380 +// case 9390: +// return .v9390 +// case 9420: +// return .v9420 +// case 9430: +// return .v9430 +// default: +// return defaultVersion(for: chain) +// } +// } +// +// // Helper methods +// +// func higherOrEqualThan(_ version: RuntimeSpecVersion) -> Bool { +// rawValue >= version.rawValue +// } +// +// func lowerOrEqualThan(_ version: RuntimeSpecVersion) -> Bool { +// rawValue <= version.rawValue +// } +// } diff --git a/fearless/Common/Services/ChainRegistry/RuntimeProviderPool/RuntimeSyncService.swift b/fearless/Common/Services/ChainRegistry/RuntimeProviderPool/RuntimeSyncService.swift index 1a81282b36..d065acb8f4 100644 --- a/fearless/Common/Services/ChainRegistry/RuntimeProviderPool/RuntimeSyncService.swift +++ b/fearless/Common/Services/ChainRegistry/RuntimeProviderPool/RuntimeSyncService.swift @@ -314,7 +314,7 @@ extension RuntimeSyncService: RuntimeSyncServiceProtocol { return } - if knownConnection.url != connection.url { + if knownConnection.connectionName != connection.connectionName { knownChains[chain.chainId] = connection performSync(for: chain.chainId) diff --git a/fearless/Common/Services/PayoutRewardsService/BatchMapper.swift b/fearless/Common/Services/PayoutRewardsService/BatchMapper.swift index 199de1462b..260800f86c 100644 --- a/fearless/Common/Services/PayoutRewardsService/BatchMapper.swift +++ b/fearless/Common/Services/PayoutRewardsService/BatchMapper.swift @@ -1,5 +1,6 @@ import Foundation import SSFUtils +import SSFModels final class BatchMapper: Mapping { typealias InputType = JSON diff --git a/fearless/Common/Services/PayoutRewardsService/ControllerMapper.swift b/fearless/Common/Services/PayoutRewardsService/ControllerMapper.swift index edf0342e8c..08ceb2ad81 100644 --- a/fearless/Common/Services/PayoutRewardsService/ControllerMapper.swift +++ b/fearless/Common/Services/PayoutRewardsService/ControllerMapper.swift @@ -1,5 +1,6 @@ import Foundation import SSFUtils +import SSFModels final class ControllerMapper: Mapping { typealias InputType = JSON diff --git a/fearless/Common/Services/PayoutRewardsService/NominateMapper.swift b/fearless/Common/Services/PayoutRewardsService/NominateMapper.swift index cdafb4e58a..851a032095 100644 --- a/fearless/Common/Services/PayoutRewardsService/NominateMapper.swift +++ b/fearless/Common/Services/PayoutRewardsService/NominateMapper.swift @@ -1,5 +1,6 @@ import Foundation import SSFUtils +import SSFModels final class NominateMapper: Mapping { typealias InputType = JSON diff --git a/fearless/Common/Services/PolkaswapSettingsSyncService.swift b/fearless/Common/Services/PolkaswapSettingsSyncService.swift index a13b1ab1e4..586e45e0de 100644 --- a/fearless/Common/Services/PolkaswapSettingsSyncService.swift +++ b/fearless/Common/Services/PolkaswapSettingsSyncService.swift @@ -128,7 +128,7 @@ final class PolkaswapSettingsSyncService { return [remove.version] }) - DispatchQueue.global(qos: .userInitiated).async { + DispatchQueue.global(qos: .utility).async { self.complete(result: .success(save)) } diff --git a/fearless/Common/Services/RemoteSubscription/AccountInfoUpdatingService.swift b/fearless/Common/Services/RemoteSubscription/AccountInfoUpdatingService.swift index 3d76591cf5..e8c41c1b14 100644 --- a/fearless/Common/Services/RemoteSubscription/AccountInfoUpdatingService.swift +++ b/fearless/Common/Services/RemoteSubscription/AccountInfoUpdatingService.swift @@ -77,10 +77,15 @@ final class AccountInfoUpdatingService { self.chains[newItem.chainId] = newItem } } else { - chains[newItem.chainId] = newItem + readLock.exclusivelyWrite { [weak self] in + guard let self else { return } + self.chains[newItem.chainId] = newItem + } + } + case let .update(chain): + chain.chainAssets.forEach { + addSubscriptionIfNeeded(for: $0) } - case .update: - break case let .delete(deletedIdentifier): removeSubscription(for: deletedIdentifier) } diff --git a/fearless/Common/Services/RuntimeRegistryService/RuntimeCoderFactory.swift b/fearless/Common/Services/RuntimeRegistryService/RuntimeCoderFactory.swift new file mode 100644 index 0000000000..fc7ed49e7b --- /dev/null +++ b/fearless/Common/Services/RuntimeRegistryService/RuntimeCoderFactory.swift @@ -0,0 +1,38 @@ +import Foundation +import SSFUtils + +// protocol RuntimeCoderFactoryProtocol { +// var specVersion: UInt32 { get } +// var txVersion: UInt32 { get } +// var metadata: RuntimeMetadata { get } +// +// func createEncoder() -> DynamicScaleEncoding +// func createDecoder(from data: Data) throws -> DynamicScaleDecoding +// } +// +// final class RuntimeCoderFactory: RuntimeCoderFactoryProtocol { +// let catalog: TypeRegistryCatalogProtocol +// let specVersion: UInt32 +// let txVersion: UInt32 +// let metadata: RuntimeMetadata +// +// init( +// catalog: TypeRegistryCatalogProtocol, +// specVersion: UInt32, +// txVersion: UInt32, +// metadata: RuntimeMetadata +// ) { +// self.catalog = catalog +// self.specVersion = specVersion +// self.txVersion = txVersion +// self.metadata = metadata +// } +// +// func createEncoder() -> DynamicScaleEncoding { +// DynamicScaleEncoder(registry: catalog, version: UInt64(specVersion)) +// } +// +// func createDecoder(from data: Data) throws -> DynamicScaleDecoding { +// try DynamicScaleDecoder(data: data, registry: catalog, version: UInt64(specVersion)) +// } +// } diff --git a/fearless/Common/Services/RuntimeRegistryService/RuntimeRegistryServiceProtocol.swift b/fearless/Common/Services/RuntimeRegistryService/RuntimeRegistryServiceProtocol.swift new file mode 100644 index 0000000000..a69ba1e36b --- /dev/null +++ b/fearless/Common/Services/RuntimeRegistryService/RuntimeRegistryServiceProtocol.swift @@ -0,0 +1,26 @@ +import Foundation +import RobinHood +import SSFUtils + +// typealias RuntimeMetadataClosure = () throws -> RuntimeMetadata +// +// protocol RuntimeCodingServiceProtocol { +// var snapshot: RuntimeSnapshot? { get } +// +// func fetchCoderFactoryOperation( +// with timeout: TimeInterval, +// closure: RuntimeMetadataClosure? +// ) -> BaseOperation +// +// func fetchCoderFactory() async throws -> RuntimeCoderFactoryProtocol +// } +// +// extension RuntimeCodingServiceProtocol { +// func fetchCoderFactoryOperation(with timeout: TimeInterval) -> BaseOperation { +// fetchCoderFactoryOperation(with: timeout, closure: nil) +// } +// +// func fetchCoderFactoryOperation() -> BaseOperation { +// fetchCoderFactoryOperation(with: 20, closure: nil) +// } +// } diff --git a/fearless/Common/Services/ServiceCoordinator.swift b/fearless/Common/Services/ServiceCoordinator.swift index b6afb02e8b..78a5112cd7 100644 --- a/fearless/Common/Services/ServiceCoordinator.swift +++ b/fearless/Common/Services/ServiceCoordinator.swift @@ -50,6 +50,7 @@ extension ServiceCoordinator: ServiceCoordinatorProtocol { func setup() { let chainRegistry = ChainRegistryFacade.sharedRegistry chainRegistry.syncUp() + chainRegistry.subscribeToChians() githubPhishingService.setup() accountInfoService.setup() @@ -148,4 +149,29 @@ extension ServiceCoordinator { walletAssetsObserver: walletAssetsObserver ) } + + private static func createPackageChainRegistry() -> SSFChainRegistry.ChainRegistryProtocol { + let chainSyncService = SSFChainRegistry.ChainSyncService( + chainsUrl: ApplicationConfig.shared.chainsSourceUrl, + operationQueue: OperationQueue(), + dataFetchFactory: SSFNetwork.NetworkOperationFactory() + ) + + let chainsTypesSyncService = SSFChainRegistry.ChainsTypesSyncService( + url: ApplicationConfig.shared.chainTypesSourceUrl, + dataOperationFactory: SSFNetwork.NetworkOperationFactory(), + operationQueue: OperationQueue() + ) + + let runtimeSyncService = SSFChainRegistry.RuntimeSyncService(dataOperationFactory: NetworkOperationFactory()) + + let chainRegistry = SSFChainRegistry.ChainRegistry( + runtimeProviderPool: SSFChainRegistry.RuntimeProviderPool(), + connectionPool: SSFChainRegistry.ConnectionPool(), + chainSyncService: chainSyncService, + chainsTypesSyncService: chainsTypesSyncService, + runtimeSyncService: runtimeSyncService + ) + return chainRegistry + } } diff --git a/fearless/Common/Services/SubscanQueryService/SubscanQueryService.swift b/fearless/Common/Services/SubscanQueryService/SubscanQueryService.swift index 37f042f6b6..67f07c9ad9 100644 --- a/fearless/Common/Services/SubscanQueryService/SubscanQueryService.swift +++ b/fearless/Common/Services/SubscanQueryService/SubscanQueryService.swift @@ -1,6 +1,7 @@ import Foundation import RobinHood import SSFUtils +import SSFModels final class SubscanQueryService: Longrunable { typealias ResultType = R diff --git a/fearless/Common/Storage/EntityToModel/AssetModelMapper.swift b/fearless/Common/Storage/EntityToModel/AssetModelMapper.swift deleted file mode 100644 index c019358eea..0000000000 --- a/fearless/Common/Storage/EntityToModel/AssetModelMapper.swift +++ /dev/null @@ -1,102 +0,0 @@ -import Foundation -import RobinHood -import CoreData -import SSFModels - -enum AssetModelMapperError: Error { - case requiredFieldsMissing -} - -final class AssetModelMapper: CoreDataMapperProtocol { - var entityIdentifierFieldName: String { "id" } - - func transform(entity: CDAsset) throws -> AssetModel { - guard - let id = entity.id, - let symbol = entity.symbol, - let name = entity.name - else { - throw AssetModelMapperError.requiredFieldsMissing - } - - let staking: RawStakingType? - if let entityStaking = entity.staking { - staking = RawStakingType(rawValue: entityStaking) - } else { - staking = nil - } - let purchaseProviders: [PurchaseProvider]? = entity.purchaseProviders?.compactMap { - PurchaseProvider(rawValue: $0) - } - - var priceProvider: PriceProvider? - if let typeRawValue = entity.priceProvider?.type, - let type = PriceProviderType(rawValue: typeRawValue), - let id = entity.priceProvider?.id { - let precision = entity.priceProvider?.precision ?? "" - priceProvider = PriceProvider(type: type, id: id, precision: Int16(precision)) - } - - return AssetModel( - id: id, - name: name, - symbol: symbol, - precision: UInt16(entity.precision), - icon: entity.icon, - price: entity.price as Decimal?, - fiatDayChange: entity.fiatDayChange as Decimal?, - currencyId: entity.currencyId, - existentialDeposit: entity.existentialDeposit, - color: entity.color, - isUtility: entity.isUtility, - isNative: entity.isNative, - staking: staking, - purchaseProviders: purchaseProviders, - type: createChainAssetModelType(from: entity.type), - ethereumType: createEthereumAssetType(from: entity.ethereumType), - priceProvider: priceProvider, - coingeckoPriceId: entity.priceId - ) - } - - func populate( - entity: CDAsset, - from model: AssetModel, - using context: NSManagedObjectContext - ) throws { - entity.id = model.id - entity.precision = Int16(model.precision) - entity.icon = model.icon - entity.priceId = model.coingeckoPriceId - entity.price = model.price as NSDecimalNumber? - entity.fiatDayChange = model.fiatDayChange as NSDecimalNumber? - entity.symbol = model.symbol - entity.existentialDeposit = model.existentialDeposit - entity.color = model.color - entity.ethereumType = model.ethereumType?.rawValue - entity.type = model.type?.rawValue - entity.ethereumType = model.ethereumType?.rawValue - - let priceProviderContext = CDPriceProvider(context: context) - priceProviderContext.type = model.priceProvider?.type.rawValue - priceProviderContext.id = model.priceProvider?.id - if let precision = model.priceProvider?.precision { - priceProviderContext.precision = "\(precision)" - } - entity.priceProvider = priceProviderContext - } - - private func createChainAssetModelType(from rawValue: String?) -> SubstrateAssetType? { - guard let rawValue = rawValue else { - return nil - } - return SubstrateAssetType(rawValue: rawValue) - } - - private func createEthereumAssetType(from rawValue: String?) -> EthereumAssetType? { - guard let rawValue = rawValue else { - return nil - } - return EthereumAssetType(rawValue: rawValue) - } -} diff --git a/fearless/Common/Storage/EntityToModel/ChainModelMapper.swift b/fearless/Common/Storage/EntityToModel/ChainModelMapper.swift index d919b3b029..0c03cef080 100644 --- a/fearless/Common/Storage/EntityToModel/ChainModelMapper.swift +++ b/fearless/Common/Storage/EntityToModel/ChainModelMapper.swift @@ -263,43 +263,62 @@ final class ChainModelMapper { crowdloans = ChainModel.ExternalResource(type: type, url: url) } + var pricing: ChainModel.BlockExplorer? + if let type = entity.pricingApiType, let url = entity.pricingApiUrl { + pricing = ChainModel.BlockExplorer(type: type, url: url) + } + let explorers = createExplorers(from: entity) if staking != nil || history != nil || crowdloans != nil || explorers != nil { - return ChainModel.ExternalApiSet(staking: staking, history: history, crowdloans: crowdloans, explorers: explorers) + return ChainModel.ExternalApiSet(staking: staking, history: history, crowdloans: crowdloans, explorers: explorers, pricing: pricing) } else { return nil } } private func createXcmConfig(from entity: CDChain) -> XcmChain? { - guard let versionRaw = entity.xcmConfig?.xcmVersion else { + guard + let versionRaw = entity.xcmConfig?.xcmVersion, + let availableAssets = entity.xcmConfig?.availableAssets, + let availableDestinations = entity.xcmConfig?.availableDestinations + else { return nil } let version = XcmCallFactoryVersion(rawValue: versionRaw) - let availableXcmAssets = entity.xcmConfig?.availableAssets?.allObjects as? [CDXcmAvailableAsset] ?? [] - let assets: [XcmAvailableAsset] = availableXcmAssets.compactMap { entity in - guard let id = entity.id, let symbol = entity.symbol else { + let assets: [XcmAvailableAsset] = availableAssets.compactMap { entity in + guard + let entity = entity as? CDXcmAvailableAsset, + let id = entity.id, + let symbol = entity.symbol + else { return nil } - return XcmAvailableAsset(id: id, symbol: symbol) + return XcmAvailableAsset(id: id, symbol: symbol, minAmount: nil) } - let availableXcmAssetDestinations = entity.xcmConfig?.availableDestinations?.allObjects as? [CDXcmAvailableDestination] ?? [] - let destinations: [XcmAvailableDestination] = availableXcmAssetDestinations.compactMap { - guard let chainId = $0.chainId else { + let destinations: [XcmAvailableDestination] = availableDestinations.compactMap { entity in + guard + let entity = entity as? CDXcmAvailableDestination, + let chainId = entity.chainId, + let assetsEntities = entity.assets + else { return nil } - let assetsEntities = $0.assets?.allObjects as? [CDXcmAvailableAsset] ?? [] + let assets: [XcmAvailableAsset] = assetsEntities.compactMap { entity in - guard let id = entity.id, let symbol = entity.symbol else { + guard + let entity = entity as? CDXcmAvailableAsset, + let id = entity.id, + let symbol = entity.symbol + else { return nil } - return XcmAvailableAsset(id: id, symbol: symbol) + return XcmAvailableAsset(id: id, symbol: symbol, minAmount: entity.minAmount) } return XcmAvailableDestination( chainId: chainId, - bridgeParachainId: $0.bridgeParachainId, + bridgeParachainId: entity.bridgeParachainId, assets: assets ) } @@ -364,6 +383,9 @@ final class ChainModelMapper { entity.crowdloansApiType = apis?.crowdloans?.type entity.crowdloansApiUrl = apis?.crowdloans?.url + + entity.pricingApiType = apis?.pricing?.type.rawValue + entity.pricingApiUrl = apis?.pricing?.url } private func createChainAssetModelType(from rawValue: String?) -> SubstrateAssetType? { @@ -394,7 +416,9 @@ final class ChainModelMapper { let configEntity = CDChainXcmConfig(context: context) configEntity.xcmVersion = xcmConfig.xcmVersion?.rawValue - configEntity.destWeightIsPrimitive = xcmConfig.destWeightIsPrimitive ?? false + if let destWeightIsPrimitive = xcmConfig.destWeightIsPrimitive { + configEntity.destWeightIsPrimitive = destWeightIsPrimitive + } let availableAssets = xcmConfig.availableAssets.map { let entity = CDXcmAvailableAsset(context: context) @@ -404,7 +428,7 @@ final class ChainModelMapper { } configEntity.availableAssets = Set(availableAssets) as NSSet - let destinationEntities = xcmConfig.availableDestinations.compactMap { + let destinationEntities = xcmConfig.availableDestinations.map { let destinationEntity = CDXcmAvailableDestination(context: context) destinationEntity.chainId = $0.chainId @@ -412,6 +436,7 @@ final class ChainModelMapper { let entity = CDXcmAvailableAsset(context: context) entity.id = $0.id entity.symbol = $0.symbol + entity.minAmount = $0.minAmount return entity } destinationEntity.assets = Set(availableAssets) as NSSet @@ -480,7 +505,8 @@ extension ChainModelMapper: CoreDataMapperProtocol { parentId: entity.parentId, paraId: entity.paraId, name: entity.name!, - xcm: xcm, nodes: Set(nodes), + xcm: xcm, + nodes: Set(nodes), addressPrefix: UInt16(bitPattern: entity.addressPrefix), types: types, icon: entity.icon, diff --git a/fearless/Common/Storage/EntityToModel/MetaAccountMapper.swift b/fearless/Common/Storage/EntityToModel/MetaAccountMapper.swift index a927087ae9..2f87233738 100644 --- a/fearless/Common/Storage/EntityToModel/MetaAccountMapper.swift +++ b/fearless/Common/Storage/EntityToModel/MetaAccountMapper.swift @@ -2,6 +2,7 @@ import Foundation import RobinHood import CoreData import SSFAccountManagmentStorage +import SSFModels final class MetaAccountMapper { var entityIdentifierFieldName: String { #keyPath(CDMetaAccount.metaId) } diff --git a/fearless/Common/Storage/Migration/AssetManagementMigrator.swift b/fearless/Common/Storage/Migration/AssetManagementMigrator.swift index 1b5f068765..74712284bd 100644 --- a/fearless/Common/Storage/Migration/AssetManagementMigrator.swift +++ b/fearless/Common/Storage/Migration/AssetManagementMigrator.swift @@ -158,7 +158,9 @@ enum AssetManagementMigratorAssembly { let walletRepository = AccountRepositoryFactory.createRepository() - let chainRepository = ChainRepositoryFactory().createRepository() + let chainRepository = ChainRepositoryFactory().createRepository( + for: NSPredicate.enabledCHain() + ) let chainAssetFetching = ChainAssetsFetching( chainRepository: AnyDataProviderRepository(chainRepository), operationQueue: OperationManagerFacade.sharedDefaultQueue diff --git a/fearless/Common/Storage/Migration/SubstrateStorage/SubstrateStorageMigrator.swift b/fearless/Common/Storage/Migration/SubstrateStorage/SubstrateStorageMigrator.swift index dcea27e78b..5b2b806c9f 100644 --- a/fearless/Common/Storage/Migration/SubstrateStorage/SubstrateStorageMigrator.swift +++ b/fearless/Common/Storage/Migration/SubstrateStorage/SubstrateStorageMigrator.swift @@ -204,7 +204,7 @@ extension SubstrateStorageMigrator: StorageMigrating { } func migrate(_ completion: @escaping () -> Void) { - DispatchQueue.global(qos: .userInitiated).async { [weak self] in + DispatchQueue.global(qos: .utility).async { [weak self] in self?.performMigration() DispatchQueue.main.async { diff --git a/fearless/Common/Storage/Migration/SubstrateStorage/SubstrateStorageVersion.swift b/fearless/Common/Storage/Migration/SubstrateStorage/SubstrateStorageVersion.swift index 6759f57f27..6398f184e6 100644 --- a/fearless/Common/Storage/Migration/SubstrateStorage/SubstrateStorageVersion.swift +++ b/fearless/Common/Storage/Migration/SubstrateStorage/SubstrateStorageVersion.swift @@ -7,6 +7,7 @@ enum SubstrateStorageVersion: String, CaseIterable { case version4 = "SubstrateDataModel_v4" case version5 = "SubstrateDataModel_v5" case version6 = "SubstrateDataModel_v6" + case version7 = "SubstrateDataModel_v7" static var current: SubstrateStorageVersion { guard let currentVersion = allCases.last else { @@ -29,6 +30,8 @@ enum SubstrateStorageVersion: String, CaseIterable { case .version5: return .version6 case .version6: + return .version7 + case .version7: return nil } } diff --git a/fearless/Common/Storage/Migration/UserStorage/StorageMigrator.swift b/fearless/Common/Storage/Migration/UserStorage/StorageMigrator.swift index b53addffb8..905543fcdc 100644 --- a/fearless/Common/Storage/Migration/UserStorage/StorageMigrator.swift +++ b/fearless/Common/Storage/Migration/UserStorage/StorageMigrator.swift @@ -242,7 +242,7 @@ extension UserStorageMigrator: StorageMigrating { } func migrate(_ completion: @escaping () -> Void) { - DispatchQueue.global(qos: .userInitiated).async { [weak self] in + DispatchQueue.global(qos: .utility).async { [weak self] in self?.performMigration() DispatchQueue.main.async { diff --git a/fearless/Common/Storage/SubstrateDataModel.xcdatamodeld/.xccurrentversion b/fearless/Common/Storage/SubstrateDataModel.xcdatamodeld/.xccurrentversion index a1b7e22810..708a49b1ec 100644 --- a/fearless/Common/Storage/SubstrateDataModel.xcdatamodeld/.xccurrentversion +++ b/fearless/Common/Storage/SubstrateDataModel.xcdatamodeld/.xccurrentversion @@ -3,6 +3,6 @@ _XCCurrentVersionName - SubstrateDataModel_v6.xcdatamodel + SubstrateDataModel_v7.xcdatamodel diff --git a/fearless/Common/Storage/SubstrateDataModel.xcdatamodeld/SubstrateDataModel_v5.xcdatamodel/contents b/fearless/Common/Storage/SubstrateDataModel.xcdatamodeld/SubstrateDataModel_v5.xcdatamodel/contents index 3bb8ef9fc5..792771c0fb 100644 --- a/fearless/Common/Storage/SubstrateDataModel.xcdatamodeld/SubstrateDataModel_v5.xcdatamodel/contents +++ b/fearless/Common/Storage/SubstrateDataModel.xcdatamodeld/SubstrateDataModel_v5.xcdatamodel/contents @@ -37,7 +37,10 @@ + + + @@ -132,10 +135,6 @@ - - - - diff --git a/fearless/Common/Storage/SubstrateDataModel.xcdatamodeld/SubstrateDataModel_v7.xcdatamodel/contents b/fearless/Common/Storage/SubstrateDataModel.xcdatamodeld/SubstrateDataModel_v7.xcdatamodel/contents new file mode 100644 index 0000000000..251f73f781 --- /dev/null +++ b/fearless/Common/Storage/SubstrateDataModel.xcdatamodeld/SubstrateDataModel_v7.xcdatamodel/contents @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/fearless/Common/Storage/SubstrateDataStorageFacade.swift b/fearless/Common/Storage/SubstrateDataStorageFacade.swift index 464bce9fb8..fe13c417b4 100644 --- a/fearless/Common/Storage/SubstrateDataStorageFacade.swift +++ b/fearless/Common/Storage/SubstrateDataStorageFacade.swift @@ -2,7 +2,7 @@ import RobinHood import CoreData enum SubstrateStorageParams { - static let modelVersion: SubstrateStorageVersion = .version6 + static let modelVersion: SubstrateStorageVersion = .version7 static let modelDirectory: String = "SubstrateDataModel.momd" static let databaseName = "SubstrateDataModel.sqlite" diff --git a/fearless/Common/Substrate/Calls/PolkaswapSwapCall.swift b/fearless/Common/Substrate/Calls/PolkaswapSwapCall.swift index a6b4e63a9b..25d2f667e3 100644 --- a/fearless/Common/Substrate/Calls/PolkaswapSwapCall.swift +++ b/fearless/Common/Substrate/Calls/PolkaswapSwapCall.swift @@ -1,6 +1,7 @@ import SSFUtils import BigInt import Foundation +import SSFModels class SwapAmount: Codable { var desired: BigUInt diff --git a/fearless/Common/Substrate/Types/AccountInfo.swift b/fearless/Common/Substrate/Types/AccountInfo.swift index f647fc2d46..c122bd0b0f 100644 --- a/fearless/Common/Substrate/Types/AccountInfo.swift +++ b/fearless/Common/Substrate/Types/AccountInfo.swift @@ -2,6 +2,7 @@ import Foundation import SSFUtils import RobinHood import BigInt +import SSFModels // MARK: - Normal diff --git a/fearless/Common/Substrate/Types/CrowdloanContributionMapper.swift b/fearless/Common/Substrate/Types/CrowdloanContributionMapper.swift index 259ac8ef5c..e26f07d203 100644 --- a/fearless/Common/Substrate/Types/CrowdloanContributionMapper.swift +++ b/fearless/Common/Substrate/Types/CrowdloanContributionMapper.swift @@ -1,6 +1,7 @@ import Foundation import SSFUtils import BigInt +import SSFModels struct CrowdloanContribution: Decodable { enum CodingKeys: String, CodingKey { diff --git a/fearless/Common/Substrate/Types/CrowdloanLastContribution.swift b/fearless/Common/Substrate/Types/CrowdloanLastContribution.swift index f67961b499..03b1367df3 100644 --- a/fearless/Common/Substrate/Types/CrowdloanLastContribution.swift +++ b/fearless/Common/Substrate/Types/CrowdloanLastContribution.swift @@ -1,5 +1,6 @@ import Foundation import SSFUtils +import SSFModels enum CrowdloanLastContribution: Equatable { static let neverField = "Never" diff --git a/fearless/Common/Substrate/Types/EventRecord.swift b/fearless/Common/Substrate/Types/EventRecord.swift index df3592aa32..c53997a663 100644 --- a/fearless/Common/Substrate/Types/EventRecord.swift +++ b/fearless/Common/Substrate/Types/EventRecord.swift @@ -1,5 +1,6 @@ import Foundation import SSFUtils +import SSFModels struct EventRecord: Decodable { enum CodingKeys: String, CodingKey { diff --git a/fearless/Common/Substrate/Types/StorageCodingPath.swift b/fearless/Common/Substrate/Types/StorageCodingPath.swift index f1db6bf43d..6dfdf6856f 100644 --- a/fearless/Common/Substrate/Types/StorageCodingPath.swift +++ b/fearless/Common/Substrate/Types/StorageCodingPath.swift @@ -101,7 +101,7 @@ enum StorageCodingPath: Equatable, CaseIterable, StorageCodingPathProtocol { case .bottomDelegations: return (moduleName: "ParachainStaking", itemName: "BottomDelegations") case .staked: - return (moduleName: "ParachainStaking", itemName: "Staked") + return (moduleName: "ParachainStaking", itemName: "Total") case .currentBlock: return (moduleName: "System", itemName: "Number") case .bondedPools: diff --git a/fearless/Common/Validation/Validators/ErrorConditionViolation.swift b/fearless/Common/Validation/Validators/ErrorConditionViolation.swift index 98b5f2e900..03f4297038 100644 --- a/fearless/Common/Validation/Validators/ErrorConditionViolation.swift +++ b/fearless/Common/Validation/Validators/ErrorConditionViolation.swift @@ -22,3 +22,26 @@ final class ErrorConditionViolation: DataValidating { return .error } } + +final class ErrorThrowingViolation: DataValidating { + private let preservesCondition: () -> String? + private let onError: (_ text: String) -> Void + + init( + onError: @escaping (_ text: String) -> Void, + preservesCondition: @escaping () -> String? + ) { + self.preservesCondition = preservesCondition + self.onError = onError + } + + func validate(notifying _: DataValidatingDelegate) -> DataValidationProblem? { + guard let textError = preservesCondition() else { + return nil + } + + onError(textError) + + return .error + } +} diff --git a/fearless/Common/View/AmountInputView/AmountInputViewV2.swift b/fearless/Common/View/AmountInputView/AmountInputViewV2.swift index 050566986e..30f52c68c6 100644 --- a/fearless/Common/View/AmountInputView/AmountInputViewV2.swift +++ b/fearless/Common/View/AmountInputView/AmountInputViewV2.swift @@ -20,7 +20,7 @@ final class AmountInputViewV2: UIView { view.fillColor = R.color.colorSemiBlack()! view.highlightedFillColor = R.color.colorSemiBlack()! - + view.shadowColor = .clear view.strokeColor = R.color.colorWhite8()! view.highlightedStrokeColor = R.color.colorWhite8()! view.strokeWidth = 0.5 @@ -112,6 +112,10 @@ final class AmountInputViewV2: UIView { // MARK: - Public methods + func set(highlighted: Bool, animated: Bool) { + triangularedBackgroundView.set(highlighted: highlighted, animated: animated) + } + func bind(viewModel: AssetBalanceViewModelProtocol) { iconView.isHidden = (viewModel.iconViewModel == nil) viewModel.iconViewModel?.cancel(on: iconView) diff --git a/fearless/Common/View/NavigationBar/Base/BaseTopBar.swift b/fearless/Common/View/NavigationBar/Base/BaseTopBar.swift index 144418b34b..2de9a78df1 100644 --- a/fearless/Common/View/NavigationBar/Base/BaseTopBar.swift +++ b/fearless/Common/View/NavigationBar/Base/BaseTopBar.swift @@ -1,7 +1,7 @@ import UIKit class BaseTopBar: UIView { - var leftStackView: UIStackView = UIFactory.default.createHorizontalStackView() + var leftStackView: UIStackView = UIFactory.default.createHorizontalStackView(spacing: 8) var centerStackView: UIStackView = UIFactory.default.createHorizontalStackView() var rightStackView: UIStackView = UIFactory.default.createHorizontalStackView() diff --git a/fearless/Common/View/PolkaswapDoubleSymbolView.swift b/fearless/Common/View/PolkaswapDoubleSymbolView.swift index bc0303540a..acfe207fa5 100644 --- a/fearless/Common/View/PolkaswapDoubleSymbolView.swift +++ b/fearless/Common/View/PolkaswapDoubleSymbolView.swift @@ -8,6 +8,11 @@ struct PolkaswapDoubleSymbolViewModel { let rightShadowColor: CGColor? } +enum PolkaswapDoubleSymbolViewMode { + case filled + case centered +} + final class PolkaswapDoubleSymbolView: UIView { private enum Constants { static let imageViewSize = CGSize(width: 41, height: 41) @@ -22,6 +27,16 @@ final class PolkaswapDoubleSymbolView: UIView { private let leftImageView = UIImageView() private let rightImageView = UIImageView() + private var imageSize: CGSize? + private var mode: PolkaswapDoubleSymbolViewMode = .centered + + init(imageSize: CGSize?, mode: PolkaswapDoubleSymbolViewMode) { + self.imageSize = imageSize + self.mode = mode + super.init(frame: .zero) + setupLayout() + } + override init(frame: CGRect) { super.init(frame: frame) setupLayout() @@ -39,14 +54,15 @@ final class PolkaswapDoubleSymbolView: UIView { } func bind(viewModel: PolkaswapDoubleSymbolViewModel) { + let size = imageSize ?? Constants.imageViewSize viewModel.rightViewModel?.loadImage( on: rightImageView, - targetSize: Constants.imageViewSize, + targetSize: size, animated: true ) viewModel.leftViewModel?.loadImage( on: leftImageView, - targetSize: Constants.imageViewSize, + targetSize: size, animated: true ) leftContainer.layer.shadowColor = viewModel.leftShadowColor @@ -54,19 +70,38 @@ final class PolkaswapDoubleSymbolView: UIView { } private func setupLayout() { - leftContainer.backgroundColor = R.color.colorBlack() - rightContainer.backgroundColor = R.color.colorBlack() + let size = imageSize ?? Constants.imageViewSize - leftContainer.addSubview(leftImageView) - leftImageView.snp.makeConstraints { make in - make.edges.equalToSuperview().inset(Constants.imageViewInset) - make.size.equalTo(Constants.imageViewSize) - } + addSubview(rightContainer) + addSubview(leftContainer) + leftContainer.addSubview(leftImageView) rightContainer.addSubview(rightImageView) - rightImageView.snp.makeConstraints { make in - make.edges.equalToSuperview().inset(Constants.imageViewInset) - make.size.equalTo(Constants.imageViewSize) + + switch mode { + case .filled: + leftImageView.snp.makeConstraints { make in + make.edges.equalToSuperview() + make.size.equalTo(size) + } + + rightImageView.snp.makeConstraints { make in + make.edges.equalToSuperview() + make.size.equalTo(size) + } + case .centered: + leftContainer.backgroundColor = R.color.colorBlack() + rightContainer.backgroundColor = R.color.colorBlack() + + leftImageView.snp.makeConstraints { make in + make.edges.equalToSuperview().inset(Constants.imageViewInset) + make.size.equalTo(size) + } + + rightImageView.snp.makeConstraints { make in + make.edges.equalToSuperview().inset(Constants.imageViewInset) + make.size.equalTo(size) + } } [leftContainer, rightContainer].forEach { view in @@ -74,9 +109,6 @@ final class PolkaswapDoubleSymbolView: UIView { view.layer.shadowOpacity = Constants.shadowOpacity } - addSubview(rightContainer) - addSubview(leftContainer) - leftContainer.snp.makeConstraints { make in make.top.leading.bottom.equalToSuperview() make.trailing.equalTo(rightContainer.snp.leading).offset(Constants.imagesInset) diff --git a/fearless/Common/View/SearchTriangularedView.swift b/fearless/Common/View/SearchTriangularedView.swift index b3ff7553fa..d6e6cb4da9 100644 --- a/fearless/Common/View/SearchTriangularedView.swift +++ b/fearless/Common/View/SearchTriangularedView.swift @@ -11,6 +11,8 @@ final class SearchTriangularedView: UIView { static let pasteButtonSize: CGFloat = 76 } + var isValid = false + var onPasteTapped: (() -> Void)? private let withPasteButton: Bool diff --git a/fearless/Common/View/ShimmeredLabel.swift b/fearless/Common/View/ShimmeredLabel.swift index 6a4328a5d9..0c28dcdfbd 100644 --- a/fearless/Common/View/ShimmeredLabel.swift +++ b/fearless/Common/View/ShimmeredLabel.swift @@ -32,12 +32,25 @@ enum ShimmeredLabelState: Hashable { } } -final class ShimmeredLabel: UILabel, ShimmeredProtocol { +final class ShimmeredLabel: SkeletonLabel, ShimmeredProtocol { private var state: ShimmeredLabelState? // MARK: - Public methods - func apply(state: ShimmeredLabelState) { + init() { + super.init(skeletonSize: .zero) + } + + override init(skeletonSize: CGSize) { + super.init(skeletonSize: skeletonSize) + } + + func apply(state: ShimmeredLabelState?) { + guard let state else { + updateTextWithLoading(nil) + return + } + self.state = state switch state { case .stopShimmering: diff --git a/fearless/Common/View/ShimmeredProtocol.swift b/fearless/Common/View/ShimmeredProtocol.swift index b434ac4ad9..ae6d7a6798 100644 --- a/fearless/Common/View/ShimmeredProtocol.swift +++ b/fearless/Common/View/ShimmeredProtocol.swift @@ -52,4 +52,8 @@ extension ShimmeredProtocol { layer.mask = nil layer.removeAnimation(forKey: Constants.animationKey) } + + func startSkeletonAnimation() {} + + func stopSkeletonAnimation() {} } diff --git a/fearless/Common/View/SkeletonLabel.swift b/fearless/Common/View/SkeletonLabel.swift new file mode 100644 index 0000000000..af6672818d --- /dev/null +++ b/fearless/Common/View/SkeletonLabel.swift @@ -0,0 +1,39 @@ +import UIKit +import SoraUI + +class SkeletonLabel: UILabel, SkeletonLoadableView { + var container: UIView { + self + } + + var skeletonSize: CGSize + var skeletonView: SkrullableView? + + init(skeletonSize: CGSize) { + self.skeletonSize = skeletonSize + super.init(frame: .zero) + } + + @available(*, unavailable) + required init?(coder _: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func updateTextWithLoading(_ text: String?) { + self.text = text + + if text != nil { + stopSkeletonAnimation() + } else { + startSkeletonAnimation() + } + } + + override func layoutSubviews() { + super.layoutSubviews() + + if text == nil { + updateSkeletonLayout() + } + } +} diff --git a/fearless/Common/View/SkeletonLoadableView.swift b/fearless/Common/View/SkeletonLoadableView.swift new file mode 100644 index 0000000000..8012c18672 --- /dev/null +++ b/fearless/Common/View/SkeletonLoadableView.swift @@ -0,0 +1,52 @@ +import UIKit +import SoraUI + +protocol SkeletonLoadableView: UIView { + var container: UIView { get } + var skeletonSize: CGSize { get set } + var skeletonView: SkrullableView? { get set } + + func startSkeletonAnimation() + func stopSkeletonAnimation() + func updateSkeletonLayout() +} + +extension SkeletonLoadableView { + func startSkeletonAnimation() { + guard skeletonView == nil else { + return + } + let skeletonView = Skrull( + size: skeletonSize, + decorations: [], + skeletons: [ + SingleSkeleton.createRow(position: CGPoint(x: 0, y: 0), size: skeletonSize) + ] + ) + .fillSkeletonStart(R.color.colorSkeletonStart()!) + .fillSkeletonEnd(color: R.color.colorSkeletonEnd()!) + .build() + + skeletonView.frame = CGRect(origin: CGPoint(x: -skeletonSize.width, y: skeletonSize.height / 2), size: skeletonSize) + skeletonView.autoresizingMask = [] + container.addSubview(skeletonView) + + self.skeletonView = skeletonView + + skeletonView.startSkrulling() + } + + func stopSkeletonAnimation() { + skeletonView?.stopSkrulling() + skeletonView?.removeFromSuperview() + skeletonView = nil + } + + func updateSkeletonLayout() { + guard let skeletonView = skeletonView else { + return + } + + skeletonView.frame = CGRect(origin: CGPoint(x: -skeletonSize.width / 2, y: skeletonSize.height / 2), size: skeletonSize) + } +} diff --git a/fearless/Common/View/Stacks.swift b/fearless/Common/View/Stacks.swift index 7237b9f34a..20d02c760d 100644 --- a/fearless/Common/View/Stacks.swift +++ b/fearless/Common/View/Stacks.swift @@ -199,16 +199,16 @@ private final class Spacer: UIView { func resetColors() { colors = [.systemRed, .systemBlue, .systemGreen, .systemOrange, .systemTeal, .systemPink, .systemPurple, .systemIndigo].reversed() } - func addBorder(view: UIView) { + func addBorder(setupView: UIView) { if colors.isEmpty { resetColors() } - view.border(colors.removeFirst(), width: 1) - for subview in view.subviews { - addBorder(view: subview) + setupView.border(colors.removeFirst(), width: 1) + for subview in setupView.subviews { + addBorder(setupView: subview) } } - addBorder(view: self) + addBorder(setupView: self) } @discardableResult func border(_ color: UIColor, width: CGFloat) -> UIView { diff --git a/fearless/Common/View/TokenPairIconsView.swift b/fearless/Common/View/TokenPairIconsView.swift new file mode 100644 index 0000000000..e3ff3be76f --- /dev/null +++ b/fearless/Common/View/TokenPairIconsView.swift @@ -0,0 +1,51 @@ +import UIKit + +class TokenPairIconsView: UIView { + let firstTokenIconView = UIImageView() + let secondTokenIconView = UIImageView() + + override init(frame: CGRect) { + super.init(frame: frame) + + drawSubviews() + setupLayout() + } + + override func layoutSubviews() { + super.layoutSubviews() + + setupLayout() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + + drawSubviews() + setupLayout() + } + + func bind(viewModel: TokenPairsIconViewModel) { + let iconSize = CGSize(width: frame.size.height / 1.5, height: frame.size.height / 1.5) + + viewModel.firstTokenIconViewModel?.loadImage(on: firstTokenIconView, targetSize: iconSize, animated: false) + viewModel.secondTokenIconViewModel?.loadImage(on: secondTokenIconView, targetSize: iconSize, animated: false) + } + + private func drawSubviews() { + addSubview(firstTokenIconView) + addSubview(secondTokenIconView) + } + + private func setupLayout() { + let iconSize = frame.size.height / 1.5 + let horizontalOffset: CGFloat = -(iconSize / 3.0) + let verticalOffset: CGFloat = -(iconSize / 2.0) + firstTokenIconView.frame = CGRect(x: 0.0, y: 0.0, width: iconSize, height: iconSize) + secondTokenIconView.frame = CGRect( + x: CGRectGetMaxX(firstTokenIconView.frame) + horizontalOffset, + y: CGRectGetMaxY(firstTokenIconView.frame) + verticalOffset, + width: iconSize, + height: iconSize + ) + } +} diff --git a/fearless/Common/View/UIFactory.swift b/fearless/Common/View/UIFactory.swift index 7e69d8ad40..5289e5301d 100644 --- a/fearless/Common/View/UIFactory.swift +++ b/fearless/Common/View/UIFactory.swift @@ -104,6 +104,11 @@ protocol UIFactoryProtocol { ) -> UIToolbar func createDisabledButton() -> TriangularedButton func createRoundedButton() -> UIButton + func createWarningView(title: String, text: String) -> UIView + func createDoneAccessoryView( + for delegate: AmountInputAccessoryViewDelegate?, + locale: Locale + ) -> UIToolbar } extension UIFactoryProtocol { @@ -370,6 +375,43 @@ final class UIFactory: UIFactoryProtocol { ) } + func createDoneAccessoryView( + for delegate: AmountInputAccessoryViewDelegate?, + locale: Locale + ) -> UIToolbar { + let frame = CGRect( + x: 0.0, + y: 0.0, + width: UIScreen.main.bounds.width, + height: UIConstants.accessoryBarHeight + ) + + let toolBar = AmountInputAccessoryView(frame: frame) + toolBar.actionDelegate = delegate + + let doneTitle = R.string.localizable.commonDone(preferredLanguages: locale.rLanguages) + let doneAction = ViewSelectorAction( + title: doneTitle, + selector: #selector(toolBar.actionSelectDone) + ) + + let spacing: CGFloat + + if toolBar.isAdaptiveWidthDecreased { + spacing = UIConstants.accessoryItemsSpacing * toolBar.designScaleRatio.width + } else { + spacing = UIConstants.accessoryItemsSpacing + } + + return createActionsAccessoryView( + for: toolBar, + actions: [], + doneAction: doneAction, + target: toolBar, + spacing: spacing + ) + } + func createCommonInputView() -> CommonInputView { let inputView = CommonInputView() inputView.defaultSetup() @@ -733,4 +775,33 @@ final class UIFactory: UIFactoryProtocol { button.layer.cornerRadius = 12 return button } + + func createWarningView(title _: String, text _: String) -> UIView { + let iconView = UIImageView(image: R.image.iconWarning()) + iconView.snp.makeConstraints { make in + make.size.equalTo(16) + } + + let hStack = UIFactory.default.createHorizontalStackView(spacing: 8) + hStack.alignment = .top + hStack.distribution = .fillProportionally + + let vStack = UIFactory.default.createVerticalStackView(spacing: 4) + + hStack.addArrangedSubview(iconView) + hStack.addArrangedSubview(vStack) + + let titleLabel = UILabel() + titleLabel.textColor = R.color.colorOrange() + titleLabel.font = .h6Title + + let textLabel = UILabel() + textLabel.textColor = R.color.colorWhite50() + textLabel.font = .p3Paragraph + + vStack.addArrangedSubview(titleLabel) + vStack.addArrangedSubview(textLabel) + + return hStack + } } diff --git a/fearless/Common/View/ViewModel/DetailsTriangularedViewModel.swift b/fearless/Common/View/ViewModel/DetailsTriangularedViewModel.swift index 37cba901a1..c324ec2611 100644 --- a/fearless/Common/View/ViewModel/DetailsTriangularedViewModel.swift +++ b/fearless/Common/View/ViewModel/DetailsTriangularedViewModel.swift @@ -9,5 +9,5 @@ struct DetailsTriangularedViewModel { struct DetailsTriangularedAttributedViewModel { let icon: UIImage - let title: NSAttributedString + let title: NSAttributedString? } diff --git a/fearless/Common/View/WarningView.swift b/fearless/Common/View/WarningView.swift new file mode 100644 index 0000000000..c98435af47 --- /dev/null +++ b/fearless/Common/View/WarningView.swift @@ -0,0 +1,78 @@ +import UIKit + +class WarningView: UIView { + let backgroundView: TriangularedView = { + let view = TriangularedView() + view.fillColor = R.color.colorSemiBlack()! + view.highlightedFillColor = R.color.colorSemiBlack()! + view.strokeColor = R.color.colorWhite16()! + view.highlightedStrokeColor = R.color.colorWhite16()! + view.strokeWidth = 0.5 + view.shadowOpacity = 0.0 + + return view + }() + + let iconView = UIImageView(image: R.image.iconWarning()) + + let hStack: UIStackView = { + let hStack = UIFactory.default.createHorizontalStackView(spacing: 8) + hStack.alignment = .center + hStack.distribution = .fillProportionally + return hStack + }() + + let vStack = UIFactory.default.createVerticalStackView(spacing: 4) + + let titleLabel: UILabel = { + let titleLabel = UILabel() + titleLabel.textColor = R.color.colorOrange() + titleLabel.font = .h6Title + return titleLabel + }() + + let textLabel: UILabel = { + let textLabel = UILabel() + textLabel.textColor = R.color.colorWhite50() + textLabel.font = .p3Paragraph + textLabel.numberOfLines = 0 + return textLabel + }() + + override init(frame: CGRect) { + super.init(frame: frame) + + drawSubviews() + setupConstraints() + } + + @available(*, unavailable) + required init?(coder _: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func drawSubviews() { + addSubview(backgroundView) + backgroundView.addSubview(hStack) + + hStack.addArrangedSubview(iconView) + hStack.addArrangedSubview(vStack) + + vStack.addArrangedSubview(titleLabel) + vStack.addArrangedSubview(textLabel) + } + + private func setupConstraints() { + backgroundView.snp.makeConstraints { make in + make.edges.equalToSuperview() + } + + hStack.snp.makeConstraints { make in + make.edges.equalToSuperview().inset(12) + } + + iconView.snp.makeConstraints { make in + make.size.equalTo(16) + } + } +} diff --git a/fearless/Common/ViewController/ModalPicker/ViewModel/TitleSwitchTableViewCellModelFactory.swift b/fearless/Common/ViewController/ModalPicker/ViewModel/TitleSwitchTableViewCellModelFactory.swift index 4c58c79b74..fcd39725cf 100644 --- a/fearless/Common/ViewController/ModalPicker/ViewModel/TitleSwitchTableViewCellModelFactory.swift +++ b/fearless/Common/ViewController/ModalPicker/ViewModel/TitleSwitchTableViewCellModelFactory.swift @@ -1,4 +1,5 @@ import Foundation +import SSFModels protocol TitleSwitchTableViewCellModelFactoryProtocol { func createSortings( diff --git a/fearless/Common/ViewController/ModalPicker/ViewModel/TitleSwitchViewModel.swift b/fearless/Common/ViewController/ModalPicker/ViewModel/TitleSwitchViewModel.swift index c5ce2b785e..1eb2411194 100644 --- a/fearless/Common/ViewController/ModalPicker/ViewModel/TitleSwitchViewModel.swift +++ b/fearless/Common/ViewController/ModalPicker/ViewModel/TitleSwitchViewModel.swift @@ -1,5 +1,6 @@ import Foundation import UIKit +import SSFModels class TitleSwitchTableViewCellModel { let icon: UIImage? diff --git a/fearless/Common/ViewModel/TokenPairsIconViewModel.swift b/fearless/Common/ViewModel/TokenPairsIconViewModel.swift new file mode 100644 index 0000000000..f1e6aa7fe1 --- /dev/null +++ b/fearless/Common/ViewModel/TokenPairsIconViewModel.swift @@ -0,0 +1,6 @@ +import Foundation + +struct TokenPairsIconViewModel { + let firstTokenIconViewModel: RemoteImageViewModel? + let secondTokenIconViewModel: RemoteImageViewModel? +} diff --git a/fearless/Common/ViewModelFactory/ChainAssetListBuilder.swift b/fearless/Common/ViewModelFactory/ChainAssetListBuilder.swift index 132e78122b..85713d993f 100644 --- a/fearless/Common/ViewModelFactory/ChainAssetListBuilder.swift +++ b/fearless/Common/ViewModelFactory/ChainAssetListBuilder.swift @@ -6,6 +6,12 @@ protocol ChainAssetListBuilder { var assetBalanceFormatterFactory: AssetBalanceFormatterFactoryProtocol { get } } +extension ChainAssetListBuilder { + var assetBalanceFormatterFactory: AssetBalanceFormatterFactoryProtocol { + AssetBalanceFormatterFactory() + } +} + struct AssetChainAssets { let chainAssets: [ChainAsset] let mainChainAsset: ChainAsset @@ -291,10 +297,10 @@ extension ChainAssetListBuilder { pricesData: [PriceData], wallet: MetaAccountModel ) -> [AssetChainAssets] { - let assetNamesSet: Set = Set(chainAssets.map { $0.asset.symbolUppercased }) + let assetNamesSet: Set = Set(chainAssets.map { $0.asset.normalizedSymbol() }) return assetNamesSet.compactMap { name in - let assetChainAssets = chainAssets.filter { $0.asset.symbolUppercased == name && wallet.fetch(for: $0.chain.accountRequest()) != nil } + let assetChainAssets = chainAssets.filter { $0.asset.normalizedSymbol() == name && wallet.fetch(for: $0.chain.accountRequest()) != nil } let chainAssetsSorted = assetChainAssets.sorted(by: { ca1, ca2 in sortChainAssets(ca1: ca1, ca2: ca2) }) @@ -344,6 +350,14 @@ extension ChainAssetListBuilder { guard wallet.assetsVisibility.isNotEmpty else { return defaultByPopular(chainAssets: chainAssets) } + let enabled = enabled(chainAssets: chainAssets, for: wallet) + return enabled + } + + func enabled( + chainAssets: [ChainAsset], + for wallet: MetaAccountModel + ) -> [ChainAsset] { let enabledAssetIds: [String] = wallet.assetsVisibility .filter { !$0.hidden } .map { $0.assetId } diff --git a/fearless/CoreLayer/CoreComponents/Network/Config/RequestConfig.swift b/fearless/CoreLayer/CoreComponents/Network/Config/RequestConfig.swift index 84d15c6405..a56870b74e 100644 --- a/fearless/CoreLayer/CoreComponents/Network/Config/RequestConfig.swift +++ b/fearless/CoreLayer/CoreComponents/Network/Config/RequestConfig.swift @@ -7,6 +7,7 @@ class RequestConfig { var queryItems: [URLQueryItem]? var headers: [HTTPHeader]? var body: Data? + var timeout: TimeInterval? var requestType: NetworkRequestType = .plain var signingType: RequestSigningType = .none @@ -19,7 +20,8 @@ class RequestConfig { endpoint: String?, queryItems: [URLQueryItem]? = nil, headers: [HTTPHeader]?, - body: Data? + body: Data?, + timeout: TimeInterval? = nil ) { self.baseURL = baseURL self.method = method @@ -27,5 +29,6 @@ class RequestConfig { self.queryItems = queryItems self.headers = headers self.body = body + self.timeout = timeout } } diff --git a/fearless/CoreLayer/CoreComponents/Network/NetworkClient/RESTNetworkClient.swift b/fearless/CoreLayer/CoreComponents/Network/NetworkClient/RESTNetworkClient.swift index 878d8c63d9..6c24bcf819 100644 --- a/fearless/CoreLayer/CoreComponents/Network/NetworkClient/RESTNetworkClient.swift +++ b/fearless/CoreLayer/CoreComponents/Network/NetworkClient/RESTNetworkClient.swift @@ -8,7 +8,6 @@ final class RESTNetworkClient { } private func processDataResponse( - urlRequest _: URLRequest, data: Data, response: URLResponse ) -> Result { @@ -44,6 +43,6 @@ extension RESTNetworkClient: NetworkClient { return .failure(.init(errorCode: error.code)) } - return processDataResponse(urlRequest: request, data: data, response: response) + return processDataResponse(data: data, response: response) } } diff --git a/fearless/CoreLayer/CoreComponents/Network/RequestConfigurators/RESTRequestConfigurator.swift b/fearless/CoreLayer/CoreComponents/Network/RequestConfigurators/RESTRequestConfigurator.swift index 7b8597b1d3..a7dc33f0fb 100644 --- a/fearless/CoreLayer/CoreComponents/Network/RequestConfigurators/RESTRequestConfigurator.swift +++ b/fearless/CoreLayer/CoreComponents/Network/RequestConfigurators/RESTRequestConfigurator.swift @@ -33,6 +33,10 @@ extension RESTRequestConfigurator: RequestConfigurator { urlRequest.httpMethod = config.method.rawValue urlRequest.httpBody = config.body + if let timeout = config.timeout { + urlRequest.timeoutInterval = timeout + } + config.headers?.forEach { urlRequest.addValue($0.value, forHTTPHeaderField: $0.field) } diff --git a/fearless/CoreLayer/CoreComponents/QR/QRParser.swift b/fearless/CoreLayer/CoreComponents/QR/QRParser.swift deleted file mode 100644 index 536a0fbfa1..0000000000 --- a/fearless/CoreLayer/CoreComponents/QR/QRParser.swift +++ /dev/null @@ -1,32 +0,0 @@ -import Foundation -import SSFQRService - -protocol QRParser { - func extractAddress(from code: String) throws -> String -} - -final class SubstrateQRParser: QRParser { - private let prefix: String = SubstrateQRConstants.prefix - private let separator: String = SubstrateQRConstants.fieldsSeparator - - func extractAddress(from code: String) throws -> String { - let fields = code - .components(separatedBy: separator) - - if fields.count == 1 { - return code - } - - guard fields.count >= 3, fields.count <= 4 else { - throw QRDecoderError.unexpectedNumberOfFields - } - - guard fields[0] == prefix else { - throw QRDecoderError.undefinedPrefix - } - - let address = fields[1] - - return address - } -} diff --git a/fearless/CoreLayer/CoreComponents/Storage/RequestFactory/AsyncStorageRequestFactoryDefault.swift b/fearless/CoreLayer/CoreComponents/Storage/RequestFactory/AsyncStorageRequestFactoryDefault.swift index 9dc1092b5e..883e5c0335 100644 --- a/fearless/CoreLayer/CoreComponents/Storage/RequestFactory/AsyncStorageRequestFactoryDefault.swift +++ b/fearless/CoreLayer/CoreComponents/Storage/RequestFactory/AsyncStorageRequestFactoryDefault.swift @@ -23,7 +23,7 @@ final actor AsyncStorageRequestDefault: AsyncStorageRequestFactory { storageKeyFactory: storageKeyFactory, keyParams: keyParams ) - let keys = try keysWorker.performEncoding() + let keys = try await keysWorker.performEncoding() let queryItems: [StorageResponse] = try await queryItems( engine: engine, @@ -105,7 +105,7 @@ final actor AsyncStorageRequestDefault: AsyncStorageRequestFactory { storageKeyFactory: storageKeyFactory, keyParams: keyParams ) - let keys = try keysWorker.performEncoding() + let keys = try await keysWorker.performEncoding() let queryItems: [StorageResponse] = try await queryItems( engine: engine, @@ -167,7 +167,7 @@ final actor AsyncStorageRequestDefault: AsyncStorageRequestFactory { storageKeyFactory: storageKeyFactory, keyParams: keyParams ) - let keys = try keysWorker.performEncoding() + let keys = try await keysWorker.performEncoding() return try await queryItemsByPrefix( engine: engine, diff --git a/fearless/CoreLayer/CoreComponents/Storage/StorageFactoryWorkers/MapKeyEncodingWorker.swift b/fearless/CoreLayer/CoreComponents/Storage/StorageFactoryWorkers/MapKeyEncodingWorker.swift index 1dd91e53a8..e081ca256e 100644 --- a/fearless/CoreLayer/CoreComponents/Storage/StorageFactoryWorkers/MapKeyEncodingWorker.swift +++ b/fearless/CoreLayer/CoreComponents/Storage/StorageFactoryWorkers/MapKeyEncodingWorker.swift @@ -3,7 +3,7 @@ import SSFRuntimeCodingService import SSFModels import SSFUtils -final class MapKeyEncodingWorker { +actor MapKeyEncodingWorker { private let keyParams: [any Encodable] private let codingFactory: RuntimeCoderFactoryProtocol private let path: StorageCodingPath diff --git a/fearless/CoreLayer/OperationFactory/BlockExplorer/History/Main/ReefSubsquidHistoryOperationFactory.swift b/fearless/CoreLayer/OperationFactory/BlockExplorer/History/Main/ReefSubsquidHistoryOperationFactory.swift index 84f724434c..4672dee7fe 100644 --- a/fearless/CoreLayer/OperationFactory/BlockExplorer/History/Main/ReefSubsquidHistoryOperationFactory.swift +++ b/fearless/CoreLayer/OperationFactory/BlockExplorer/History/Main/ReefSubsquidHistoryOperationFactory.swift @@ -130,6 +130,7 @@ final class ReefSubsquidHistoryOperationFactory { id } signedData + blockHash } } pageInfo { diff --git a/fearless/CoreLayer/OperationFactory/BlockExplorer/History/Staking/ParachainSubqueryHistoryOperationFactory.swift b/fearless/CoreLayer/OperationFactory/BlockExplorer/History/Staking/ParachainSubqueryHistoryOperationFactory.swift index 768144ef93..142689607b 100644 --- a/fearless/CoreLayer/OperationFactory/BlockExplorer/History/Staking/ParachainSubqueryHistoryOperationFactory.swift +++ b/fearless/CoreLayer/OperationFactory/BlockExplorer/History/Staking/ParachainSubqueryHistoryOperationFactory.swift @@ -1,6 +1,7 @@ import Foundation import RobinHood import SSFUtils +import SSFModels enum SubqueryHistoryOperationFactoryError: Error { case urlMissing diff --git a/fearless/CoreLayer/OperationFactory/BlockExplorer/History/Staking/ParachainSubsquidHistoryOperationFactory.swift b/fearless/CoreLayer/OperationFactory/BlockExplorer/History/Staking/ParachainSubsquidHistoryOperationFactory.swift index 44b8d018e0..5610d4a805 100644 --- a/fearless/CoreLayer/OperationFactory/BlockExplorer/History/Staking/ParachainSubsquidHistoryOperationFactory.swift +++ b/fearless/CoreLayer/OperationFactory/BlockExplorer/History/Staking/ParachainSubsquidHistoryOperationFactory.swift @@ -1,6 +1,7 @@ import Foundation import RobinHood import SSFUtils +import SSFModels enum SubsquidHistoryOperationFactoryError: Error { case urlMissing diff --git a/fearless/CoreLayer/OperationFactory/BlockExplorer/Rewards/SubqueryRewardOperationFactory.swift b/fearless/CoreLayer/OperationFactory/BlockExplorer/Rewards/SubqueryRewardOperationFactory.swift index df2dd22369..188cbca4e4 100644 --- a/fearless/CoreLayer/OperationFactory/BlockExplorer/Rewards/SubqueryRewardOperationFactory.swift +++ b/fearless/CoreLayer/OperationFactory/BlockExplorer/Rewards/SubqueryRewardOperationFactory.swift @@ -1,6 +1,7 @@ import Foundation import RobinHood import SSFUtils +import SSFModels enum SubqueryRewardOperationFactoryError: Error { case urlMissing diff --git a/fearless/CoreLayer/OperationFactory/BlockExplorer/Rewards/SubsquidRewardOperationFactory.swift b/fearless/CoreLayer/OperationFactory/BlockExplorer/Rewards/SubsquidRewardOperationFactory.swift index 4806a9e56d..a620884abe 100644 --- a/fearless/CoreLayer/OperationFactory/BlockExplorer/Rewards/SubsquidRewardOperationFactory.swift +++ b/fearless/CoreLayer/OperationFactory/BlockExplorer/Rewards/SubsquidRewardOperationFactory.swift @@ -2,6 +2,7 @@ import Foundation import RobinHood import SSFUtils import SoraFoundation +import SSFModels enum ArrosquidRewardOperationFactoryError: Error { case urlMissing diff --git a/fearless/CoreLayer/StorageRequests/StakingPallet/StakingErasRewardPointsRequest.swift b/fearless/CoreLayer/StorageRequests/StakingPallet/StakingErasRewardPointsRequest.swift index 31e7616c4d..9606ab5455 100644 --- a/fearless/CoreLayer/StorageRequests/StakingPallet/StakingErasRewardPointsRequest.swift +++ b/fearless/CoreLayer/StorageRequests/StakingPallet/StakingErasRewardPointsRequest.swift @@ -1,12 +1,17 @@ import Foundation import SSFModels +import SSFStorageQueryKit -struct StakingErasRewardPointsRequest: PrefixRequest { - var storagePath: StorageCodingPath { - .erasRewardPoints +struct StakingErasRewardPointsRequest: SSFStorageQueryKit.PrefixRequest { + var keyType: SSFStorageQueryKit.MapKeyType { + .u32 } - var keyType: MapKeyType { - .u32 + var parametersType: SSFStorageQueryKit.PrefixStorageRequestParametersType { + .simple + } + + var storagePath: any SSFModels.StorageCodingPathProtocol { + StorageCodingPath.erasRewardPoints } } diff --git a/fearless/CoreLayer/StorageRequests/StakingPallet/StakingErasTotalStakeRequest.swift b/fearless/CoreLayer/StorageRequests/StakingPallet/StakingErasTotalStakeRequest.swift index 8c3ee019df..71ab2525d2 100644 --- a/fearless/CoreLayer/StorageRequests/StakingPallet/StakingErasTotalStakeRequest.swift +++ b/fearless/CoreLayer/StorageRequests/StakingPallet/StakingErasTotalStakeRequest.swift @@ -1,12 +1,17 @@ import Foundation import SSFModels +import SSFStorageQueryKit -struct StakingErasTotalStakeRequest: PrefixRequest { - var storagePath: StorageCodingPath { - .erasTotalStake +struct StakingErasTotalStakeRequest: SSFStorageQueryKit.PrefixRequest { + var storagePath: any SSFModels.StorageCodingPathProtocol { + StorageCodingPath.erasTotalStake } - var keyType: MapKeyType { + var keyType: SSFStorageQueryKit.MapKeyType { .u32 } + + var parametersType: SSFStorageQueryKit.PrefixStorageRequestParametersType { + .simple + } } diff --git a/fearless/CoreLayer/StorageRequests/StakingPallet/StakingErasValidatorRewardRequest.swift b/fearless/CoreLayer/StorageRequests/StakingPallet/StakingErasValidatorRewardRequest.swift index 556c5bc21d..a6cec8fd2e 100644 --- a/fearless/CoreLayer/StorageRequests/StakingPallet/StakingErasValidatorRewardRequest.swift +++ b/fearless/CoreLayer/StorageRequests/StakingPallet/StakingErasValidatorRewardRequest.swift @@ -1,12 +1,17 @@ import Foundation import SSFModels +import SSFStorageQueryKit -struct StakingErasValidatorRewardRequest: PrefixRequest { - var storagePath: StorageCodingPath { - .erasValidatorReward +struct StakingErasValidatorRewardRequest: SSFStorageQueryKit.PrefixRequest { + var keyType: SSFStorageQueryKit.MapKeyType { + .u32 } - var keyType: MapKeyType { - .u32 + var parametersType: SSFStorageQueryKit.PrefixStorageRequestParametersType { + .simple + } + + var storagePath: any SSFModels.StorageCodingPathProtocol { + StorageCodingPath.erasValidatorReward } } diff --git a/fearless/Modules/AllDone/AllDonePresenter.swift b/fearless/Modules/AllDone/AllDonePresenter.swift index b11a627899..6afa3c5a2b 100644 --- a/fearless/Modules/AllDone/AllDonePresenter.swift +++ b/fearless/Modules/AllDone/AllDonePresenter.swift @@ -65,9 +65,7 @@ final class AllDonePresenter { view?.didReceive(explorer: nil) return } - let explorer = chainAsset?.chain.externalApi?.explorers?.first(where: { - $0.type == .subscan || $0.type == .etherscan || $0.type == .reef - }) + let explorer = chainAsset?.chain.externalApi?.explorers?.first view?.didReceive(explorer: explorer) self.explorer = explorer } diff --git a/fearless/Modules/AssetManagement/AssetManagementAssembly.swift b/fearless/Modules/AssetManagement/AssetManagementAssembly.swift index d78a1a455f..cf1ed2c2c5 100644 --- a/fearless/Modules/AssetManagement/AssetManagementAssembly.swift +++ b/fearless/Modules/AssetManagement/AssetManagementAssembly.swift @@ -13,7 +13,9 @@ final class AssetManagementAssembly { let localizationManager = LocalizationManager.shared let priceLocalSubscriber = PriceLocalStorageSubscriberImpl.shared - let chainRepository = ChainRepositoryFactory().createRepository() + let chainRepository = ChainRepositoryFactory().createRepository( + for: NSPredicate.enabledCHain() + ) let chainAssetFetching = ChainAssetsFetching( chainRepository: AnyDataProviderRepository(chainRepository), operationQueue: OperationManagerFacade.sharedDefaultQueue @@ -63,12 +65,22 @@ final class AssetManagementAssembly { storagePerformer: storagePerformer ) + let walletAssetsObserver = WalletAssetsObserverImpl( + wallet: wallet, + chainRegistry: chainRegistry, + accountInfoRemote: accountInfoRemote, + eventCenter: EventCenter.shared, + logger: Logger.shared, + userDefaultsStorage: SettingsManager.shared + ) + let interactor = AssetManagementInteractor( chainAssetFetching: chainAssetFetching, priceLocalSubscriber: priceLocalSubscriber, accountInfoFetchingProvider: accountInfoFetchingProvider, eventCenter: EventCenter.shared, - accountInfoRemoteService: accountInfoRemote + accountInfoRemoteService: accountInfoRemote, + walletAssetObserver: walletAssetsObserver ) let router = AssetManagementRouter() diff --git a/fearless/Modules/AssetManagement/AssetManagementInteractor.swift b/fearless/Modules/AssetManagement/AssetManagementInteractor.swift index b69370b57e..6b584da9c5 100644 --- a/fearless/Modules/AssetManagement/AssetManagementInteractor.swift +++ b/fearless/Modules/AssetManagement/AssetManagementInteractor.swift @@ -18,6 +18,7 @@ actor AssetManagementInteractor { private let accountInfoFetchingProvider: AccountInfoFetching private let eventCenter: EventCenterProtocol private let accountInfoRemoteService: AccountInfoRemoteService + private let walletAssetObserver: WalletAssetsObserver private var bufferWallet: MetaAccountModel? @@ -26,13 +27,15 @@ actor AssetManagementInteractor { priceLocalSubscriber: PriceLocalStorageSubscriber, accountInfoFetchingProvider: AccountInfoFetching, eventCenter: EventCenterProtocol, - accountInfoRemoteService: AccountInfoRemoteService + accountInfoRemoteService: AccountInfoRemoteService, + walletAssetObserver: WalletAssetsObserver ) { self.chainAssetFetching = chainAssetFetching self.priceLocalSubscriber = priceLocalSubscriber self.accountInfoFetchingProvider = accountInfoFetchingProvider self.eventCenter = eventCenter self.accountInfoRemoteService = accountInfoRemoteService + self.walletAssetObserver = walletAssetObserver self.eventCenter.add(observer: self) } @@ -96,7 +99,7 @@ extension AssetManagementInteractor: AssetManagementInteractorInput { func getAvailableChainAssets() async throws -> [ChainAsset] { let chainAssets = try await chainAssetFetching.fetchAwait( shouldUseCache: true, - filters: [], + filters: [.enabledChains], sortDescriptors: [] ) fetchPrices(for: chainAssets) @@ -123,6 +126,12 @@ extension AssetManagementInteractor: AssetManagementInteractorInput { ) return accountInfo } + + func updatedVisibility(for chainAssets: [ChainAsset]) async -> MetaAccountModel { + let updatedWallet = await walletAssetObserver.updateVisibility(wallet: bufferWallet, chainAssets: chainAssets) + bufferWallet = updatedWallet + return updatedWallet + } } // MARK: - PriceLocalSubscriptionHandler diff --git a/fearless/Modules/AssetManagement/AssetManagementPresenter.swift b/fearless/Modules/AssetManagement/AssetManagementPresenter.swift index 16b4b6e6ef..cc50302cc0 100644 --- a/fearless/Modules/AssetManagement/AssetManagementPresenter.swift +++ b/fearless/Modules/AssetManagement/AssetManagementPresenter.swift @@ -27,6 +27,9 @@ protocol AssetManagementInteractorInput: AnyObject { for chainAsset: ChainAsset, wallet: MetaAccountModel ) async throws -> AccountInfo? + func updatedVisibility( + for chainAssets: [ChainAsset] + ) async -> MetaAccountModel } final class AssetManagementPresenter { @@ -40,6 +43,7 @@ final class AssetManagementPresenter { private let viewModelFactory: AssetManagementViewModelFactory private var networkFilter: NetworkManagmentFilter? + private var viewModel: AssetManagementViewModel? private var chainAssets: [ChainAsset] = [] private var accountInfos: [ChainAssetKey: AccountInfo?] = [:] private var prices: [PriceData] = [] @@ -83,6 +87,7 @@ final class AssetManagementPresenter { search: searchText, pendingAccountInfoChainAssets: pendingAccountInfoChainAssets ) + self.viewModel = viewModel await view?.didReceive(viewModel: viewModel) } } @@ -208,6 +213,17 @@ extension AssetManagementPresenter: AssetManagementViewOutput { } getInitialData() } + + func didPullToRefresh() { + Task { + guard let chainAssets = viewModel?.dispayedChainAssets else { + return + } + let updatedWallet = await interactor.updatedVisibility(for: chainAssets) + wallet = updatedWallet + provideViewModel() + } + } } // MARK: - AssetManagementInteractorOutput diff --git a/fearless/Modules/AssetManagement/AssetManagementViewController.swift b/fearless/Modules/AssetManagement/AssetManagementViewController.swift index b54c02edef..97c4118bd1 100644 --- a/fearless/Modules/AssetManagement/AssetManagementViewController.swift +++ b/fearless/Modules/AssetManagement/AssetManagementViewController.swift @@ -10,6 +10,7 @@ protocol AssetManagementViewOutput: AnyObject { func allNetworkButtonDidTapped() func didSelectRow(at indexPath: IndexPath, viewModel: AssetManagementViewModel) func didTap(on section: Int, viewModel: AssetManagementViewModel) + func didPullToRefresh() } final class AssetManagementViewController: UIViewController, ViewHolder, HiddableBarWhenPushed, KeyboardViewAdoptable { @@ -90,8 +91,18 @@ final class AssetManagementViewController: UIViewController, ViewHolder, Hiddabl rootView.tableView.estimatedSectionFooterHeight = 0 rootView.tableView.contentInsetAdjustmentBehavior = .never + + if let refreshControl = rootView.tableView.refreshControl { + refreshControl.addTarget( + self, + action: #selector(handlePullToRefresh), + for: .valueChanged + ) + } } + // MARK: - Actions + @objc private func handleTap(sender: UIGestureRecognizer) { guard let viewModel, let section = sender.view?.tag else { @@ -100,6 +111,11 @@ final class AssetManagementViewController: UIViewController, ViewHolder, Hiddabl output.didTap(on: section, viewModel: viewModel) } + @objc + private func handlePullToRefresh() { + output.didPullToRefresh() + } + // MARK: - KeyboardViewAdoptable var target: Constraint? { rootView.keyboardAdoptableConstraint } @@ -116,6 +132,7 @@ extension AssetManagementViewController: AssetManagementViewInput { rootView.setFilter(title: viewModel.filterButtonTitle) rootView.setAddAssetButton(visible: viewModel.addAssetButtonIsHidden) rootView.tableView.reloadData() + rootView.tableView.refreshControl?.endRefreshing() reloadEmptyState(animated: false) } diff --git a/fearless/Modules/AssetManagement/AssetManagementViewLayout.swift b/fearless/Modules/AssetManagement/AssetManagementViewLayout.swift index 112fad2f95..6d23192e81 100644 --- a/fearless/Modules/AssetManagement/AssetManagementViewLayout.swift +++ b/fearless/Modules/AssetManagement/AssetManagementViewLayout.swift @@ -53,6 +53,7 @@ final class AssetManagementViewLayout: UIView { tableView.separatorStyle = .none tableView.backgroundColor = R.color.colorBlack19() tableView.tableFooterView = UIView() + tableView.refreshControl = UIRefreshControl() return tableView }() diff --git a/fearless/Modules/AssetManagement/ViewModel/AssetManagementViewModel.swift b/fearless/Modules/AssetManagement/ViewModel/AssetManagementViewModel.swift index 8140331aba..8db9515f5e 100644 --- a/fearless/Modules/AssetManagement/ViewModel/AssetManagementViewModel.swift +++ b/fearless/Modules/AssetManagement/ViewModel/AssetManagementViewModel.swift @@ -6,6 +6,7 @@ struct AssetManagementViewModel { var list: [AssetManagementTableSection] let filterButtonTitle: String let addAssetButtonIsHidden: Bool + let dispayedChainAssets: [ChainAsset] } struct AssetManagementTableSection { diff --git a/fearless/Modules/AssetManagement/ViewModel/AssetManagementViewModelFactory.swift b/fearless/Modules/AssetManagement/ViewModel/AssetManagementViewModelFactory.swift index fb06c878c1..2b95dc6a9c 100644 --- a/fearless/Modules/AssetManagement/ViewModel/AssetManagementViewModelFactory.swift +++ b/fearless/Modules/AssetManagement/ViewModel/AssetManagementViewModelFactory.swift @@ -106,7 +106,8 @@ final class AssetManagementViewModelFactoryDefault: AssetManagementViewModelFact let viewModel = AssetManagementViewModel( list: list, filterButtonTitle: filterButtonTitle, - addAssetButtonIsHidden: true + addAssetButtonIsHidden: true, + dispayedChainAssets: filtredChainAssets ) return viewModel } diff --git a/fearless/Modules/AssetNetworks/AssetNetworksAssembly.swift b/fearless/Modules/AssetNetworks/AssetNetworksAssembly.swift index d3430dde8b..0ae4799947 100644 --- a/fearless/Modules/AssetNetworks/AssetNetworksAssembly.swift +++ b/fearless/Modules/AssetNetworks/AssetNetworksAssembly.swift @@ -9,6 +9,7 @@ final class AssetNetworksAssembly { let priceLocalSubscriber = PriceLocalStorageSubscriberImpl.shared let chainRepository = ChainRepositoryFactory().createRepository( + for: NSPredicate.enabledCHain(), sortDescriptors: [NSSortDescriptor.chainsByAddressPrefix] ) let chainAssetFetching = ChainAssetsFetching( diff --git a/fearless/Modules/AssetNetworks/Views/AssetNetworksTableCell.swift b/fearless/Modules/AssetNetworks/Views/AssetNetworksTableCell.swift index f8575a1923..17920996bc 100644 --- a/fearless/Modules/AssetNetworks/Views/AssetNetworksTableCell.swift +++ b/fearless/Modules/AssetNetworks/Views/AssetNetworksTableCell.swift @@ -78,6 +78,7 @@ final class AssetNetworksTableCell: UITableViewCell { override func prepareForReuse() { super.prepareForReuse() + viewModel?.iconViewModel?.cancel(on: networkIconImageView) viewModel = nil } diff --git a/fearless/Modules/BackupWallet/BackupWalletAssembly.swift b/fearless/Modules/BackupWallet/BackupWalletAssembly.swift index 5b12d0608b..5a14e709dd 100644 --- a/fearless/Modules/BackupWallet/BackupWalletAssembly.swift +++ b/fearless/Modules/BackupWallet/BackupWalletAssembly.swift @@ -13,6 +13,7 @@ final class BackupWalletAssembly { let priceLocalSubscriber = PriceLocalStorageSubscriberImpl.shared let chainRepository = ChainRepositoryFactory().createRepository( + for: NSPredicate.enabledCHain(), sortDescriptors: [NSSortDescriptor.chainsByAddressPrefix] ) let accountRepositoryFactory = AccountRepositoryFactory(storageFacade: UserDataStorageFacade.shared) diff --git a/fearless/Modules/BackupWallet/BackupWalletViewModelFactory.swift b/fearless/Modules/BackupWallet/BackupWalletViewModelFactory.swift index e14673088f..5f2817dfe4 100644 --- a/fearless/Modules/BackupWallet/BackupWalletViewModelFactory.swift +++ b/fearless/Modules/BackupWallet/BackupWalletViewModelFactory.swift @@ -1,6 +1,7 @@ import Foundation import SoraFoundation import SSFCloudStorage +import SSFModels protocol BackupWalletViewModelFactoryProtocol { func createViewModel( diff --git a/fearless/Modules/BalanceInfo/BalanceInfoAssembly.swift b/fearless/Modules/BalanceInfo/BalanceInfoAssembly.swift index f903a69b41..6763943e03 100644 --- a/fearless/Modules/BalanceInfo/BalanceInfoAssembly.swift +++ b/fearless/Modules/BalanceInfo/BalanceInfoAssembly.swift @@ -8,6 +8,7 @@ enum BalanceInfoType { case wallet(wallet: MetaAccountModel) case chainAsset(wallet: MetaAccountModel, chainAsset: ChainAsset) case chainAssets(chainAssets: [ChainAsset], wallet: MetaAccountModel) + case networkManagement(wallet: MetaAccountModel) var wallet: MetaAccountModel { switch self { @@ -17,6 +18,8 @@ enum BalanceInfoType { return wallet case let .chainAssets(_, wallet): return wallet + case let .networkManagement(wallet): + return wallet } } } diff --git a/fearless/Modules/BalanceInfo/BalanceInfoInteractor.swift b/fearless/Modules/BalanceInfo/BalanceInfoInteractor.swift index c70227beaa..7e35d1cfd8 100644 --- a/fearless/Modules/BalanceInfo/BalanceInfoInteractor.swift +++ b/fearless/Modules/BalanceInfo/BalanceInfoInteractor.swift @@ -80,6 +80,11 @@ private extension BalanceInfoInteractor { wallet: wallet, listener: self ) + case let .networkManagement(wallet): + walletBalanceSubscriptionAdapter.subscribeNetworkManagementBalance( + wallet: wallet, + listener: self + ) } } @@ -162,6 +167,8 @@ extension BalanceInfoInteractor: WalletBalanceSubscriptionListener { return .chainAsset(wallet: wallet, chainAsset: chainAsset) case let .chainAssets(chainAssets, wallet): return .chainAssets(chainAssets: chainAssets, wallet: wallet) + case let .networkManagement(wallet): + return .networkManagement(wallet: wallet) } } diff --git a/fearless/Modules/BalanceInfo/BalanceInfoPresenter.swift b/fearless/Modules/BalanceInfo/BalanceInfoPresenter.swift index 8860a73e42..472d9843d0 100644 --- a/fearless/Modules/BalanceInfo/BalanceInfoPresenter.swift +++ b/fearless/Modules/BalanceInfo/BalanceInfoPresenter.swift @@ -156,6 +156,10 @@ extension BalanceInfoPresenter: EventVisitorProtocol { let newType = BalanceInfoType.chainAssets(chainAssets: chainAssets, wallet: event.account) interactor.balanceInfoType = newType interactor.fetchBalanceInfo() + case .networkManagement: + let newType = BalanceInfoType.networkManagement(wallet: event.account) + interactor.balanceInfoType = newType + interactor.fetchBalanceInfo() } } } diff --git a/fearless/Modules/BalanceInfo/BalanceInfoViewLayout.swift b/fearless/Modules/BalanceInfo/BalanceInfoViewLayout.swift index 0a1d6883f0..0cec6ab010 100644 --- a/fearless/Modules/BalanceInfo/BalanceInfoViewLayout.swift +++ b/fearless/Modules/BalanceInfo/BalanceInfoViewLayout.swift @@ -35,10 +35,9 @@ final class BalanceInfoViewLayout: UIView { priceLabel.attributedText = viewModel?.dayChangeAttributedString balanceLabel.text = viewModel?.balanceString - balanceLabel.layoutIfNeeded() - priceLabel.layoutIfNeeded() - if viewModel == nil { + balanceLabel.layoutIfNeeded() + priceLabel.layoutIfNeeded() startLoadingIfNeeded() } else { stopLoadingIfNeeded() diff --git a/fearless/Modules/BalanceInfo/BalanceInfoViewModelFactory.swift b/fearless/Modules/BalanceInfo/BalanceInfoViewModelFactory.swift index b308683b7e..af149c4501 100644 --- a/fearless/Modules/BalanceInfo/BalanceInfoViewModelFactory.swift +++ b/fearless/Modules/BalanceInfo/BalanceInfoViewModelFactory.swift @@ -68,6 +68,17 @@ final class BalanceInfoViewModelFactory: BalanceInfoViewModelFactoryProtocol { infoButtonEnabled: infoButtonEnabled, locale: locale ) + case let .networkManagement(wallet): + guard let info = balances[wallet.metaId] else { + return zeroBalanceViewModel( + balanceString: wallet.selectedCurrency.symbol + "0", + infoButtonEnabled: false + ) + } + balanceInfoViewModel = buildWalletBalance( + with: info, + locale: locale + ) } return balanceInfoViewModel diff --git a/fearless/Modules/Banners/BannerCollectionViewCell.swift b/fearless/Modules/Banners/BannerCollectionViewCell.swift index 163ff179fb..57fc8d210c 100644 --- a/fearless/Modules/Banners/BannerCollectionViewCell.swift +++ b/fearless/Modules/Banners/BannerCollectionViewCell.swift @@ -7,15 +7,18 @@ struct BannerCellViewModel { let buttonTitle: String let image: UIImage let dismissable: Bool + let fullsizeImage: Bool + let bannerType: Banners } protocol BannerCellectionCellDelegate: AnyObject { - func didActionButtonTapped(indexPath: IndexPath?) - func didCloseButtonTapped(indexPath: IndexPath?) + func didActionButtonTapped(banner: Banners) + func didCloseButtonTapped(banner: Banners) } final class BannerCollectionViewCell: UICollectionViewCell { weak var delegate: BannerCellectionCellDelegate? + private var viewModel: BannerCellViewModel? let titleLabel: UILabel = { let label = UILabel() @@ -79,20 +82,45 @@ final class BannerCollectionViewCell: UICollectionViewCell { } func bind(viewModel: BannerCellViewModel) { + self.viewModel = viewModel + titleLabel.text = viewModel.title subtitleLabel.text = viewModel.subtitle actionButton.imageWithTitleView?.title = viewModel.buttonTitle imageView.image = viewModel.image closeButton.isHidden = !viewModel.dismissable + + updateImageConstraints(fullsizeImage: viewModel.fullsizeImage) } private func bindActions() { actionButton.addAction { [weak self] in - self?.delegate?.didActionButtonTapped(indexPath: self?.indexPath) + guard let banner = self?.viewModel?.bannerType else { + return + } + + self?.delegate?.didActionButtonTapped(banner: banner) } closeButton.addAction { [weak self] in - self?.delegate?.didCloseButtonTapped(indexPath: self?.indexPath) + + guard let banner = self?.viewModel?.bannerType else { + return + } + + self?.delegate?.didCloseButtonTapped(banner: banner) + } + } + + private func updateImageConstraints(fullsizeImage: Bool) { + if fullsizeImage { + imageView.snp.remakeConstraints { make in + make.leading.trailing.bottom.equalToSuperview() + } + } else { + imageView.snp.remakeConstraints { make in + make.trailing.bottom.equalToSuperview() + } } } @@ -102,19 +130,25 @@ final class BannerCollectionViewCell: UICollectionViewCell { make.trailing.bottom.equalToSuperview() } + addSubview(closeButton) + closeButton.snp.makeConstraints { make in + make.top.trailing.equalToSuperview().inset(UIConstants.defaultOffset) + make.size.equalTo(UIConstants.roundedCloseButtonSize) + } + addSubview(titleLabel) titleLabel.setContentHuggingPriority(.defaultHigh, for: .horizontal) titleLabel.snp.makeConstraints { make in make.top.equalToSuperview().offset(16) make.leading.equalToSuperview().offset(UIConstants.bigOffset) - make.trailing.equalTo(imageView.snp.leading).inset(16) + make.trailing.equalTo(closeButton.snp.leading).inset(16) } addSubview(subtitleLabel) subtitleLabel.snp.makeConstraints { make in make.top.equalTo(titleLabel.snp.bottom).offset(UIConstants.defaultOffset) make.leading.equalToSuperview().offset(UIConstants.bigOffset) - make.trailing.equalTo(imageView.snp.leading).inset(16) + make.trailing.equalTo(closeButton.snp.leading).inset(16) } addSubview(actionButton) @@ -125,11 +159,5 @@ final class BannerCollectionViewCell: UICollectionViewCell { make.height.equalTo(32) make.width.greaterThanOrEqualTo(102) } - - addSubview(closeButton) - closeButton.snp.makeConstraints { make in - make.top.trailing.equalToSuperview().inset(UIConstants.defaultOffset) - make.size.equalTo(UIConstants.roundedCloseButtonSize) - } } } diff --git a/fearless/Modules/Banners/BannersAssembly.swift b/fearless/Modules/Banners/BannersAssembly.swift index 4cda660b7f..90be3884a7 100644 --- a/fearless/Modules/Banners/BannersAssembly.swift +++ b/fearless/Modules/Banners/BannersAssembly.swift @@ -3,7 +3,11 @@ import SoraFoundation import RobinHood final class BannersAssembly { - static func configureModule(output: BannersModuleOutput?) -> BannersModuleCreationResult? { + static func configureModule( + output: BannersModuleOutput?, + type: BannersModuleType, + wallet: MetaAccountModel? + ) -> BannersModuleCreationResult? { let localizationManager = LocalizationManager.shared let walletProvider = UserDataStorageFacade.shared @@ -13,13 +17,9 @@ final class BannersAssembly { mapper: AnyCoreDataMapper(ManagedMetaAccountMapper()) ) - let accountRepositoryFactory = AccountRepositoryFactory(storageFacade: UserDataStorageFacade.shared) - let accountRepository = accountRepositoryFactory.createMetaAccountRepository(for: nil, sortDescriptors: []) - let interactor = BannersInteractor( walletProvider: walletProvider, - repository: accountRepository, - operationQueue: OperationQueue() + eventCenter: EventCenter.shared ) let router = BannersRouter() @@ -29,7 +29,9 @@ final class BannersAssembly { moduleOutput: output, interactor: interactor, router: router, - localizationManager: localizationManager + localizationManager: localizationManager, + type: type, + wallet: wallet ) let view = BannersViewController( diff --git a/fearless/Modules/Banners/BannersInteractor.swift b/fearless/Modules/Banners/BannersInteractor.swift index 5355fd7a85..11864bd8f3 100644 --- a/fearless/Modules/Banners/BannersInteractor.swift +++ b/fearless/Modules/Banners/BannersInteractor.swift @@ -12,22 +12,44 @@ final class BannersInteractor { private weak var output: BannersInteractorOutput? private let walletProvider: StreamableProvider - private let repository: AnyDataProviderRepository - private let operationQueue: OperationQueue + private let eventCenter: EventCenterProtocol init( walletProvider: StreamableProvider, - repository: AnyDataProviderRepository, - operationQueue: OperationQueue + eventCenter: EventCenterProtocol ) { self.walletProvider = walletProvider - self.repository = repository - self.operationQueue = operationQueue + self.eventCenter = eventCenter } // MARK: - Private methods +} + +// MARK: - BannersInteractorInput + +extension BannersInteractor: BannersInteractorInput { + func setup(with output: BannersInteractorOutput) { + self.output = output + } + + func markWalletAsBackedUp(_ wallet: MetaAccountModel) { + let updatedWallet = wallet.replacingIsBackuped(true) - private func subscribeToWallet() { + SelectedWalletSettings.shared.performSave(value: updatedWallet) { [weak self] result in + DispatchQueue.main.async { + switch result { + case let .success(account): + self?.output?.didReceive(wallet: account) + let event = MetaAccountModelChangedEvent(account: account) + self?.eventCenter.notify(with: event) + case let .failure(error): + self?.output?.didReceive(error: error) + } + } + } + } + + func subscribeToWallet() { let updateClosure: ([DataProviderChange]) -> Void = { [weak self] changes in guard let selectedWallet = changes.firstToLastChange(filter: { wallet in wallet.isSelected @@ -52,37 +74,3 @@ final class BannersInteractor { ) } } - -// MARK: - BannersInteractorInput - -extension BannersInteractor: BannersInteractorInput { - func setup(with output: BannersInteractorOutput) { - self.output = output - subscribeToWallet() - } - - func markWalletAsBackedUp(_ wallet: MetaAccountModel) { - let updatedWallet = wallet.replacingIsBackuped(true) - - let operation = repository.saveOperation { - [updatedWallet] - } _: { - [] - } - - operation.completionBlock = { - SelectedWalletSettings.shared.performSave(value: updatedWallet) { [weak self] result in - DispatchQueue.main.async { - switch result { - case let .success(account): - self?.output?.didReceive(wallet: account) - case let .failure(error): - self?.output?.didReceive(error: error) - } - } - } - } - - operationQueue.addOperation(operation) - } -} diff --git a/fearless/Modules/Banners/BannersPresenter.swift b/fearless/Modules/Banners/BannersPresenter.swift index 030b4aaa22..828ca7f5bc 100644 --- a/fearless/Modules/Banners/BannersPresenter.swift +++ b/fearless/Modules/Banners/BannersPresenter.swift @@ -1,6 +1,12 @@ import Foundation +import SSFModels import SoraFoundation +enum BannersModuleType { + case independent + case embed +} + protocol BannersViewInput: ControllerBackedProtocol { func didReceive(viewModel: BannersViewModel) } @@ -8,6 +14,7 @@ protocol BannersViewInput: ControllerBackedProtocol { protocol BannersInteractorInput: AnyObject { func setup(with output: BannersInteractorOutput) func markWalletAsBackedUp(_ wallet: MetaAccountModel) + func subscribeToWallet() } final class BannersPresenter { @@ -17,6 +24,7 @@ final class BannersPresenter { private let router: BannersRouterInput private let interactor: BannersInteractorInput private weak var moduleOutput: BannersModuleOutput? + private let type: BannersModuleType private let logger: LoggerProtocol private lazy var viewModelFactory: BannersViewModelFactoryProtocol = { @@ -32,12 +40,17 @@ final class BannersPresenter { moduleOutput: BannersModuleOutput?, interactor: BannersInteractorInput, router: BannersRouterInput, - localizationManager: LocalizationManagerProtocol + localizationManager: LocalizationManagerProtocol, + type: BannersModuleType, + wallet: MetaAccountModel? ) { self.logger = logger self.moduleOutput = moduleOutput self.interactor = interactor self.router = router + self.type = type + self.wallet = wallet + self.localizationManager = localizationManager } @@ -88,39 +101,45 @@ final class BannersPresenter { // MARK: - BannersViewOutput extension BannersPresenter: BannersViewOutput { - func didTapOnCell(at indexPath: IndexPath) { - guard - let wallet = wallet, - let tappedOption = Banners(rawValue: indexPath.row) else { + func didTapOnBanner(_ banner: Banners) { + guard let wallet = wallet else { return } - switch tappedOption { + switch banner { case .backup: router.showWalletBackupScreen(for: wallet, from: view) case .buyXor: break + case .liquidityPools: + router.presentLiquidityPools(on: view, wallet: wallet, chainId: Chain.soraMain.genesisHash) + case .liquidityPoolsTest: + router.presentLiquidityPools(on: view, wallet: wallet, chainId: Chain.soraTest.genesisHash) } } - func didCloseCell(at indexPath: IndexPath) { - guard - let wallet = wallet, - let tappedOption = Banners(rawValue: indexPath.row) else { + func didCloseBanner(_ banner: Banners) { + guard let wallet = wallet else { return } - switch tappedOption { + switch banner { case .backup: showNotBackedUpAlert(wallet: wallet) case .buyXor: break + case .liquidityPools, .liquidityPoolsTest: + moduleOutput?.didTapCloseBanners() } } func didLoad(view: BannersViewInput) { self.view = view interactor.setup(with: self) + + if type == .independent { + interactor.subscribeToWallet() + } } } @@ -148,4 +167,9 @@ extension BannersPresenter: BannersModuleInput { self.wallet = wallet provideViewModel() } + + func update(banners: [Banners]) { + let viewModel = viewModelFactory.createViewModel(banners: banners, locale: selectedLocale) + view?.didReceive(viewModel: viewModel) + } } diff --git a/fearless/Modules/Banners/BannersProtocols.swift b/fearless/Modules/Banners/BannersProtocols.swift index 71f4a3ddfa..e28bddd444 100644 --- a/fearless/Modules/Banners/BannersProtocols.swift +++ b/fearless/Modules/Banners/BannersProtocols.swift @@ -1,3 +1,5 @@ +import SSFModels + typealias BannersModuleCreationResult = ( view: BannersViewInput, input: BannersModuleInput @@ -8,12 +10,20 @@ protocol BannersRouterInput: AnyObject, SheetAlertPresentable { for wallet: MetaAccountModel, from view: ControllerBackedProtocol? ) + + func presentLiquidityPools( + on view: ControllerBackedProtocol?, + wallet: MetaAccountModel, + chainId: ChainModel.Id + ) } protocol BannersModuleInput: AnyObject { func reload(with wallet: MetaAccountModel) + func update(banners: [Banners]) } protocol BannersModuleOutput: AnyObject { func reloadBannersView() + func didTapCloseBanners() } diff --git a/fearless/Modules/Banners/BannersRouter.swift b/fearless/Modules/Banners/BannersRouter.swift index db70aac5e1..8c89e171ba 100644 --- a/fearless/Modules/Banners/BannersRouter.swift +++ b/fearless/Modules/Banners/BannersRouter.swift @@ -1,4 +1,5 @@ import Foundation +import SSFModels final class BannersRouter: BannersRouterInput { func showWalletBackupScreen( @@ -12,4 +13,21 @@ final class BannersRouter: BannersRouterInput { let navigation = FearlessNavigationController(rootViewController: module.view.controller) view?.controller.present(navigation, animated: true) } + + func presentLiquidityPools( + on view: ControllerBackedProtocol?, + wallet: MetaAccountModel, + chainId: ChainModel.Id + ) { + guard + let tabBarController = view?.controller, + let viewController = LiquidityPoolsOverviewAssembly.configureModule(wallet: wallet, chainId: chainId)?.view.controller + else { + return + } + let navigationController = FearlessNavigationController(rootViewController: viewController) + + let presentingController = tabBarController.topModalViewController + presentingController.present(navigationController, animated: true, completion: nil) + } } diff --git a/fearless/Modules/Banners/BannersViewController.swift b/fearless/Modules/Banners/BannersViewController.swift index 1d381b026f..3330a4a738 100644 --- a/fearless/Modules/Banners/BannersViewController.swift +++ b/fearless/Modules/Banners/BannersViewController.swift @@ -3,8 +3,8 @@ import SoraFoundation protocol BannersViewOutput: AnyObject { func didLoad(view: BannersViewInput) - func didTapOnCell(at indexPath: IndexPath) - func didCloseCell(at indexPath: IndexPath) + func didTapOnBanner(_ banner: Banners) + func didCloseBanner(_ banner: Banners) } final class BannersViewController: UIViewController, ViewHolder { @@ -72,18 +72,12 @@ extension BannersViewController: Localizable { // MARK: - BannerCellectionCellDelegate extension BannersViewController: BannerCellectionCellDelegate { - func didActionButtonTapped(indexPath: IndexPath?) { - guard let indexPath = indexPath else { - return - } - output.didTapOnCell(at: indexPath) + func didActionButtonTapped(banner: Banners) { + output.didTapOnBanner(banner) } - func didCloseButtonTapped(indexPath: IndexPath?) { - guard let indexPath = indexPath else { - return - } - output.didCloseCell(at: indexPath) + func didCloseButtonTapped(banner: Banners) { + output.didCloseBanner(banner) } } diff --git a/fearless/Modules/Banners/BannersViewModelFactory.swift b/fearless/Modules/Banners/BannersViewModelFactory.swift index 5dff310d80..f59d00bb7e 100644 --- a/fearless/Modules/Banners/BannersViewModelFactory.swift +++ b/fearless/Modules/Banners/BannersViewModelFactory.swift @@ -1,4 +1,5 @@ import Foundation +import SSFModels struct BannersViewModel { let banners: [BannerCellViewModel] @@ -7,6 +8,8 @@ struct BannersViewModel { enum Banners: Int { case backup case buyXor + case liquidityPools + case liquidityPoolsTest } protocol BannersViewModelFactoryProtocol { @@ -14,17 +17,12 @@ protocol BannersViewModelFactoryProtocol { wallet: MetaAccountModel, locale: Locale ) -> BannersViewModel + + func createViewModel(banners: [Banners], locale: Locale) -> BannersViewModel } final class BannersViewModelFactory: BannersViewModelFactoryProtocol { - func createViewModel( - wallet: MetaAccountModel, - locale: Locale - ) -> BannersViewModel { - var banners: [Banners] = [] - if !wallet.hasBackup { - banners.insert(.backup, at: 0) - } + func createViewModel(banners: [Banners], locale: Locale) -> BannersViewModel { let bannersViewModel: [BannerCellViewModel] = banners.map { switch $0 { case .backup: @@ -39,7 +37,9 @@ final class BannersViewModelFactory: BannersViewModelFactoryProtocol { subtitle: subtitle, buttonTitle: buttonAction, image: R.image.fearlessBanner()!, - dismissable: true + dismissable: true, + fullsizeImage: false, + bannerType: .backup ) case .buyXor: let title = R.string.localizable @@ -53,11 +53,54 @@ final class BannersViewModelFactory: BannersViewModelFactoryProtocol { subtitle: subtitle, buttonTitle: buttonAction, image: R.image.xorBanner()!, - dismissable: true + dismissable: true, + fullsizeImage: false, + bannerType: .buyXor + ) + case .liquidityPools: + let title = "Liquidity pools" + let subtitle = "Invest your funds in Liquidity\npools and receive rewards" + let buttonAction = "Show details" + + return BannerCellViewModel( + title: title, + subtitle: subtitle, + buttonTitle: buttonAction, + image: R.image.iconLpBanner()!, + dismissable: true, + fullsizeImage: true, + bannerType: .liquidityPools + ) + + case .liquidityPoolsTest: + let title = "Liquidity pools test" + let subtitle = "Invest your funds in Liquidity\npools and receive rewards" + let buttonAction = "Show details" + + return BannerCellViewModel( + title: title, + subtitle: subtitle, + buttonTitle: buttonAction, + image: R.image.iconLpBanner()!, + dismissable: true, + fullsizeImage: true, + bannerType: .liquidityPoolsTest ) } } return BannersViewModel(banners: bannersViewModel) } + + func createViewModel( + wallet: MetaAccountModel, + locale: Locale + ) -> BannersViewModel { + var banners: [Banners] = [] + if !wallet.hasBackup { + banners.insert(.backup, at: 0) + } + + return createViewModel(banners: banners, locale: locale) + } } diff --git a/fearless/Modules/CrossChain/CrossChainAssembly.swift b/fearless/Modules/CrossChain/CrossChainAssembly.swift index dde9e07e33..ea434c3561 100644 --- a/fearless/Modules/CrossChain/CrossChainAssembly.swift +++ b/fearless/Modules/CrossChain/CrossChainAssembly.swift @@ -22,6 +22,7 @@ final class CrossChainAssembly { ) let chainRepository = ChainRepositoryFactory().createRepository( + for: NSPredicate.enabledCHain(), sortDescriptors: [NSSortDescriptor.chainsByAddressPrefix] ) let operationQueue = OperationQueue() diff --git a/fearless/Modules/CrossChain/CrossChainPresenter.swift b/fearless/Modules/CrossChain/CrossChainPresenter.swift index 8c8f37dff9..b790d2d683 100644 --- a/fearless/Modules/CrossChain/CrossChainPresenter.swift +++ b/fearless/Modules/CrossChain/CrossChainPresenter.swift @@ -5,12 +5,13 @@ import BigInt import SSFExtrinsicKit import SSFUtils import SSFModels +import SSFQRService protocol CrossChainViewInput: ControllerBackedProtocol, LoadableViewProtocol { func didReceive(assetBalanceViewModel: AssetBalanceViewModelProtocol?) func didReceive(amountInputViewModel: IAmountInputViewModel?) func didReceive(originSelectNetworkViewModel: SelectNetworkViewModel) - func didReceive(destSelectNetworkViewModel: SelectNetworkViewModel) + func didReceive(destSelectNetworkViewModel: SelectNetworkViewModel?) func didReceive(originFeeViewModel: LocalizableResource?) func didReceive(destinationFeeViewModel: LocalizableResource?) func didReceive(recipientViewModel: RecipientViewModel) @@ -113,7 +114,10 @@ final class CrossChainPresenter { } private func checkLoadingState() { - view?.setButtonLoadingState(isLoading: !loadingCollector.isReady) + guard let isReady = loadingCollector.isReady else { + return + } + view?.setButtonLoadingState(isLoading: !isReady) } private func provideInputViewModel() { @@ -156,6 +160,7 @@ final class CrossChainPresenter { private func provideDestSelectNetworkViewModel() { guard let selectedDestChainModel = selectedDestChainModel else { + view?.didReceive(destSelectNetworkViewModel: nil) return } @@ -241,18 +246,12 @@ final class CrossChainPresenter { } private func handle(newAddress: String) { - guard let destChain = selectedDestChainModel else { - return - } loadingCollector.addressExists = !newAddress.isEmpty checkLoadingState() interactor.fetchDestinationAccountInfo(address: newAddress) recipientAddress = newAddress - let isValid = interactor.validate(address: newAddress, for: destChain).isValid - let viewModel = viewModelFactory.buildRecipientViewModel( - address: newAddress, - isValid: isValid - ) + let isValid = processDestinationAddress() != nil + let viewModel = viewModelFactory.buildRecipientViewModel(address: newAddress, isValid: isValid) view?.didReceive(recipientViewModel: viewModel) } @@ -263,7 +262,7 @@ final class CrossChainPresenter { guard let chain = selectedDestChainModel else { return } - let isValid = interactor.validate(address: recipientAddress, for: chain).isValid + let isValid = interactor.validate(address: recipientAddress, for: chain).isValidOrSame if isValid, let recipientAddress = recipientAddress { handle(newAddress: recipientAddress) } else { @@ -285,11 +284,6 @@ final class CrossChainPresenter { let minimumBalance = Decimal.fromSubstrateAmount(existentialDeposit ?? .zero, precision: Int16(utilityChainAsset.asset.precision)) ?? .zero let inputAmountDecimal = amountInputResult? .absoluteValue(from: originNetworkSelectedAssetBalance - (destNetworkFee ?? .zero) - originNetworkFeeIfRequired()) ?? .zero - let edParameters: ExistentialDepositValidationParameters = .utility( - spendingAmount: originNetworkFeeIfRequired() + inputAmountDecimal, - totalAmount: utilityBalance, - minimumBalance: minimumBalance - ) let destChainAsset = selectedDestChainModel.map { ChainAsset(chain: $0, asset: selectedAmountChainAsset.asset) } @@ -302,18 +296,6 @@ final class CrossChainPresenter { return Decimal.fromSubstrateAmount($0, precision: Int16(destChainAsset.asset.precision)) } - let destMinimumBalance: Decimal? = destExistentialDeposit.flatMap { - Decimal.fromSubstrateAmount($0, precision: Int16(utilityChainAsset.asset.precision)) - } - - let totalDestinationAmount = destBalanceDecimal.map { $0 + inputAmountDecimal } - - let destEdParameters: ExistentialDepositValidationParameters = .utility( - spendingAmount: 0, - totalAmount: totalDestinationAmount, - minimumBalance: destMinimumBalance - ) - let originFeeValidating = dataValidatingFactory.has( fee: originNetworkFee, locale: selectedLocale @@ -345,10 +327,19 @@ final class CrossChainPresenter { locale: selectedLocale ) + let spending: Decimal + if selectedAmountChainAsset.isUtility { + spending = originNetworkFee.or(.zero) + inputAmountDecimal + } else { + spending = originNetworkFee.or(.zero) + } + let exsitentialDepositIsNotViolated = dataValidatingFactory.exsitentialDepositIsNotViolated( - parameters: edParameters, - locale: selectedLocale, + spending: spending, + balance: utilityBalance.or(.zero), + minimumBalance: minimumBalance, chainAsset: selectedAmountChainAsset, + locale: selectedLocale, canProceedIfViolated: false, proceedAction: {}, setMaxAction: {}, @@ -356,10 +347,11 @@ final class CrossChainPresenter { ) let soraBridgeViolated = dataValidatingFactory.soraBridgeViolated( - originCHainId: selectedOriginChainModel.chainId, - destChainId: selectedDestChainModel?.chainId, + originCHain: selectedOriginChainModel, + destChain: selectedDestChainModel, amount: inputAmountDecimal, - locale: selectedLocale + locale: selectedLocale, + asset: selectedAmountChainAsset.asset ) let soraBridgeAmountLessFeeViolated = dataValidatingFactory.soraBridgeAmountLessFeeViolated( @@ -482,6 +474,18 @@ final class CrossChainPresenter { originNetworkSelectedAssetBalance = totalBalance - (destNetworkFee ?? .zero) - originNetworkFeeIfRequired() - (minimumBalance * 1.1) provideAssetViewModel() } + + private func processDestinationAddress() -> String? { + guard + let chain = selectedDestChainModel, + let destWallet = destWallet, + let accountId = destWallet.fetch(for: chain.accountRequest())?.accountId, + let address = try? AddressFactory.address(for: accountId, chain: chain) + else { + return nil + } + return address + } } // MARK: - CrossChainViewOutput @@ -489,7 +493,6 @@ final class CrossChainPresenter { extension CrossChainPresenter: CrossChainViewOutput { func selectAmountPercentage(_ percentage: Float) { loadingCollector.originFeeReady = false - view?.setButtonLoadingState(isLoading: true) amountInputResult = .rate(Decimal(Double(percentage))) provideAssetViewModel() provideInputViewModel() @@ -498,7 +501,6 @@ extension CrossChainPresenter: CrossChainViewOutput { func updateAmount(_ newValue: Decimal) { loadingCollector.originFeeReady = false - view?.setButtonLoadingState(isLoading: true) amountInputResult = .absolute(newValue) provideAssetViewModel() estimateFee() @@ -509,7 +511,7 @@ extension CrossChainPresenter: CrossChainViewOutput { from: view, wallet: wallet, chainAssets: availableOriginChainAssets, - selectedAssetId: selectedAmountChainAsset.asset.identifier, + selectedAssetId: selectedAmountChainAsset.asset.id, output: self ) } @@ -529,6 +531,7 @@ extension CrossChainPresenter: CrossChainViewOutput { self.view = view interactor.setup(with: self) provideOriginSelectNetworkViewModel() + provideDestSelectNetworkViewModel() provideInputViewModel() } @@ -661,12 +664,6 @@ extension CrossChainPresenter: CrossChainInteractorOutput { availableDestChainModels = filtredChainAssets .map { $0.chain } .withoutDuplicates() - - if selectedDestChainModel == nil { - selectedDestChainModel = filtredChainAssets.map { $0.chain }.first - } - provideDestSelectNetworkViewModel() - estimateFee() } func didSetup() { @@ -812,20 +809,15 @@ extension CrossChainPresenter: ContactsModuleOutput { extension CrossChainPresenter: WalletsManagmentModuleOutput { func selectedWallet(_ wallet: MetaAccountModel, for _: Int) { - guard - let chain = selectedDestChainModel, - let accountId = wallet.fetch(for: chain.accountRequest())?.accountId, - let address = try? AddressFactory.address(for: accountId, chain: chain) - else { + destWallet = wallet + guard let address = processDestinationAddress() else { + let viewModel = viewModelFactory.buildRecipientViewModel(address: wallet.name, isValid: false) + view?.didReceive(recipientViewModel: viewModel) return } - let viewModel = viewModelFactory.buildRecipientViewModel( - address: address, - isValid: true - ) + let viewModel = viewModelFactory.buildRecipientViewModel(address: address, isValid: true) view?.didReceive(recipientViewModel: viewModel) - destWallet = wallet recipientAddress = address loadingCollector.addressExists = true checkLoadingState() diff --git a/fearless/Modules/CrossChain/CrossChainViewController.swift b/fearless/Modules/CrossChain/CrossChainViewController.swift index 241a394fee..ef15b6f1e0 100644 --- a/fearless/Modules/CrossChain/CrossChainViewController.swift +++ b/fearless/Modules/CrossChain/CrossChainViewController.swift @@ -114,7 +114,7 @@ final class CrossChainViewController: UIViewController, ViewHolder, HiddableBarW } private func updatePreviewButton() { - let isEnabled = amountInputViewModel?.isValid == true && rootView.searchView.textField.text.or("").isNotEmpty + let isEnabled = amountInputViewModel?.isValid == true && rootView.searchView.textField.text.or("").isNotEmpty && rootView.searchView.isValid rootView.actionButton.set(enabled: isEnabled) } } @@ -156,7 +156,7 @@ extension CrossChainViewController: CrossChainViewInput { rootView.bind(originalSelectNetworkViewModel: originSelectNetworkViewModel) } - func didReceive(destSelectNetworkViewModel: SelectNetworkViewModel) { + func didReceive(destSelectNetworkViewModel: SelectNetworkViewModel?) { rootView.bind(destSelectNetworkViewModel: destSelectNetworkViewModel) } diff --git a/fearless/Modules/CrossChain/CrossChainViewLayout.swift b/fearless/Modules/CrossChain/CrossChainViewLayout.swift index 3f32396030..9e5a2a0d4d 100644 --- a/fearless/Modules/CrossChain/CrossChainViewLayout.swift +++ b/fearless/Modules/CrossChain/CrossChainViewLayout.swift @@ -93,10 +93,12 @@ final class CrossChainViewLayout: UIView { // MARK: - Public methods func bind(originFeeViewModel: BalanceViewModelProtocol?) { + originNetworkFeeView.isHidden = originFeeViewModel == nil originNetworkFeeView.bindBalance(viewModel: originFeeViewModel) } func bind(destinationFeeViewModel: BalanceViewModelProtocol?) { + destinationNetworkFeeView.isHidden = destinationFeeViewModel == nil destinationNetworkFeeView.bindBalance(viewModel: destinationFeeViewModel) } @@ -113,7 +115,12 @@ final class CrossChainViewLayout: UIView { .loadAmountInputIcon(on: originSelectNetworkView.iconView, animated: true) } - func bind(destSelectNetworkViewModel: SelectNetworkViewModel) { + func bind(destSelectNetworkViewModel: SelectNetworkViewModel?) { + guard let destSelectNetworkViewModel else { + destSelectNetworkView.subtitle = R.string.localizable.commonSelectNetwork(preferredLanguages: locale.rLanguages) + destSelectNetworkView.iconView.image = R.image.addressPlaceholder() + return + } destSelectNetworkView.subtitle = destSelectNetworkViewModel.chainName destSelectNetworkViewModel.iconViewModel?.cancel(on: destSelectNetworkView.iconView) destSelectNetworkView.iconView.image = nil @@ -125,6 +132,7 @@ final class CrossChainViewLayout: UIView { func bind(recipientViewModel: RecipientViewModel) { searchView.textField.text = recipientViewModel.address searchView.updateState(icon: recipientViewModel.icon) + searchView.isValid = recipientViewModel.isValid } // MARK: - Private methods @@ -134,6 +142,9 @@ final class CrossChainViewLayout: UIView { addSubview(contentView) addSubview(actionButton) + originNetworkFeeView.isHidden = true + destinationNetworkFeeView.isHidden = true + actionButton.snp.makeConstraints { make in make.height.equalTo(UIConstants.actionHeight) make.leading.trailing.equalToSuperview().inset(UIConstants.bigOffset) diff --git a/fearless/Modules/CrossChain/Model/CrossChainViewLoadingCollector.swift b/fearless/Modules/CrossChain/Model/CrossChainViewLoadingCollector.swift index ad3f386589..15703aefaf 100644 --- a/fearless/Modules/CrossChain/Model/CrossChainViewLoadingCollector.swift +++ b/fearless/Modules/CrossChain/Model/CrossChainViewLoadingCollector.swift @@ -1,8 +1,8 @@ import Foundation struct CrossChainViewLoadingCollector { - var originFeeReady: Bool = false - var destinationFeeReady: Bool = false + var originFeeReady: Bool? + var destinationFeeReady: Bool? var balanceReady: Bool = false var existentialDepositReady: Bool = false var destinationBalanceReady: Bool = false @@ -21,7 +21,10 @@ struct CrossChainViewLoadingCollector { addressExists = false } - var isReady: Bool { + var isReady: Bool? { + guard let originFeeReady, let destinationFeeReady else { + return nil + } let destinationReady = addressExists ? destinationBalanceReady : true return [ originFeeReady, diff --git a/fearless/Modules/CrossChainConfirmation/CrossChainDepsContainer.swift b/fearless/Modules/CrossChainConfirmation/CrossChainDepsContainer.swift index a0f1ea500b..1e9c2d76db 100644 --- a/fearless/Modules/CrossChainConfirmation/CrossChainDepsContainer.swift +++ b/fearless/Modules/CrossChainConfirmation/CrossChainDepsContainer.swift @@ -89,7 +89,7 @@ final class CrossChainDepsContainer { accountResponse: response ) - let signingWrapperData = XcmAssembly.SigningWrapperData( + let signingWrapperData = SigningWrapperData( publicKeyData: response.publicKey, secretKeyData: secretKeyData ) diff --git a/fearless/Modules/Crowdloan/CustomCrowdloan/Bifrost/BifrostBonusService.swift b/fearless/Modules/Crowdloan/CustomCrowdloan/Bifrost/BifrostBonusService.swift index 52f3f0611f..1bb4d886f0 100644 --- a/fearless/Modules/Crowdloan/CustomCrowdloan/Bifrost/BifrostBonusService.swift +++ b/fearless/Modules/Crowdloan/CustomCrowdloan/Bifrost/BifrostBonusService.swift @@ -2,6 +2,7 @@ import Foundation import RobinHood import SSFUtils import BigInt +import SSFModels final class BifrostBonusService { static let defaultReferralCode = "FRLS69" diff --git a/fearless/Modules/Export/AccountExportPassword/AccountExportPasswordViewController.xib b/fearless/Modules/Export/AccountExportPassword/AccountExportPasswordViewController.xib index c5ee3eeb5d..f4aa026a66 100644 --- a/fearless/Modules/Export/AccountExportPassword/AccountExportPasswordViewController.xib +++ b/fearless/Modules/Export/AccountExportPassword/AccountExportPasswordViewController.xib @@ -1,9 +1,9 @@ - + - + @@ -66,7 +66,7 @@ - + @@ -119,6 +119,10 @@ + + + +