Skip to content

Jon/fix/phaze 3.1#5943

Open
swansontec wants to merge 11 commits intodevelopfrom
jon/fix/phaze-3.1
Open

Jon/fix/phaze 3.1#5943
swansontec wants to merge 11 commits intodevelopfrom
jon/fix/phaze-3.1

Conversation

@swansontec
Copy link
Contributor

@swansontec swansontec commented Feb 17, 2026

CHANGELOG

Does this branch warrant an entry to the CHANGELOG?

  • Yes
  • No

Dependencies

none

Requirements

If you have made any visual changes to the GUI. Make sure you have:

  • Tested on iOS device
  • Tested on Android device
  • Tested on small-screen device (iPod Touch)
  • Tested on large-screen device (tablet)

Note

Medium Risk
Touches gift card purchase/send configuration and transaction metadata persistence, where mistakes could impact payment flow or support diagnostics. Changes are localized to gift card screens/providers but include new status/error branches and API cleaning behavior.

Overview
Improves Phaze gift card supportability and resilience by adding a new GiftCardAccountInfoScene (behind a confirm-to-reveal wall) that can be opened from failed cards, the gift card kebab menu (Get Help), or developer settings.

Enhances gift card transaction details by persisting quoteId/productId/orderId on purchase and updating GiftCardDetailsCard to display the Quote ID plus a single “copy all” action (with legacy fallback when older txs stored quoteId in orderId).

Hardens Phaze flows: distinguishes offline vs service failures in list/market/purchase scenes (with warning banners and connectivity-aware retries), adds more granular card statuses (confirming/pending/failed), avoids clearing cached orders on refresh errors, and ensures purchases lock fees to high priority (networkFeeOption: 'high', fee tile locked) while guarding against missing token data or missing payment addresses. Also makes Phaze API cleaners more tolerant to malformed array items and adds support for failed order status.

Written by Cursor Bugbot for commit d6f22c2. This will update automatically on new commits. Configure here.


Add asTolerantArray helper that skips malformed items instead of
throwing on the entire array. Apply it to brand lists and voucher
arrays so a single bad entry doesn't break the whole UI. Also add
'failed' to recognized order statuses and make deliveryAddress
optional with an empty-string default.
Expose isError/error from useGiftCardProvider so scenes can detect
provider initialization failures. On GiftCardListScene, stop clearing
orders on API errors (keep last-known-good data visible), pause
polling when offline and auto-resume on reconnect, and show an
informational warning banner that auto-clears on success. On
GiftCardMarketScene, gate the brand query on network connectivity so
it auto-retries when online, and show a warning instead of an infinite
loader when the initial fetch fails. On GiftCardPurchaseScene, guard
against empty delivery addresses and show a warning when the provider
fails to initialize.
Add isCreatingOrder to the early-return guard in handleNextPress so a
second tap during the brief window before React disables the button
cannot trigger duplicate order creation.
Distinguish between awaiting blockchain confirmations (txid exists but
no voucher yet), pending voucher delivery, and failed/expired orders.
Failed cards are dimmed like redeemed cards.
Display the Phaze quoteId at the top of the kebab menu modal for
easier debugging and support reference.
Extend the gift card tx details card with a Quote ID row and a single
copy button on the right side that copies all data at once. Dividers
stop short of the copy button. The redeem row remains separate with
its own chevron.

Document backward-compat: orderId stores quoteId in prior versions.
New scene to view Phaze account credentials behind a confirmation wall.
Shows quoteId context when accessed from a specific card. After the user
confirms a ConfirmContinueModal warning about redemption risk, identity
data (email, user ID) is revealed with copy buttons.
Add a 'Get Help' row to the gift card kebab menu that navigates to the
new Gift Card Account Information scene with the quoteId. Also surface
a 'Get Help' button on failed cards, reusing the existing redeem button
pattern.
Add a Gift Card Account Info row in the developer mode section of
SettingsScene that navigates to the new account information scene.
Set networkFeeOption to high and lock the fee tile so users cannot
lower the fee priority. Gift card orders are time-sensitive with
expiring quotes, so high priority reduces the risk of missed deadlines.
Populate quoteId, productId, and orderId correctly in the saved action
now that the core type has explicit fields. Update GiftCardDetailsCard
with backward-compat detection: if quoteId is absent, treat orderId as
the quoteId per legacy behavior.
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

orderId: order.quoteId,
orderId: cartItem.orderId,
quoteId: order.quoteId,
productId: cartItem.productId,
Copy link

Choose a reason for hiding this comment

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

Unchecked cart[0] access after successful payment

Medium Severity

order.cart[0] is accessed without verifying the array is non-empty. If the API returns an empty cart array, cartItem is undefined and accessing .orderId / .productId throws a runtime error. This happens inside the onDone callback after payment has already been broadcast, so a crash here means the gift card action and order augment are never saved — the user paid but sees no gift card. The sibling function mergeOrderWithAugment in phazeGiftCardOrderStore.ts handles this gracefully with optional chaining (firstCartItem?.productName), but the purchase scene does not.

Fix in Cursor Fix in Web

if (!isConnected) {
setIsLoading(false)
return
}
Copy link

Choose a reason for hiding this comment

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

Offline cold start shows "no cards" not error

Low Severity

When the scene opens while offline with no cached data, useFocusEffect sets isLoading to false but never sets loadError to true. The render path hasNoCards && loadError is therefore false, and the user sees the generic "no cards" message instead of the intended gift_card_network_error. The isConnected ternary in the error display was specifically added to distinguish network vs service errors but is unreachable in this offline-from-start scenario.

Additional Locations (1)

Fix in Cursor Fix in Web

Copy link
Contributor Author

@swansontec swansontec left a comment

Choose a reason for hiding this comment

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

I can't actually approve / reject the PR, since I opened it, but here are my comments. Also check the AI comments.

/**
* Tolerant array cleaner: skips items that fail cleaning instead of throwing.
*/
const asTolerantArray =
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We have a similar cleaner in edge-server-tools, and there we call it asHealingArray. If we could align the name, since the behavior matches, that would be great.

Comment on lines +122 to +127
if (prevAccountIdRef.current !== account.id) {
prevAccountIdRef.current = account.id
setActiveOrders([])
setRedeemedOrders([])
setIsLoading(true)
setLoadError(false)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

You can't call setX during render - it needs to be in a useEffect.

Actually, I think this whole design is over-complicated. If you moved the fetch inside Tan Stack query, you could use the refetchInterval to handle the background refresh, and then wire the enabled flag into the navigation's focus state. To handle the account change, you could stick account.rootLoginId into the TanStack query key, forcing unique data per account.

We are trying to reduce our reliance on the isConnected flag, and just allow queries to fail "naturally" if the network is down. If you really want this, though, you can probably just set enabled: isFocused && isConnected on the query.

selectedAmount == null ||
provider == null ||
!isReady ||
isCreatingOrder
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This should not be needed if handleNextPress is being passed to an EdgeTouchableX component - those won't accept a second press until the first promise resolves. Is there some strange case I am missing?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah that was my initial reaction too, I believe there was a strange case - will verify.

Comment on lines +51 to +59
React.useEffect(() => {
if (!isRevealed || provider == null) return
provider
.listIdentities(account)
.then(setIdentities)
.catch((err: unknown) => {
showError(err)
})
}, [isRevealed, account, provider])
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I feel like this should be useQuery

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.

3 participants

Comments