Demo app fixes and improvements for TestFlight#103
Conversation
|
Reviews (1): Last reviewed commit: "Annotate onDismiss closure with @MainAct..." | Re-trigger Greptile |
Prompt To Fix All With AIFix the following 1 code review issue. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 1
Sources/CrossmintAuth/DefaultAuthManager.swift:225-228
**Transient errors permanently log users out**
The catch block now always sets `_authenticationStatus = .nonAuthenticated` and throws `AuthError.signInRequired`, regardless of the underlying error type. The old code set `_authenticationStatus = nil` for non-auth errors, which allowed the `authenticationStatus` getter to retry `performJWTRefresh` on the next access. With `.nonAuthenticated` stored, the `guard let` in the getter short-circuits immediately and returns `.nonAuthenticated` without any retry — a transient network error during JWT refresh will now permanently clear the user's session until they explicitly re-authenticate, even though the stored one-time secret is still valid.
Reviews (2): Last reviewed commit: "Treat all JWT refresh failures as nonAut..." | Re-trigger Greptile |
| } catch { | ||
| if case .signInRequired = error { | ||
| _authenticationStatus = .nonAuthenticated | ||
| } else { | ||
| _authenticationStatus = nil | ||
| } | ||
| throw error | ||
| _authenticationStatus = .nonAuthenticated | ||
| throw AuthError.signInRequired | ||
| } |
There was a problem hiding this comment.
Transient errors permanently log users out
The catch block now always sets _authenticationStatus = .nonAuthenticated and throws AuthError.signInRequired, regardless of the underlying error type. The old code set _authenticationStatus = nil for non-auth errors, which allowed the authenticationStatus getter to retry performJWTRefresh on the next access. With .nonAuthenticated stored, the guard let in the getter short-circuits immediately and returns .nonAuthenticated without any retry — a transient network error during JWT refresh will now permanently clear the user's session until they explicitly re-authenticate, even though the stored one-time secret is still valid.
Prompt To Fix With AI
This is a comment left during a code review.
Path: Sources/CrossmintAuth/DefaultAuthManager.swift
Line: 225-228
Comment:
**Transient errors permanently log users out**
The catch block now always sets `_authenticationStatus = .nonAuthenticated` and throws `AuthError.signInRequired`, regardless of the underlying error type. The old code set `_authenticationStatus = nil` for non-auth errors, which allowed the `authenticationStatus` getter to retry `performJWTRefresh` on the next access. With `.nonAuthenticated` stored, the `guard let` in the getter short-circuits immediately and returns `.nonAuthenticated` without any retry — a transient network error during JWT refresh will now permanently clear the user's session until they explicitly re-authenticate, even though the stored one-time secret is still valid.
How can I resolve this? If you propose a fix, please make it concise.
This pull request fixes four issues found while testing the SmartWalletsDemo on TestFlight and adds device signer setup by default to reduce how often users hit the OTP flow.
Changes
SmartWalletsDemo.entitlementsfile only hadwebcredentials:wallets-ios.demos-crossmint.com?mode=developer, which bypasses AASA validation for Xcode-installed builds but not for TestFlight. Adding the entry without?mode=developeralongside the existing one lets passkey registration work on distributed builds.fetchWalletandmakeWalletinAppStatenow passWalletOptions(deviceSigner: true). This registers the device key on first load and on wallet creation, so subsequent transfers can be signed locally without triggering OTP.onDismissnow callscancelTransaction()annotated with@MainActor. Previously, swiping the sheet down would close the UI but leave the underlying send task suspended indefinitely since only the X button wired up cancellation.cancelOTP()is already idempotent so calling it after a successful submission is safe.loadTransfersno longer setsisLoading = truewhen called from pull-to-refresh. The previous behavior toggled the view fromListtoProgressView, which removed the list from the hierarchy and caused SwiftUI to cancel the.refreshabletask mid-flight, which is why every manual refresh landed on "Unknown error: cancelled".