From 1f925c03e32abd3ad57f604a932ef9898732b15a Mon Sep 17 00:00:00 2001 From: matiasbzurovski <164921079+matiasbzurovski@users.noreply.github.com> Date: Thu, 12 Dec 2024 16:25:34 +0100 Subject: [PATCH 01/13] Hotfix for delete account with hidden assets only (#1414) --- Aux/Config/Common.xcconfig | 2 +- .../AccountPortfoliosClient+State.swift | 5 ++++ .../DeleteAccountConfirmation+Reducer.swift | 8 +++--- .../CreateAccountCoordinator+Models.swift | 4 +++ .../CreateAccountCoordinator+Reducer.swift | 27 +++++++++++++++++-- .../OnboardingCoordinator+Reducer.swift | 23 +++------------- 6 files changed, 42 insertions(+), 27 deletions(-) diff --git a/Aux/Config/Common.xcconfig b/Aux/Config/Common.xcconfig index 6a48d0ac1b..fa81b01bb3 100644 --- a/Aux/Config/Common.xcconfig +++ b/Aux/Config/Common.xcconfig @@ -1,7 +1,7 @@ // MARK: - Custom flags /// Application version shared across all targets and flavours -APP_VERSION = 1.11.0 +APP_VERSION = 1.11.1 /// App Icon base name APP_ICON = AppIcon diff --git a/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+State.swift b/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+State.swift index d35d495a95..30f5883b02 100644 --- a/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+State.swift +++ b/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+State.swift @@ -51,6 +51,11 @@ extension AccountPortfoliosClient { return modified } + + /// Returns if the original account (which doesn't remove the hidden resources) contains any asset + var containsAnyAsset: Bool { + originalAccount.containsAnyAsset + } } /// Internal state that holds all loaded portfolios. diff --git a/RadixWallet/Features/AccountPreferencesFeature/Children/DeleteAccount/DeleteAccountConfirmation+Reducer.swift b/RadixWallet/Features/AccountPreferencesFeature/Children/DeleteAccount/DeleteAccountConfirmation+Reducer.swift index fed075409c..0c8746376a 100644 --- a/RadixWallet/Features/AccountPreferencesFeature/Children/DeleteAccount/DeleteAccountConfirmation+Reducer.swift +++ b/RadixWallet/Features/AccountPreferencesFeature/Children/DeleteAccount/DeleteAccountConfirmation+Reducer.swift @@ -16,7 +16,7 @@ struct DeleteAccountConfirmation: Sendable, FeatureReducer { @CasePathable enum InternalAction: Sendable, Equatable { - case fetchAccountPortfolioResult(TaskResult) + case fetchAccountPortfolioResult(TaskResult) case fetchReceivingAccounts case fetchReceivingAccountsResult(TaskResult<[State.ReceivingAccountCandidate]>) } @@ -44,7 +44,7 @@ struct DeleteAccountConfirmation: Sendable, FeatureReducer { state.footerButtonState = .loading(.local) return .run { [address = state.account.address] send in let result = await TaskResult { - try await accountPortfoliosClient.fetchAccountPortfolio(address, true).account + try await accountPortfoliosClient.fetchAccountPortfolio(address, true) } await send(.internal(.fetchAccountPortfolioResult(result))) } @@ -53,9 +53,9 @@ struct DeleteAccountConfirmation: Sendable, FeatureReducer { func reduce(into state: inout State, internalAction: InternalAction) -> Effect { switch internalAction { - case let .fetchAccountPortfolioResult(.success(account)): + case let .fetchAccountPortfolioResult(.success(portfolio)): state.footerButtonState = .enabled - return account.containsAnyAsset ? .send(.internal(.fetchReceivingAccounts)) : .send(.delegate(.deleteAccount)) + return portfolio.containsAnyAsset ? .send(.internal(.fetchReceivingAccounts)) : .send(.delegate(.deleteAccount)) case .fetchReceivingAccounts: return .run { send in diff --git a/RadixWallet/Features/CreateAccount/Coordinator/CreateAccountCoordinator+Models.swift b/RadixWallet/Features/CreateAccount/Coordinator/CreateAccountCoordinator+Models.swift index 4af2d69827..a0ba0d028f 100644 --- a/RadixWallet/Features/CreateAccount/Coordinator/CreateAccountCoordinator+Models.swift +++ b/RadixWallet/Features/CreateAccount/Coordinator/CreateAccountCoordinator+Models.swift @@ -5,15 +5,18 @@ import SwiftUI struct CreateAccountConfig: Sendable, Hashable { let specificNetworkID: NetworkID? let isFirstAccount: Bool + let isNewProfile: Bool let navigationButtonCTA: CreateAccountNavigationButtonCTA fileprivate init( isFirstAccount: Bool, + isNewProfile: Bool = false, navigationButtonCTA: CreateAccountNavigationButtonCTA, specificNetworkID: NetworkID? = nil ) { self.specificNetworkID = specificNetworkID self.isFirstAccount = isFirstAccount + self.isNewProfile = isNewProfile self.navigationButtonCTA = navigationButtonCTA } } @@ -31,6 +34,7 @@ extension CreateAccountConfig { case .firstAccountForNewProfile: self.init( isFirstAccount: true, + isNewProfile: true, navigationButtonCTA: .goHome ) case let .firstAccountOnNewNetwork(specificNetworkID): diff --git a/RadixWallet/Features/CreateAccount/Coordinator/CreateAccountCoordinator+Reducer.swift b/RadixWallet/Features/CreateAccount/Coordinator/CreateAccountCoordinator+Reducer.swift index 19fbb10274..4ebb7629be 100644 --- a/RadixWallet/Features/CreateAccount/Coordinator/CreateAccountCoordinator+Reducer.swift +++ b/RadixWallet/Features/CreateAccount/Coordinator/CreateAccountCoordinator+Reducer.swift @@ -14,6 +14,8 @@ struct CreateAccountCoordinator: Sendable, FeatureReducer { let config: CreateAccountConfig var name: NonEmptyString? + fileprivate var createdProfile = false + init( root: Path.State? = nil, config: CreateAccountConfig @@ -92,6 +94,7 @@ struct CreateAccountCoordinator: Sendable, FeatureReducer { enum InternalAction: Sendable, Equatable { case createAccountResult(TaskResult) case handleAccountCreated(TaskResult) + case handleProfileCreated(factorSourceOption: DerivePublicKeys.State.FactorSourceOption) } enum DelegateAction: Sendable, Equatable { @@ -103,6 +106,7 @@ struct CreateAccountCoordinator: Sendable, FeatureReducer { @Dependency(\.factorSourcesClient) var factorSourcesClient @Dependency(\.accountsClient) var accountsClient @Dependency(\.onLedgerEntitiesClient) var onLedgerEntitiesClient + @Dependency(\.onboardingClient) var onboardingClient @Dependency(\.errorQueue) var errorQueue @Dependency(\.isPresented) var isPresented @Dependency(\.dismiss) var dismiss @@ -146,11 +150,11 @@ extension CreateAccountCoordinator { state.path.append(.selectLedger(.init(context: .createHardwareAccount))) return .none } else { - return derivePublicKey(state: &state, factorSourceOption: .device) + return createProfileIfNecessaryThenDerivePublicKey(state: &state, factorSourceOption: .device) } case let .path(.element(_, action: .selectLedger(.delegate(.choseLedger(ledger))))): - return derivePublicKey( + return createProfileIfNecessaryThenDerivePublicKey( state: &state, factorSourceOption: .specific( ledger.asGeneral @@ -194,6 +198,10 @@ extension CreateAccountCoordinator { config: state.config ))) return .send(.delegate(.accountCreated)) + + case let .handleProfileCreated(factorSourceOption): + state.createdProfile = true + return derivePublicKey(state: &state, factorSourceOption: factorSourceOption) } } @@ -253,6 +261,21 @@ extension CreateAccountCoordinator { } } + private func createProfileIfNecessaryThenDerivePublicKey(state: inout State, factorSourceOption: DerivePublicKeys.State.FactorSourceOption) -> Effect { + if state.config.isNewProfile, !state.createdProfile { + // We need to create the Profile before deriving the public key + .run { send in + try await onboardingClient.createNewProfile() + await send(.internal(.handleProfileCreated(factorSourceOption: factorSourceOption))) + } catch: { error, _ in + errorQueue.schedule(error) + } + } else { + // We can derive the public key since the Profile has been created already + derivePublicKey(state: &state, factorSourceOption: factorSourceOption) + } + } + private func derivePublicKey(state: inout State, factorSourceOption: DerivePublicKeys.State.FactorSourceOption) -> Effect { state.destination = .derivePublicKey( .init( diff --git a/RadixWallet/Features/OnboardingFeature/Coordinator/OnboardingCoordinator+Reducer.swift b/RadixWallet/Features/OnboardingFeature/Coordinator/OnboardingCoordinator+Reducer.swift index 17f2c9fd9c..fe2078d673 100644 --- a/RadixWallet/Features/OnboardingFeature/Coordinator/OnboardingCoordinator+Reducer.swift +++ b/RadixWallet/Features/OnboardingFeature/Coordinator/OnboardingCoordinator+Reducer.swift @@ -14,10 +14,6 @@ struct OnboardingCoordinator: Sendable, FeatureReducer { } } - public enum InternalAction: Sendable, Equatable { - case newProfileCreated - } - @CasePathable enum ChildAction: Sendable, Equatable { case startup(OnboardingStartup.Action) @@ -45,7 +41,6 @@ struct OnboardingCoordinator: Sendable, FeatureReducer { } } - @Dependency(\.onboardingClient) var onboardingClient @Dependency(\.radixConnectClient) var radixConnectClient @Dependency(\.appEventsClient) var appEventsClient @Dependency(\.errorQueue) var errorQueue @@ -65,27 +60,15 @@ struct OnboardingCoordinator: Sendable, FeatureReducer { private let destinationPath: WritableKeyPath> = \.$destination - func reduce(into state: inout State, internalAction: InternalAction) -> Effect { - switch internalAction { - case .newProfileCreated: + func reduce(into state: inout State, childAction: ChildAction) -> Effect { + switch childAction { + case .startup(.delegate(.setupNewUser)): state.destination = .createAccount( .init( config: .init(purpose: .firstAccountForNewProfile) ) ) return .none - } - } - - func reduce(into state: inout State, childAction: ChildAction) -> Effect { - switch childAction { - case .startup(.delegate(.setupNewUser)): - return .run { send in - try await onboardingClient.createNewProfile() - await send(.internal(.newProfileCreated)) - } catch: { error, _ in - errorQueue.schedule(error) - } case .startup(.delegate(.profileCreatedFromImportedBDFS)): appEventsClient.handleEvent(.walletRestored) From c7471aa138efb04c9a49fbcda52c162cfb686bc9 Mon Sep 17 00:00:00 2001 From: Ghenadie <118184705+GhenadieVP@users.noreply.github.com> Date: Thu, 12 Dec 2024 18:41:19 +0200 Subject: [PATCH 02/13] Profle claim fix (#1416) --- RadixWallet.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/swiftpm/Package.resolved | 4 ++-- .../CloudBackupClient/CloudBackupClient+Live.swift | 2 +- RadixWallet/Clients/ProfileStore/ProfileStore.swift | 10 ---------- .../TransactionClientTests.swift | 2 ++ .../SplashFeatureTests/SplashFeatureTests.swift | 5 +++++ 6 files changed, 11 insertions(+), 14 deletions(-) diff --git a/RadixWallet.xcodeproj/project.pbxproj b/RadixWallet.xcodeproj/project.pbxproj index e0b2df18cb..0331b22e3c 100644 --- a/RadixWallet.xcodeproj/project.pbxproj +++ b/RadixWallet.xcodeproj/project.pbxproj @@ -9295,7 +9295,7 @@ repositoryURL = "https://github.com/radixdlt/sargon"; requirement = { kind = exactVersion; - version = 1.1.71; + version = 1.1.83; }; }; /* End XCRemoteSwiftPackageReference section */ diff --git a/RadixWallet.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/RadixWallet.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 89523bfc31..7ee16155da 100644 --- a/RadixWallet.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/RadixWallet.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -114,8 +114,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/radixdlt/sargon", "state" : { - "revision" : "df3c55dc134a9f87848ef0470f1702b304739719", - "version" : "1.1.71" + "revision" : "061ce881fe1d7637dee44f531bbf605672001141", + "version" : "1.1.83" } }, { diff --git a/RadixWallet/Clients/CloudBackupClient/CloudBackupClient+Live.swift b/RadixWallet/Clients/CloudBackupClient/CloudBackupClient+Live.swift index 92e7c49301..a5d38d3f25 100644 --- a/RadixWallet/Clients/CloudBackupClient/CloudBackupClient+Live.swift +++ b/RadixWallet/Clients/CloudBackupClient/CloudBackupClient+Live.swift @@ -174,7 +174,7 @@ extension CloudBackupClient { guard shouldBackUp || timeToCheckIfClaimed else { return } let shouldReclaim: Bool - if let backedUpID = backedUpHeader?.lastUsedOnDevice.id, await !profileStore.isThisDevice(deviceID: backedUpID) { + if let backedUpID = backedUpHeader?.lastUsedOnDevice.id, SargonOS.shared.hostId().id != backedUpID { let action = await overlayWindowClient.scheduleFullScreen(.init(root: .claimWallet(.init()))) switch action { case .claimWallet(.transferBack): diff --git a/RadixWallet/Clients/ProfileStore/ProfileStore.swift b/RadixWallet/Clients/ProfileStore/ProfileStore.swift index 2c778f7b65..df12b5e130 100644 --- a/RadixWallet/Clients/ProfileStore/ProfileStore.swift +++ b/RadixWallet/Clients/ProfileStore/ProfileStore.swift @@ -60,16 +60,6 @@ extension ProfileStore { } } -extension ProfileStore { - func isThisDevice(deviceID: DeviceID) async -> Bool { - guard let hostId = try? await SargonOS.shared.resolveHostId().id else { - return false - } - - return hostId == deviceID - } -} - // MARK: Public extension ProfileStore { /// Mutates the in-memory copy of the Profile usung `transform`, and saves a diff --git a/RadixWalletTests/Clients/TransactionClientTests/TransactionClientTests.swift b/RadixWalletTests/Clients/TransactionClientTests/TransactionClientTests.swift index a39b88f16c..1395e4b66e 100644 --- a/RadixWalletTests/Clients/TransactionClientTests/TransactionClientTests.swift +++ b/RadixWalletTests/Clients/TransactionClientTests/TransactionClientTests.swift @@ -156,6 +156,8 @@ final class TransactionClientTests: TestCase { ) }))!] } + $0.secureStorageClient.saveDeviceInfo = { _ in } + $0.secureStorageClient.loadDeviceInfo = { nil } } operation: { try await TransactionClient.feePayerSelectionAmongstCandidates( request: .init( diff --git a/RadixWalletTests/Features/SplashFeatureTests/SplashFeatureTests.swift b/RadixWalletTests/Features/SplashFeatureTests/SplashFeatureTests.swift index c49119156d..74c304d615 100644 --- a/RadixWalletTests/Features/SplashFeatureTests/SplashFeatureTests.swift +++ b/RadixWalletTests/Features/SplashFeatureTests/SplashFeatureTests.swift @@ -30,6 +30,8 @@ final class SplashFeatureTests: TestCase { return .loaded(profile) } $0.userDefaults = userDefaults + $0.secureStorageClient.saveDeviceInfo = { _ in } + $0.secureStorageClient.loadDeviceInfo = { nil } } // when @@ -99,6 +101,9 @@ final class SplashFeatureTests: TestCase { $0.secureStorageClient.loadProfileSnapshotData = { _ in profile.jsonData() } + $0.secureStorageClient.saveDeviceInfo = { _ in } + $0.secureStorageClient.loadDeviceInfo = { nil } + $0.secureStorageClient.deprecatedLoadDeviceID = { nil } } // when From 08b354f254f76cc2d8adb7e75bf466a134e1a521 Mon Sep 17 00:00:00 2001 From: Ghenadie <118184705+GhenadieVP@users.noreply.github.com> Date: Fri, 13 Dec 2024 18:38:44 +0200 Subject: [PATCH 03/13] Fix profile claim after import (#1419) --- .../TransportProfileClient/TransportProfileClient+Live.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/RadixWallet/Clients/TransportProfileClient/TransportProfileClient+Live.swift b/RadixWallet/Clients/TransportProfileClient/TransportProfileClient+Live.swift index 4383b19933..d6e51e8d1a 100644 --- a/RadixWallet/Clients/TransportProfileClient/TransportProfileClient+Live.swift +++ b/RadixWallet/Clients/TransportProfileClient/TransportProfileClient+Live.swift @@ -12,10 +12,11 @@ extension TransportProfileClient: DependencyKey { return Self( importProfile: { profile, factorSourceIDs, skippedMainBdfs, containsP2PLinks in do { + try await profileStore.importProfile(profile, skippedMainBdfs: skippedMainBdfs) + let profile = await profileStore.profile() if profile.appPreferences.security.isCloudProfileSyncEnabled { try? await cloudBackupClient.claimProfileOnICloud(profile) } - try await profileStore.importProfile(profile, skippedMainBdfs: skippedMainBdfs) userDefaults.setShowRelinkConnectorsAfterProfileRestore(containsP2PLinks) } catch { // Revert the saved mnemonic From d43450cbb1552a930329fa8800ba681524afbb1b Mon Sep 17 00:00:00 2001 From: Ghenadie <118184705+GhenadieVP@users.noreply.github.com> Date: Tue, 17 Dec 2024 17:46:19 +0200 Subject: [PATCH 04/13] GeneralSubintent manifest class (#1422) --- Aux/Config/Common.xcconfig | 2 +- RadixWallet.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/swiftpm/Package.resolved | 4 ++-- .../Sections/Sections+ManifestSummary.swift | 5 +++++ RadixWallet/Features/SplashFeature/Splash.swift | 1 + RadixWallet/SargonExtensions/SargonSecureStorageDriver.swift | 4 ++++ 6 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Aux/Config/Common.xcconfig b/Aux/Config/Common.xcconfig index fa81b01bb3..4160d30bd9 100644 --- a/Aux/Config/Common.xcconfig +++ b/Aux/Config/Common.xcconfig @@ -1,7 +1,7 @@ // MARK: - Custom flags /// Application version shared across all targets and flavours -APP_VERSION = 1.11.1 +APP_VERSION = 1.11.2 /// App Icon base name APP_ICON = AppIcon diff --git a/RadixWallet.xcodeproj/project.pbxproj b/RadixWallet.xcodeproj/project.pbxproj index 0331b22e3c..847f16bc21 100644 --- a/RadixWallet.xcodeproj/project.pbxproj +++ b/RadixWallet.xcodeproj/project.pbxproj @@ -9295,7 +9295,7 @@ repositoryURL = "https://github.com/radixdlt/sargon"; requirement = { kind = exactVersion; - version = 1.1.83; + version = 1.1.86; }; }; /* End XCRemoteSwiftPackageReference section */ diff --git a/RadixWallet.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/RadixWallet.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 7ee16155da..810dd31921 100644 --- a/RadixWallet.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/RadixWallet.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -114,8 +114,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/radixdlt/sargon", "state" : { - "revision" : "061ce881fe1d7637dee44f531bbf605672001141", - "version" : "1.1.83" + "revision" : "750d49a106a6bf359bfed3bc76d1c81a963c7bf5", + "version" : "1.1.86" } }, { diff --git a/RadixWallet/Features/InteractionReview/Sections/Sections+ManifestSummary.swift b/RadixWallet/Features/InteractionReview/Sections/Sections+ManifestSummary.swift index 164e0ebb2d..6489f6a75c 100644 --- a/RadixWallet/Features/InteractionReview/Sections/Sections+ManifestSummary.swift +++ b/RadixWallet/Features/InteractionReview/Sections/Sections+ManifestSummary.swift @@ -2,6 +2,11 @@ import Sargon extension InteractionReview.Sections { func sections(for summary: ManifestSummary, networkID: NetworkID) async throws -> Common.SectionsData? { + /// Only GeneralSubintent classification is allowed for PreAuth transactions + guard summary.classification.first == .generalSubintent else { + return nil + } + let allWithdrawAddresses = summary.accountWithdrawals.values.flatMap { $0 }.map(\.resourceAddress) let allDepositAddresses = summary.accountDeposits.values.flatMap(\.specifiedResources).map(\.resourceAddress) diff --git a/RadixWallet/Features/SplashFeature/Splash.swift b/RadixWallet/Features/SplashFeature/Splash.swift index a9ed75041b..ba4fe2dab7 100644 --- a/RadixWallet/Features/SplashFeature/Splash.swift +++ b/RadixWallet/Features/SplashFeature/Splash.swift @@ -218,6 +218,7 @@ struct Splash: Sendable, FeatureReducer { drivers: .init( bundle: Bundle.main, userDefaultsSuite: UserDefaults.Dependency.radixSuiteName, + unsafeStorageKeyMapping: [:], secureStorageDriver: SargonSecureStorage() ) ) diff --git a/RadixWallet/SargonExtensions/SargonSecureStorageDriver.swift b/RadixWallet/SargonExtensions/SargonSecureStorageDriver.swift index f3064b96cd..3041abd894 100644 --- a/RadixWallet/SargonExtensions/SargonSecureStorageDriver.swift +++ b/RadixWallet/SargonExtensions/SargonSecureStorageDriver.swift @@ -61,6 +61,10 @@ final class SargonSecureStorage: SecureStorageDriver { } } + func containsDataForKey(key: SecureStorageKey) async throws -> Bool { + false + } + private func loadHostId() -> BagOfBytes? { let deviceInfo: DeviceInfo? = { if let existing = try? secureStorageClient.loadDeviceInfo() { From 27d311eaa6475876175f7f790b8072ccfd7eead8 Mon Sep 17 00:00:00 2001 From: Ghenadie <118184705+GhenadieVP@users.noreply.github.com> Date: Tue, 24 Dec 2024 12:01:41 +0200 Subject: [PATCH 05/13] 1.11.3 hotfix (#1428) --- Aux/Config/Common.xcconfig | 2 +- RadixWallet.xcodeproj/project.pbxproj | 33 +++++++--- .../xcshareddata/swiftpm/Package.resolved | 6 +- .../DeviceFactorSourceClient+Interface.swift | 14 +---- .../FactorSourcesClient+Live.swift | 7 +-- .../OnLedgerEntitiesClient+CreateEntity.swift | 2 +- .../PreAuthorizationClient+Live.swift | 2 +- .../TransactionClient+Live.swift | 18 ++++-- .../SharedModels/Assets/ResourceAmount.swift | 17 ++++++ .../ResourceBalance/ResourceBalance.swift | 6 +- .../ClaimWallet/ClaimWallet+Reducer.swift | 60 ++++++++++++++++++- .../ClaimWallet/ClaimWallet+View.swift | 34 +++++++++-- .../Coordinator/DappInteractionFlow.swift | 13 +--- .../InspectProfile+View.swift | 7 --- .../PreAuthorizationReview.swift | 12 ++-- .../TransactionReview.swift | 7 +++ .../TestExtensions/TestUtils.swift | 2 +- 17 files changed, 168 insertions(+), 74 deletions(-) diff --git a/Aux/Config/Common.xcconfig b/Aux/Config/Common.xcconfig index 4160d30bd9..7e043cc4b3 100644 --- a/Aux/Config/Common.xcconfig +++ b/Aux/Config/Common.xcconfig @@ -1,7 +1,7 @@ // MARK: - Custom flags /// Application version shared across all targets and flavours -APP_VERSION = 1.11.2 +APP_VERSION = 1.11.3 /// App Icon base name APP_ICON = AppIcon diff --git a/RadixWallet.xcodeproj/project.pbxproj b/RadixWallet.xcodeproj/project.pbxproj index 847f16bc21..d2dffeebf1 100644 --- a/RadixWallet.xcodeproj/project.pbxproj +++ b/RadixWallet.xcodeproj/project.pbxproj @@ -828,6 +828,7 @@ 83377A052B9DDB5C00D8AA36 /* NPSSurveyClient+Live.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83377A042B9DDB5C00D8AA36 /* NPSSurveyClient+Live.swift */; }; 8338B9E52AFAB20700D1D8EA /* TransactionFee.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8338B9E42AFAB20700D1D8EA /* TransactionFee.swift */; }; 834B651F2B972E5100B7E1E8 /* NPSSurvey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 834B651E2B972E5100B7E1E8 /* NPSSurvey.swift */; }; + 835DFF932D19855A00229DB0 /* Sargon in Frameworks */ = {isa = PBXBuildFile; productRef = 835DFF922D19855A00229DB0 /* Sargon */; }; 835F196D2B3581C300E0B71D /* UnknownDappComponents+View.swift in Sources */ = {isa = PBXBuildFile; fileRef = 835F196C2B3581C300E0B71D /* UnknownDappComponents+View.swift */; }; 8370FC5C2B99C780007AD882 /* NPSSurveyClient+Interface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8370FC5B2B99C780007AD882 /* NPSSurveyClient+Interface.swift */; }; 8381C8B02BBD2CD400A470B4 /* TokenPriceCientTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8381C8AF2BBD2CD400A470B4 /* TokenPriceCientTests.swift */; }; @@ -843,6 +844,7 @@ 839B6C542B21D28400402651 /* ExpandableTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 839B6C532B21D28400402651 /* ExpandableTextView.swift */; }; 83AAAC6D2B483D1B00222B64 /* StakeSummaryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83AAAC6B2B483D1B00222B64 /* StakeSummaryView.swift */; }; 83B783562C1764AE00AA7930 /* Sargon in Frameworks */ = {isa = PBXBuildFile; productRef = 83B783552C1764AE00AA7930 /* Sargon */; }; + 83D3F3C32D15C9CA00CA976D /* Sargon in Frameworks */ = {isa = PBXBuildFile; productRef = 83D3F3C22D15C9CA00CA976D /* Sargon */; }; 83D663B02B271D0100D1AB9E /* TruncationMask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83D663AF2B271D0100D1AB9E /* TruncationMask.swift */; }; 83D908AD2C931A7100822CC4 /* SargonSecureStorageDriver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83D908AC2C931A7100822CC4 /* SargonSecureStorageDriver.swift */; }; 83DFAF2E2B4E8A51008B70CE /* View+Extra.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83DFAF2D2B4E8A51008B70CE /* View+Extra.swift */; }; @@ -2568,6 +2570,7 @@ 48FFFAAB2ADC1FE900B2B213 /* DependenciesAdditions in Frameworks */, 48FFFAA22ADC1F5D00B2B213 /* Algorithms in Frameworks */, 48FFFAC12ADC20C400B2B213 /* JSONPreview in Frameworks */, + 83D3F3C32D15C9CA00CA976D /* Sargon in Frameworks */, 48FFFADB2ADC21E400B2B213 /* SwiftLogConsoleColors in Frameworks */, 48FFFADE2ADC21F500B2B213 /* FileLogging in Frameworks */, 48FFFACF2ADC216400B2B213 /* CollectionConcurrencyKit in Frameworks */, @@ -2585,6 +2588,7 @@ 5B1C4FD52BBB0B0C00B9436F /* AppsFlyerLib-Strict in Frameworks */, 48FFFB032ADC6F8100B2B213 /* Builders in Frameworks */, 48FFFAB72ADC207B00B2B213 /* NavigationTransitions in Frameworks */, + 835DFF932D19855A00229DB0 /* Sargon in Frameworks */, 5B634A942C91D2A0004B2FBC /* ScreenshotPreventing in Frameworks */, 48FFFA992ADC1EEC00B2B213 /* AsyncExtensions in Frameworks */, 83B783562C1764AE00AA7930 /* Sargon in Frameworks */, @@ -7107,6 +7111,8 @@ 5B634A932C91D2A0004B2FBC /* ScreenshotPreventing */, 5B447E0A2CAAFC2D0063AE39 /* Sargon */, 5B4E1D1E2CB7FE8E002FAC2E /* Sargon */, + 83D3F3C22D15C9CA00CA976D /* Sargon */, + 835DFF922D19855A00229DB0 /* Sargon */, ); productName = RadixWallet; productReference = 48CFBC4F2ADC106300E77A5C /* Radix Wallet Dev.app */; @@ -7177,7 +7183,7 @@ 8318BB172BC8403800057BCB /* XCRemoteSwiftPackageReference "swift-custom-dump" */, E6A0B0492BF23C7000617DAC /* XCRemoteSwiftPackageReference "swift-identified-collections" */, 5B634A922C91D2A0004B2FBC /* XCRemoteSwiftPackageReference "ScreenshotPreventing-iOS" */, - E775A1BC2CFA04B100E72DB9 /* XCRemoteSwiftPackageReference "sargon" */, + 835DFF912D19855A00229DB0 /* XCRemoteSwiftPackageReference "sargon" */, ); productRefGroup = 48CFBC502ADC106300E77A5C /* Products */; projectDirPath = ""; @@ -9266,6 +9272,14 @@ version = 1.3.0; }; }; + 835DFF912D19855A00229DB0 /* XCRemoteSwiftPackageReference "sargon" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/radixdlt/sargon"; + requirement = { + kind = exactVersion; + version = 1.1.96; + }; + }; A415574E2B757C5E0040AD4E /* XCRemoteSwiftPackageReference "swift-composable-architecture" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/pointfreeco/swift-composable-architecture"; @@ -9290,14 +9304,6 @@ version = 1.0.2; }; }; - E775A1BC2CFA04B100E72DB9 /* XCRemoteSwiftPackageReference "sargon" */ = { - isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/radixdlt/sargon"; - requirement = { - kind = exactVersion; - version = 1.1.86; - }; - }; /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ @@ -9506,10 +9512,19 @@ isa = XCSwiftPackageProductDependency; productName = Sargon; }; + 835DFF922D19855A00229DB0 /* Sargon */ = { + isa = XCSwiftPackageProductDependency; + package = 835DFF912D19855A00229DB0 /* XCRemoteSwiftPackageReference "sargon" */; + productName = Sargon; + }; 83B783552C1764AE00AA7930 /* Sargon */ = { isa = XCSwiftPackageProductDependency; productName = Sargon; }; + 83D3F3C22D15C9CA00CA976D /* Sargon */ = { + isa = XCSwiftPackageProductDependency; + productName = Sargon; + }; A415574F2B757C5E0040AD4E /* ComposableArchitecture */ = { isa = XCSwiftPackageProductDependency; package = A415574E2B757C5E0040AD4E /* XCRemoteSwiftPackageReference "swift-composable-architecture" */; diff --git a/RadixWallet.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/RadixWallet.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 810dd31921..c18d9683e2 100644 --- a/RadixWallet.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/RadixWallet.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "7d3590b225945abb1bc0ab6c684b005c28c64bdc204afcc2d34c3e379ef8a3c8", + "originHash" : "4eb650ade57061cd1cf989ce8f615547774e9303f591ff57a76f3f2c04cdbd07", "pins" : [ { "identity" : "anycodable", @@ -114,8 +114,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/radixdlt/sargon", "state" : { - "revision" : "750d49a106a6bf359bfed3bc76d1c81a963c7bf5", - "version" : "1.1.86" + "revision" : "2f610dafec01e66542d6902f02aeffda83dbc7cd", + "version" : "1.1.96" } }, { diff --git a/RadixWallet/Clients/DeviceFactorSourceClient/DeviceFactorSourceClient+Interface.swift b/RadixWallet/Clients/DeviceFactorSourceClient/DeviceFactorSourceClient+Interface.swift index 830a921e5b..758f4cadfa 100644 --- a/RadixWallet/Clients/DeviceFactorSourceClient/DeviceFactorSourceClient+Interface.swift +++ b/RadixWallet/Clients/DeviceFactorSourceClient/DeviceFactorSourceClient+Interface.swift @@ -128,12 +128,7 @@ extension DeviceFactorSourceClient { switch signerEntity.securityState { case let .unsecured(control): - let factorInstance = switch purpose { - case .signAuth: - control.authenticationSigning ?? control.transactionSigning - case .signTransaction, .signPreAuthorization: - control.transactionSigning - } + let factorInstance = control.transactionSigning guard let deviceFactorSource = try await factorSourcesClient.getDeviceFactorSource(of: factorInstance) @@ -180,12 +175,7 @@ extension DeviceFactorSourceClient { switch entity.securityState { case let .unsecured(unsecuredControl): - let factorInstance = switch purpose { - case .signAuth: - unsecuredControl.authenticationSigning ?? unsecuredControl.transactionSigning - case .signTransaction, .signPreAuthorization: - unsecuredControl.transactionSigning - } + let factorInstance = unsecuredControl.transactionSigning let derivationPath = factorInstance.derivationPath diff --git a/RadixWallet/Clients/FactorSourcesClient/FactorSourcesClient+Live.swift b/RadixWallet/Clients/FactorSourcesClient/FactorSourcesClient+Live.swift index 3207f1bba9..d0296e90b9 100644 --- a/RadixWallet/Clients/FactorSourcesClient/FactorSourcesClient+Live.swift +++ b/RadixWallet/Clients/FactorSourcesClient/FactorSourcesClient+Live.swift @@ -370,12 +370,7 @@ func signingFactors( switch entity.securityState { case let .unsecured(unsecuredEntityControl): - let factorInstance = switch signingPurpose { - case .signAuth: - unsecuredEntityControl.authenticationSigning ?? unsecuredEntityControl.transactionSigning - case .signTransaction, .signPreAuthorization: - unsecuredEntityControl.transactionSigning - } + let factorInstance = unsecuredEntityControl.transactionSigning let id = factorInstance.factorSourceID guard let factorSource = allFactorSources[id: id.asGeneral] else { diff --git a/RadixWallet/Clients/OnLedgerEntitiesClient/Helpers/OnLedgerEntitiesClient+CreateEntity.swift b/RadixWallet/Clients/OnLedgerEntitiesClient/Helpers/OnLedgerEntitiesClient+CreateEntity.swift index 95a36f7860..c67b8e76de 100644 --- a/RadixWallet/Clients/OnLedgerEntitiesClient/Helpers/OnLedgerEntitiesClient+CreateEntity.swift +++ b/RadixWallet/Clients/OnLedgerEntitiesClient/Helpers/OnLedgerEntitiesClient+CreateEntity.swift @@ -562,7 +562,7 @@ extension OnLedgerEntitiesClient { struct OwnedResourcePoolDetails: Hashable, Sendable { let address: PoolAddress let dAppName: String? - let poolUnitResource: ResourceWithVaultAmount + var poolUnitResource: ResourceWithVaultAmount var xrdResource: ResourceWithRedemptionValue? var nonXrdResources: [ResourceWithRedemptionValue] diff --git a/RadixWallet/Clients/PreAuthorizationClient/PreAuthorizationClient+Live.swift b/RadixWallet/Clients/PreAuthorizationClient/PreAuthorizationClient+Live.swift index 26695f55c6..b3e44d90fb 100644 --- a/RadixWallet/Clients/PreAuthorizationClient/PreAuthorizationClient+Live.swift +++ b/RadixWallet/Clients/PreAuthorizationClient/PreAuthorizationClient+Live.swift @@ -16,7 +16,7 @@ extension PreAuthorizationClient: DependencyKey { notaryPublicKey: Sargon.PublicKey.ed25519(request.notaryPublicKey.intoSargon()) ) } catch { - throw PreAuthorizationFailure.failedToGetPreview(.failedToAnalyse(error)) + throw TransactionFailure.fromCommonError(error as? CommonError) } } diff --git a/RadixWallet/Clients/TransactionClient/TransactionClient+Live.swift b/RadixWallet/Clients/TransactionClient/TransactionClient+Live.swift index 74e83326e9..dbd737c9b3 100644 --- a/RadixWallet/Clients/TransactionClient/TransactionClient+Live.swift +++ b/RadixWallet/Clients/TransactionClient/TransactionClient+Live.swift @@ -368,12 +368,20 @@ extension TransactionFailure { case .FailedToExtractTransactionReceiptBytes: .failedToPrepareTXReview(.failedToExtractTXReceiptBytes) + case let .ExecutionSummaryFail(underlying): + .failedToPrepareTXReview(.failedTXPreview(underlying)) + + case let .FailedToGenerateManifestSummary(underlying): + .failedToPrepareTXReview(.failedTXPreview(underlying)) + + case let .InvalidInstructionsString(underlying): + .failedToPrepareTXReview(.failedTXPreview(underlying)) + + case let .some(err): + .failedToPrepareTXReview(.failedTXPreview(errorMessageFromError(error: err))) + default: - if let code = commonError?.errorCode { - .failedToPrepareTXReview(.failedTXPreview("Unknown reason, code: \(code)")) - } else { - .failedToPrepareTXReview(.failedTXPreview("Unknown reason")) - } + .failedToPrepareTXReview(.failedTXPreview("Unknown reason")) } } } diff --git a/RadixWallet/Core/SharedModels/Assets/ResourceAmount.swift b/RadixWallet/Core/SharedModels/Assets/ResourceAmount.swift index 00042e8146..2507f60b1f 100644 --- a/RadixWallet/Core/SharedModels/Assets/ResourceAmount.swift +++ b/RadixWallet/Core/SharedModels/Assets/ResourceAmount.swift @@ -59,6 +59,15 @@ extension ResourceAmount { } } + var guaranteedAmount: ExactResourceAmount? { + switch self { + case let .predicted(_, amount): + amount + default: + nil + } + } + func adjustedNominalAmount(_ adjust: (Decimal192) -> Decimal192) -> Self { switch self { case let .exact(amount): @@ -85,6 +94,14 @@ extension ResourceAmount { return .unknown } } + + mutating func setGuaranteedAmount(_ newGuaranteed: Decimal192) { + guard case let .predicted(predicted, _) = self else { + return + } + + self = .predicted(predicted: predicted, guaranteed: .init(nominalAmount: newGuaranteed)) + } } // MARK: CustomDebugStringConvertible diff --git a/RadixWallet/Features/AssetsFeature/Components/HelperViews/ResourceBalance/ResourceBalance.swift b/RadixWallet/Features/AssetsFeature/Components/HelperViews/ResourceBalance/ResourceBalance.swift index 14c322b7fd..434e19fa15 100644 --- a/RadixWallet/Features/AssetsFeature/Components/HelperViews/ResourceBalance/ResourceBalance.swift +++ b/RadixWallet/Features/AssetsFeature/Components/HelperViews/ResourceBalance/ResourceBalance.swift @@ -81,13 +81,13 @@ struct KnownResourceBalance: Sendable, Hashable { struct Fungible: Sendable, Hashable { let isXRD: Bool - let amount: ResourceAmount + var amount: ResourceAmount var guarantee: TransactionGuarantee? } struct LiquidStakeUnit: Sendable, Hashable { let resource: OnLedgerEntity.Resource - let amount: ResourceAmount + var amount: ResourceAmount let worth: ResourceAmount let validator: OnLedgerEntity.Validator var guarantee: TransactionGuarantee? @@ -109,7 +109,7 @@ struct KnownResourceBalance: Sendable, Hashable { } struct PoolUnit: Sendable, Hashable { - let details: OnLedgerEntitiesClient.OwnedResourcePoolDetails + var details: OnLedgerEntitiesClient.OwnedResourcePoolDetails var guarantee: TransactionGuarantee? } diff --git a/RadixWallet/Features/ClaimWallet/ClaimWallet+Reducer.swift b/RadixWallet/Features/ClaimWallet/ClaimWallet+Reducer.swift index a865ee2c19..e14cabb5ea 100644 --- a/RadixWallet/Features/ClaimWallet/ClaimWallet+Reducer.swift +++ b/RadixWallet/Features/ClaimWallet/ClaimWallet+Reducer.swift @@ -1,6 +1,7 @@ import ComposableArchitecture import SwiftUI +// MARK: - ClaimWallet @Reducer struct ClaimWallet: Sendable, FeatureReducer { @ObservableState @@ -10,6 +11,9 @@ struct ClaimWallet: Sendable, FeatureReducer { isLoading ? .loading(.global(text: nil)) : .enabled } + @Presents + var destination: Destination.State? = nil + init() {} } @@ -26,24 +30,74 @@ struct ClaimWallet: Sendable, FeatureReducer { case transferBack } + struct Destination: DestinationReducer { + @CasePathable + enum State: Sendable, Hashable { + case confirmReset(AlertState) + } + + @CasePathable + enum Action: Sendable, Hashable { + case confirmReset(ConfirmReset) + + enum ConfirmReset: Sendable, Hashable { + case confirm + } + } + + var body: some Reducer { + EmptyReducer() + } + } + @Dependency(\.resetWalletClient) var resetWalletClient init() {} - var body: some ReducerOf { + var body: some ReducerOf { Reduce(core) + .ifLet(destinationPath, action: /Action.destination) { + Destination() + } } + private let destinationPath: WritableKeyPath> = \.$destination + func reduce(into state: inout State, viewAction: ViewAction) -> Effect { switch viewAction { case .clearWalletButtonTapped: + state.destination = Destination.confirmResetState + return .none + + case .transferBackButtonTapped: + return .send(.delegate(.transferBack)) + } + } + + func reduce(into state: inout State, presentedAction: Destination.Action) -> Effect { + switch presentedAction { + case .confirmReset(.confirm): state.isLoading = true return .run { send in await resetWalletClient.resetWallet() await send(.delegate(.didClearWallet)) } - case .transferBackButtonTapped: - return .send(.delegate(.transferBack)) } } } + +extension ClaimWallet.Destination { + static let confirmResetState: State = .confirmReset(.init( + title: { + TextState(L10n.FactoryReset.Dialog.title) + }, + actions: { + ButtonState(role: .destructive, action: .confirm) { + TextState(L10n.Common.confirm) + } + }, + message: { + TextState(L10n.FactoryReset.Dialog.message) + } + )) +} diff --git a/RadixWallet/Features/ClaimWallet/ClaimWallet+View.swift b/RadixWallet/Features/ClaimWallet/ClaimWallet+View.swift index d26e85bfd4..2a95a84db8 100644 --- a/RadixWallet/Features/ClaimWallet/ClaimWallet+View.swift +++ b/RadixWallet/Features/ClaimWallet/ClaimWallet+View.swift @@ -29,20 +29,20 @@ extension ClaimWallet { .foregroundColor(.app.gray2) .textStyle(.secondaryHeader) .multilineTextAlignment(.center) - .padding(.bottom, .medium1) + .padding(.bottom, .small1) Text(L10n.ConfigurationBackup.Automated.walletTransferredExplanation1 + "\n\n" + L10n.ConfigurationBackup.Automated.walletTransferredExplanation2) .textStyle(.body1Regular) .multilineTextAlignment(.center) + .padding(.bottom, .small1) Spacer() - VStack { - Button(L10n.ConfigurationBackup.Automated.walletTransferredClearButton) { + VStack(spacing: .medium1) { + Button(L10n.FactoryReset.resetWallet) { store.send(.view(.clearWalletButtonTapped)) } - .buttonStyle(.primaryRectangular) - .padding(.bottom, .small2) + .buttonStyle(.primaryRectangular(isDestructive: true)) Button(L10n.ConfigurationBackup.Automated.walletTransferredTransferBackButton) { store.send(.view(.transferBackButtonTapped)) @@ -50,10 +50,32 @@ extension ClaimWallet { .buttonStyle(.primaryText()) } } - .padding(.horizontal, .large1) + .padding(.horizontal, .medium3) .padding(.vertical, .medium3) .controlState(store.screenState) } + .destinations(with: store) + } + } +} + +private extension StoreOf { + var destination: PresentationStoreOf { + func scopeState(state: State) -> PresentationState { + state.$destination } + return scope(state: scopeState, action: Action.destination) + } +} + +@MainActor +private extension View { + func destinations(with store: StoreOf) -> some View { + let destination = store.destination + return confirmReset(with: destination) + } + + private func confirmReset(with destinationStore: PresentationStoreOf) -> some View { + alert(store: destinationStore.scope(state: \.confirmReset, action: \.confirmReset)) } } diff --git a/RadixWallet/Features/DappInteractionFeature/Coordinator/DappInteractionFlow.swift b/RadixWallet/Features/DappInteractionFeature/Coordinator/DappInteractionFlow.swift index 97907c07c0..499608077b 100644 --- a/RadixWallet/Features/DappInteractionFeature/Coordinator/DappInteractionFlow.swift +++ b/RadixWallet/Features/DappInteractionFeature/Coordinator/DappInteractionFlow.swift @@ -440,7 +440,7 @@ extension DappInteractionFlow { return continueEffect(for: &state) } - func handleSignAndSubmitTXFailed( + func handleTransactionFailure( _ error: TransactionFailure ) -> Effect { let (errorKind, message) = error.errorKindAndMessage @@ -520,13 +520,6 @@ extension DappInteractionFlow { return continueEffect(for: &state) } - func handlePreAuthorizationFailure( - _ error: PreAuthorizationFailure - ) -> Effect { - let (errorKind, message) = error.errorKindAndMessage - return dismissEffect(for: state, errorKind: errorKind, message: message) - } - let item = state.currentItem guard let action = childAction.action else { return .none } @@ -571,7 +564,7 @@ extension DappInteractionFlow { return .send(.delegate(.dismiss)) case let .reviewTransaction(.delegate(.failed(error))): - return handleSignAndSubmitTXFailed(error) + return handleTransactionFailure(error) case let .personaProofOfOwnership(.delegate(.provenPersonaOwnership(persona, challenge))): return handlePersonaProofOfOwnership(item, persona, challenge) @@ -591,7 +584,7 @@ extension DappInteractionFlow { return handlePreAuthorizationSignature(item, encoded) case let .preAuthorizationReview(.delegate(.failed(error))): - return handlePreAuthorizationFailure(error) + return handleTransactionFailure(error) default: return .none diff --git a/RadixWallet/Features/DebugInspectProfile/InspectProfile+View.swift b/RadixWallet/Features/DebugInspectProfile/InspectProfile+View.swift index a85414fa26..923de6c3ae 100644 --- a/RadixWallet/Features/DebugInspectProfile/InspectProfile+View.swift +++ b/RadixWallet/Features/DebugInspectProfile/InspectProfile+View.swift @@ -657,13 +657,6 @@ extension UnsecuredEntityControlView { factorInstance: unsecuredControl.transactionSigning, indentation: inOneLevel ) - if let authenticationSigning = unsecuredControl.authenticationSigning { - HierarchicalDeterministicFactorInstanceView( - description: "Auth Signing", - factorInstance: authenticationSigning, - indentation: inOneLevel - ) - } } } } diff --git a/RadixWallet/Features/PreAuthorizationReview/PreAuthorizationReview.swift b/RadixWallet/Features/PreAuthorizationReview/PreAuthorizationReview.swift index 7edba2fef9..da5f73f011 100644 --- a/RadixWallet/Features/PreAuthorizationReview/PreAuthorizationReview.swift +++ b/RadixWallet/Features/PreAuthorizationReview/PreAuthorizationReview.swift @@ -45,7 +45,7 @@ struct PreAuthorizationReview: Sendable, FeatureReducer { enum DelegateAction: Sendable, Equatable { case signedPreAuthorization(SignedSubintent) - case failed(PreAuthorizationFailure) + case failed(TransactionFailure) } struct Destination: DestinationReducer { @@ -117,12 +117,12 @@ struct PreAuthorizationReview: Sendable, FeatureReducer { switch internalAction { case let .previewLoaded(.failure(error)): loggerGlobal.error("PreAuthroization preview failed, error: \(error)") - errorQueue.schedule(error) - guard let failure = error as? PreAuthorizationFailure else { - assertionFailure("Failed with unexpected error \(error)") - return .none + errorQueue.schedule(TransactionReviewFailure(underylying: error)) + if let txFailure = error as? TransactionFailure { + return .send(.delegate(.failed(txFailure))) + } else { + return .send(.delegate(.failed(TransactionFailure.failedToPrepareTXReview(.abortedTXReview(error))))) } - return .send(.delegate(.failed(failure))) case let .previewLoaded(.success(preview)): state.preview = preview diff --git a/RadixWallet/Features/TransactionReviewFeature/TransactionReview.swift b/RadixWallet/Features/TransactionReviewFeature/TransactionReview.swift index ce4076df6f..ce1f7e5d5c 100644 --- a/RadixWallet/Features/TransactionReviewFeature/TransactionReview.swift +++ b/RadixWallet/Features/TransactionReviewFeature/TransactionReview.swift @@ -599,21 +599,28 @@ extension ResourceBalance { } } set { + guard let newValue else { + return + } + switch self { case let .known(knownResourceBalance): switch knownResourceBalance.details { case var .fungible(fungible): fungible.guarantee = newValue + fungible.amount.setGuaranteedAmount(newValue.amount) var known = knownResourceBalance known.details = .fungible(fungible) self = .known(known) case var .liquidStakeUnit(liquidStakeUnit): liquidStakeUnit.guarantee = newValue + liquidStakeUnit.amount.setGuaranteedAmount(newValue.amount) var known = knownResourceBalance known.details = .liquidStakeUnit(liquidStakeUnit) self = .known(known) case var .poolUnit(poolUnit): poolUnit.guarantee = newValue + poolUnit.details.poolUnitResource.amount.setGuaranteedAmount(newValue.amount) var known = knownResourceBalance known.details = .poolUnit(poolUnit) self = .known(known) diff --git a/RadixWalletTests/TestExtensions/TestUtils.swift b/RadixWalletTests/TestExtensions/TestUtils.swift index e565c65dbd..5c9cca2511 100644 --- a/RadixWalletTests/TestExtensions/TestUtils.swift +++ b/RadixWalletTests/TestExtensions/TestUtils.swift @@ -77,7 +77,7 @@ extension Profile { factorSourceId: privateHDFactorSource.factorSource.id, publicKey: .sample ), - authenticationSigning: nil + provisionalSecurifiedConfig: nil ) ) From 85e937309d9d2d24212babc8c202a687aee12ac6 Mon Sep 17 00:00:00 2001 From: Ghenadie Vasiliev-Pusca Date: Wed, 8 Jan 2025 10:30:15 +0200 Subject: [PATCH 06/13] Fix create new account --- .../Clients/ProfileStore/ProfileStore.swift | 1 + .../CreateAccountCoordinator+Models.swift | 4 --- .../CreateAccountCoordinator+Reducer.swift | 27 ++----------------- .../OnboardingCoordinator+Reducer.swift | 23 +++++++++++++--- 4 files changed, 23 insertions(+), 32 deletions(-) diff --git a/RadixWallet/Clients/ProfileStore/ProfileStore.swift b/RadixWallet/Clients/ProfileStore/ProfileStore.swift index df12b5e130..b19bd6c00f 100644 --- a/RadixWallet/Clients/ProfileStore/ProfileStore.swift +++ b/RadixWallet/Clients/ProfileStore/ProfileStore.swift @@ -37,6 +37,7 @@ extension ProfileStore { extension ProfileStore { func createNewProfile() async throws { + try? await SargonOS.shared.deleteWallet() try await SargonOS.shared.newWallet(shouldPreDeriveInstances: false) } diff --git a/RadixWallet/Features/CreateAccount/Coordinator/CreateAccountCoordinator+Models.swift b/RadixWallet/Features/CreateAccount/Coordinator/CreateAccountCoordinator+Models.swift index a0ba0d028f..4af2d69827 100644 --- a/RadixWallet/Features/CreateAccount/Coordinator/CreateAccountCoordinator+Models.swift +++ b/RadixWallet/Features/CreateAccount/Coordinator/CreateAccountCoordinator+Models.swift @@ -5,18 +5,15 @@ import SwiftUI struct CreateAccountConfig: Sendable, Hashable { let specificNetworkID: NetworkID? let isFirstAccount: Bool - let isNewProfile: Bool let navigationButtonCTA: CreateAccountNavigationButtonCTA fileprivate init( isFirstAccount: Bool, - isNewProfile: Bool = false, navigationButtonCTA: CreateAccountNavigationButtonCTA, specificNetworkID: NetworkID? = nil ) { self.specificNetworkID = specificNetworkID self.isFirstAccount = isFirstAccount - self.isNewProfile = isNewProfile self.navigationButtonCTA = navigationButtonCTA } } @@ -34,7 +31,6 @@ extension CreateAccountConfig { case .firstAccountForNewProfile: self.init( isFirstAccount: true, - isNewProfile: true, navigationButtonCTA: .goHome ) case let .firstAccountOnNewNetwork(specificNetworkID): diff --git a/RadixWallet/Features/CreateAccount/Coordinator/CreateAccountCoordinator+Reducer.swift b/RadixWallet/Features/CreateAccount/Coordinator/CreateAccountCoordinator+Reducer.swift index 4ebb7629be..19fbb10274 100644 --- a/RadixWallet/Features/CreateAccount/Coordinator/CreateAccountCoordinator+Reducer.swift +++ b/RadixWallet/Features/CreateAccount/Coordinator/CreateAccountCoordinator+Reducer.swift @@ -14,8 +14,6 @@ struct CreateAccountCoordinator: Sendable, FeatureReducer { let config: CreateAccountConfig var name: NonEmptyString? - fileprivate var createdProfile = false - init( root: Path.State? = nil, config: CreateAccountConfig @@ -94,7 +92,6 @@ struct CreateAccountCoordinator: Sendable, FeatureReducer { enum InternalAction: Sendable, Equatable { case createAccountResult(TaskResult) case handleAccountCreated(TaskResult) - case handleProfileCreated(factorSourceOption: DerivePublicKeys.State.FactorSourceOption) } enum DelegateAction: Sendable, Equatable { @@ -106,7 +103,6 @@ struct CreateAccountCoordinator: Sendable, FeatureReducer { @Dependency(\.factorSourcesClient) var factorSourcesClient @Dependency(\.accountsClient) var accountsClient @Dependency(\.onLedgerEntitiesClient) var onLedgerEntitiesClient - @Dependency(\.onboardingClient) var onboardingClient @Dependency(\.errorQueue) var errorQueue @Dependency(\.isPresented) var isPresented @Dependency(\.dismiss) var dismiss @@ -150,11 +146,11 @@ extension CreateAccountCoordinator { state.path.append(.selectLedger(.init(context: .createHardwareAccount))) return .none } else { - return createProfileIfNecessaryThenDerivePublicKey(state: &state, factorSourceOption: .device) + return derivePublicKey(state: &state, factorSourceOption: .device) } case let .path(.element(_, action: .selectLedger(.delegate(.choseLedger(ledger))))): - return createProfileIfNecessaryThenDerivePublicKey( + return derivePublicKey( state: &state, factorSourceOption: .specific( ledger.asGeneral @@ -198,10 +194,6 @@ extension CreateAccountCoordinator { config: state.config ))) return .send(.delegate(.accountCreated)) - - case let .handleProfileCreated(factorSourceOption): - state.createdProfile = true - return derivePublicKey(state: &state, factorSourceOption: factorSourceOption) } } @@ -261,21 +253,6 @@ extension CreateAccountCoordinator { } } - private func createProfileIfNecessaryThenDerivePublicKey(state: inout State, factorSourceOption: DerivePublicKeys.State.FactorSourceOption) -> Effect { - if state.config.isNewProfile, !state.createdProfile { - // We need to create the Profile before deriving the public key - .run { send in - try await onboardingClient.createNewProfile() - await send(.internal(.handleProfileCreated(factorSourceOption: factorSourceOption))) - } catch: { error, _ in - errorQueue.schedule(error) - } - } else { - // We can derive the public key since the Profile has been created already - derivePublicKey(state: &state, factorSourceOption: factorSourceOption) - } - } - private func derivePublicKey(state: inout State, factorSourceOption: DerivePublicKeys.State.FactorSourceOption) -> Effect { state.destination = .derivePublicKey( .init( diff --git a/RadixWallet/Features/OnboardingFeature/Coordinator/OnboardingCoordinator+Reducer.swift b/RadixWallet/Features/OnboardingFeature/Coordinator/OnboardingCoordinator+Reducer.swift index fe2078d673..17f2c9fd9c 100644 --- a/RadixWallet/Features/OnboardingFeature/Coordinator/OnboardingCoordinator+Reducer.swift +++ b/RadixWallet/Features/OnboardingFeature/Coordinator/OnboardingCoordinator+Reducer.swift @@ -14,6 +14,10 @@ struct OnboardingCoordinator: Sendable, FeatureReducer { } } + public enum InternalAction: Sendable, Equatable { + case newProfileCreated + } + @CasePathable enum ChildAction: Sendable, Equatable { case startup(OnboardingStartup.Action) @@ -41,6 +45,7 @@ struct OnboardingCoordinator: Sendable, FeatureReducer { } } + @Dependency(\.onboardingClient) var onboardingClient @Dependency(\.radixConnectClient) var radixConnectClient @Dependency(\.appEventsClient) var appEventsClient @Dependency(\.errorQueue) var errorQueue @@ -60,15 +65,27 @@ struct OnboardingCoordinator: Sendable, FeatureReducer { private let destinationPath: WritableKeyPath> = \.$destination - func reduce(into state: inout State, childAction: ChildAction) -> Effect { - switch childAction { - case .startup(.delegate(.setupNewUser)): + func reduce(into state: inout State, internalAction: InternalAction) -> Effect { + switch internalAction { + case .newProfileCreated: state.destination = .createAccount( .init( config: .init(purpose: .firstAccountForNewProfile) ) ) return .none + } + } + + func reduce(into state: inout State, childAction: ChildAction) -> Effect { + switch childAction { + case .startup(.delegate(.setupNewUser)): + return .run { send in + try await onboardingClient.createNewProfile() + await send(.internal(.newProfileCreated)) + } catch: { error, _ in + errorQueue.schedule(error) + } case .startup(.delegate(.profileCreatedFromImportedBDFS)): appEventsClient.handleEvent(.walletRestored) From bdafdb468d55699feb1943c2afda96d20bd05ee0 Mon Sep 17 00:00:00 2001 From: Ghenadie Vasiliev-Pusca Date: Wed, 8 Jan 2025 10:52:17 +0200 Subject: [PATCH 07/13] Remove widthdrawal/deposit constraint --- .../Sections/Sections+ExecutionSummary.swift | 4 ---- 1 file changed, 4 deletions(-) diff --git a/RadixWallet/Features/InteractionReview/Sections/Sections+ExecutionSummary.swift b/RadixWallet/Features/InteractionReview/Sections/Sections+ExecutionSummary.swift index 49de0d814c..13841fc0d7 100644 --- a/RadixWallet/Features/InteractionReview/Sections/Sections+ExecutionSummary.swift +++ b/RadixWallet/Features/InteractionReview/Sections/Sections+ExecutionSummary.swift @@ -44,10 +44,6 @@ extension InteractionReview.Sections { return nil case .general, .transfer: - if summary.detailedManifestClass == .general { - guard !summary.deposits.isEmpty || !summary.withdrawals.isEmpty else { return nil } - } - let resourcesInfo = try await resourcesInfo(allAddresses.elements) let withdrawals = try await extractWithdrawals( accountWithdraws: summary.withdrawals, From ff8fcc5bbb1be9dea443c518118bbac3b2eb7882 Mon Sep 17 00:00:00 2001 From: Ghenadie Vasiliev-Pusca Date: Wed, 8 Jan 2025 10:59:20 +0200 Subject: [PATCH 08/13] Update AtMost handling --- .../AccountPortfoliosClient+State.swift | 3 --- .../Core/SharedModels/Assets/ResourceAmount.swift | 10 +++------- .../ResourceBalance/ResourceBalanceView.swift | 7 ------- 3 files changed, 3 insertions(+), 17 deletions(-) diff --git a/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+State.swift b/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+State.swift index 30f5883b02..4e710baf96 100644 --- a/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+State.swift +++ b/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+State.swift @@ -271,9 +271,6 @@ extension ResourceAmount { case var .atLeast(exactAmount): exactAmount.fiatWorth = change(resourceAddress, exactAmount) self = .atLeast(exactAmount) - case var .atMost(exactAmount): - exactAmount.fiatWorth = change(resourceAddress, exactAmount) - self = .atMost(exactAmount) case var .between(minExactAmount, maxExactAmount): minExactAmount.fiatWorth = change(resourceAddress, minExactAmount) maxExactAmount.fiatWorth = change(resourceAddress, maxExactAmount) diff --git a/RadixWallet/Core/SharedModels/Assets/ResourceAmount.swift b/RadixWallet/Core/SharedModels/Assets/ResourceAmount.swift index 2507f60b1f..f312dbd9e5 100644 --- a/RadixWallet/Core/SharedModels/Assets/ResourceAmount.swift +++ b/RadixWallet/Core/SharedModels/Assets/ResourceAmount.swift @@ -4,7 +4,6 @@ import Sargon enum ResourceAmount: Sendable, Hashable, Codable { case exact(ExactResourceAmount) case atLeast(ExactResourceAmount) - case atMost(ExactResourceAmount) case between(minimum: ExactResourceAmount, maximum: ExactResourceAmount) case predicted(predicted: ExactResourceAmount, guaranteed: ExactResourceAmount) case unknown @@ -15,13 +14,14 @@ enum ResourceAmount: Sendable, Hashable, Codable { self = .exact(amount) case let .atLeast(amount): self = .atLeast(.init(nominalAmount: amount)) - case let .atMost(amount): - self = .atMost(.init(nominalAmount: amount)) case let .between(minAmount, maxAmount): self = .between( minimum: .init(nominalAmount: minAmount), maximum: .init(nominalAmount: maxAmount) ) + case .atMost: + // AtMost is consider unknown in the Wallet UI as per https://radixdlt.atlassian.net/browse/ABW-4040 + self = .unknown case .unknownAmount: self = .unknown } @@ -74,8 +74,6 @@ extension ResourceAmount { return .exact(adjust(amount.nominalAmount)) case let .atLeast(amount): return .atLeast(.init(nominalAmount: adjust(amount.nominalAmount))) - case let .atMost(amount): - return .atMost(.init(nominalAmount: adjust(amount.nominalAmount))) case let .between(minAmount, maxAmount): let min = adjust(minAmount.nominalAmount) let max = adjust(maxAmount.nominalAmount) @@ -112,8 +110,6 @@ extension ResourceAmount: CustomDebugStringConvertible { amount.nominalAmount.formatted() case let .atLeast(amount): "At least \(amount.nominalAmount.formatted())" - case let .atMost(amount): - "No more than \(amount.nominalAmount.formatted())" case let .between(minAmount, maxAmount): "Min: \(minAmount.nominalAmount.formatted()); Max: \(maxAmount.nominalAmount.formatted())" case let .predicted(predicted, guaranteed): diff --git a/RadixWallet/Features/AssetsFeature/Components/HelperViews/ResourceBalance/ResourceBalanceView.swift b/RadixWallet/Features/AssetsFeature/Components/HelperViews/ResourceBalance/ResourceBalanceView.swift index d75992a88b..e5ca67c35d 100644 --- a/RadixWallet/Features/AssetsFeature/Components/HelperViews/ResourceBalance/ResourceBalanceView.swift +++ b/RadixWallet/Features/AssetsFeature/Components/HelperViews/ResourceBalance/ResourceBalanceView.swift @@ -653,13 +653,6 @@ extension ResourceBalanceView { appearance: appearance, symbol: symbol ) - case let .atMost(exactAmount): - SubAmountView( - title: L10n.InteractionReview.noMoreThan, - amount: exactAmount, - appearance: appearance, - symbol: symbol - ) case let .between(minAmount, maxAmount): VStack(alignment: alignment, spacing: .small3) { SubAmountView( From bf7ef119ac145957e35d89a3684eea723428104a Mon Sep 17 00:00:00 2001 From: Ghenadie Vasiliev-Pusca Date: Wed, 8 Jan 2025 11:10:28 +0200 Subject: [PATCH 09/13] Update unknown amount style --- .../ResourceBalance/ResourceBalanceView.swift | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/RadixWallet/Features/AssetsFeature/Components/HelperViews/ResourceBalance/ResourceBalanceView.swift b/RadixWallet/Features/AssetsFeature/Components/HelperViews/ResourceBalance/ResourceBalanceView.swift index e5ca67c35d..2ae77b61ad 100644 --- a/RadixWallet/Features/AssetsFeature/Components/HelperViews/ResourceBalance/ResourceBalanceView.swift +++ b/RadixWallet/Features/AssetsFeature/Components/HelperViews/ResourceBalance/ResourceBalanceView.swift @@ -517,12 +517,9 @@ extension ResourceBalanceView { } if case .unknown = amount { - StatusMessageView( - text: L10n.InteractionReview.Unknown.amount, - type: .warning, - useNarrowSpacing: true, - useSmallerFontSize: true - ) + Text(L10n.InteractionReview.Unknown.amount) + .textStyle(.body2HighImportance) + .foregroundStyle(.app.gray2) } } } From 492f21c43310c5d8cf25d77f54987d2304877e32 Mon Sep 17 00:00:00 2001 From: Ghenadie Vasiliev-Pusca Date: Wed, 8 Jan 2025 11:31:04 +0200 Subject: [PATCH 10/13] update --- RadixWallet/Clients/ProfileStore/ProfileStore.swift | 1 - .../Coordinator/OnboardingCoordinator+Reducer.swift | 8 ++++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/RadixWallet/Clients/ProfileStore/ProfileStore.swift b/RadixWallet/Clients/ProfileStore/ProfileStore.swift index b19bd6c00f..df12b5e130 100644 --- a/RadixWallet/Clients/ProfileStore/ProfileStore.swift +++ b/RadixWallet/Clients/ProfileStore/ProfileStore.swift @@ -37,7 +37,6 @@ extension ProfileStore { extension ProfileStore { func createNewProfile() async throws { - try? await SargonOS.shared.deleteWallet() try await SargonOS.shared.newWallet(shouldPreDeriveInstances: false) } diff --git a/RadixWallet/Features/OnboardingFeature/Coordinator/OnboardingCoordinator+Reducer.swift b/RadixWallet/Features/OnboardingFeature/Coordinator/OnboardingCoordinator+Reducer.swift index 17f2c9fd9c..f0217c40c4 100644 --- a/RadixWallet/Features/OnboardingFeature/Coordinator/OnboardingCoordinator+Reducer.swift +++ b/RadixWallet/Features/OnboardingFeature/Coordinator/OnboardingCoordinator+Reducer.swift @@ -111,6 +111,14 @@ struct OnboardingCoordinator: Sendable, FeatureReducer { _ = await radixConnectClient.loadP2PLinksAndConnectAll() } + case .createAccount(.delegate(.dismissed)): + return .run { _ in + // Clear out the ephemeral profile created on `setupNewUser` + try await SargonOS.shared.deleteWallet() + } catch: { error, _ in + errorQueue.schedule(error) + } + default: return .none } From 884caa154d127e19fb0d857d3e83bff9e3bead26 Mon Sep 17 00:00:00 2001 From: Ghenadie <118184705+GhenadieVP@users.noreply.github.com> Date: Wed, 8 Jan 2025 11:32:32 +0200 Subject: [PATCH 11/13] Update ResourceAmount.swift --- RadixWallet/Core/SharedModels/Assets/ResourceAmount.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RadixWallet/Core/SharedModels/Assets/ResourceAmount.swift b/RadixWallet/Core/SharedModels/Assets/ResourceAmount.swift index f312dbd9e5..28d7703bfc 100644 --- a/RadixWallet/Core/SharedModels/Assets/ResourceAmount.swift +++ b/RadixWallet/Core/SharedModels/Assets/ResourceAmount.swift @@ -20,7 +20,7 @@ enum ResourceAmount: Sendable, Hashable, Codable { maximum: .init(nominalAmount: maxAmount) ) case .atMost: - // AtMost is consider unknown in the Wallet UI as per https://radixdlt.atlassian.net/browse/ABW-4040 + // AtMost is considered unknown in the Wallet as per https://radixdlt.atlassian.net/browse/ABW-4040 self = .unknown case .unknownAmount: self = .unknown From 61e4f42158e4fc77115c8d20859258bfb862deed Mon Sep 17 00:00:00 2001 From: Ghenadie Vasiliev-Pusca Date: Wed, 8 Jan 2025 11:36:42 +0200 Subject: [PATCH 12/13] version --- Aux/Config/Common.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Aux/Config/Common.xcconfig b/Aux/Config/Common.xcconfig index 7e043cc4b3..390f3343aa 100644 --- a/Aux/Config/Common.xcconfig +++ b/Aux/Config/Common.xcconfig @@ -1,7 +1,7 @@ // MARK: - Custom flags /// Application version shared across all targets and flavours -APP_VERSION = 1.11.3 +APP_VERSION = 1.11.4 /// App Icon base name APP_ICON = AppIcon From fbd2daa5486220da273f52da8f21d286a2d2c048 Mon Sep 17 00:00:00 2001 From: Ghenadie Vasiliev-Pusca Date: Wed, 8 Jan 2025 17:33:08 +0200 Subject: [PATCH 13/13] fix --- .../ResourceBalance/ResourceBalanceView.swift | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/RadixWallet/Features/AssetsFeature/Components/HelperViews/ResourceBalance/ResourceBalanceView.swift b/RadixWallet/Features/AssetsFeature/Components/HelperViews/ResourceBalance/ResourceBalanceView.swift index 2ae77b61ad..4eb5f131fb 100644 --- a/RadixWallet/Features/AssetsFeature/Components/HelperViews/ResourceBalance/ResourceBalanceView.swift +++ b/RadixWallet/Features/AssetsFeature/Components/HelperViews/ResourceBalance/ResourceBalanceView.swift @@ -563,12 +563,9 @@ extension ResourceBalanceView { } if case .unknown = amount { - StatusMessageView( - text: L10n.InteractionReview.Unknown.amount, - type: .warning, - useNarrowSpacing: true, - useSmallerFontSize: true - ) + Text(L10n.InteractionReview.Unknown.amount) + .textStyle(.body2HighImportance) + .foregroundStyle(.app.gray2) } } }