Skip to content

Demo app fixes and improvements for TestFlight#103

Merged
tomas-martins-crossmint merged 6 commits into
mainfrom
tomas/demo-app-fixes-testflight-version
Jun 8, 2026
Merged

Demo app fixes and improvements for TestFlight#103
tomas-martins-crossmint merged 6 commits into
mainfrom
tomas/demo-app-fixes-testflight-version

Conversation

@tomas-martins-crossmint

Copy link
Copy Markdown
Contributor

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

  • The SmartWalletsDemo.entitlements file only had webcredentials:wallets-ios.demos-crossmint.com?mode=developer, which bypasses AASA validation for Xcode-installed builds but not for TestFlight. Adding the entry without ?mode=developer alongside the existing one lets passkey registration work on distributed builds.
  • fetchWallet and makeWallet in AppState now pass WalletOptions(deviceSigner: true). This registers the device key on first load and on wallet creation, so subsequent transfers can be signed locally without triggering OTP.
  • The OTP sheet's onDismiss now calls cancelTransaction() 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.
  • loadTransfers no longer sets isLoading = true when called from pull-to-refresh. The previous behavior toggled the view from List to ProgressView, which removed the list from the hierarchy and caused SwiftUI to cancel the .refreshable task mid-flight, which is why every manual refresh landed on "Unknown error: cancelled".

@greptile-apps

greptile-apps Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Reviews (1): Last reviewed commit: "Annotate onDismiss closure with @MainAct..." | Re-trigger Greptile

@greptile-apps

greptile-apps Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor
Prompt To Fix All With AI
Fix 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

Comment on lines 225 to 228
} catch {
if case .signInRequired = error {
_authenticationStatus = .nonAuthenticated
} else {
_authenticationStatus = nil
}
throw error
_authenticationStatus = .nonAuthenticated
throw AuthError.signInRequired
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 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.

@tomas-martins-crossmint tomas-martins-crossmint merged commit a2a43fa into main Jun 8, 2026
3 of 5 checks passed
@tomas-martins-crossmint tomas-martins-crossmint deleted the tomas/demo-app-fixes-testflight-version branch June 8, 2026 19:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants