Skip to content

Comments

EdgeSpend: Phaze gift card improvements and error resilience#5937

Open
Jon-edge wants to merge 11 commits intodevelopfrom
jon/fix/phaze-3
Open

EdgeSpend: Phaze gift card improvements and error resilience#5937
Jon-edge wants to merge 11 commits intodevelopfrom
jon/fix/phaze-3

Conversation

@Jon-edge
Copy link
Contributor

@Jon-edge Jon-edge commented Feb 12, 2026

CHANGELOG

Does this branch warrant an entry to the CHANGELOG?

  • Yes

Dependencies

Requires edge-core-js with updated EdgeTxActionGiftCard type (adds quoteId and productId fields).

Description

Context

Asana: "EdgeSpend - Various Improvements/Fixes". Addresses several Phaze gift card UX and robustness issues across purchase, list, market, and detail scenes.

Changes

  • Fault-tolerant cleaners: asTolerantArray helper so a single malformed brand or voucher entry doesn't break the entire list. Makes deliveryAddress optional and adds 'failed' to recognized order statuses.
  • Error resilience across scenes: Exposes isError/error from useGiftCardProvider. On GiftCardListScene, stops clearing orders on API errors (keeps last-known-good data), pauses polling when offline, auto-resumes on reconnect, shows informational warning banners, and disables the purchase button when offline or the API is down. On GiftCardMarketScene, gates brand query on connectivity and shows a warning instead of an infinite loader. On GiftCardPurchaseScene, guards against empty delivery addresses and shows a warning when the provider fails. Distinguishes network connectivity errors from Phaze service errors with separate messaging.
  • Double-tap prevention: Adds isCreatingOrder guard in handleNextPress to prevent duplicate order creation.
  • Card status states: Distinguishes "Awaiting Payment Confirmations" (tx sent, no voucher yet) from "Pending Delivery" and "Failed" on the gift card display card.
  • QuoteID in menu: Shows the Phaze quoteId at the top of the kebab menu modal for support reference.
  • QuoteId row and card-level copy: Extends GiftCardDetailsCard with Quote ID, Product ID, and Order ID rows. A single copy button on the right copies all data at once. Backward-compat: if quoteId is absent in the core type, treats orderId as the quoteId per legacy behavior.
  • Gift Card Account Information scene: New scene behind a ConfirmContinueModal warning that reveals Phaze account credentials (email, user ID). Accessible from the kebab menu "Get Help" row (with quoteId context) and from a developer settings row (without quoteId).
  • Get Help on failed cards: Failed cards show a "Get Help" button that navigates to the account info scene with the card's quoteId.
  • Lock network fee: Sets networkFeeOption to high and locks the fee tile during gift card purchases to reduce the risk of quote expiration.
  • Wire up new core type fields: Populates quoteId, productId, and orderId correctly in the saved EdgeTxActionGiftCard now that the core type has explicit fields.

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)

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: baaedaa456

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +186 to +187
// Keep existing cached orders visible — don't clear state on error
setLoadError(true)

Choose a reason for hiding this comment

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

P1 Badge Clear displayed orders when account refresh fails

Keeping existing state on fetch failure can expose the previous account’s cards after an account switch. clearOrderCache() only resets module-level caches, but the activeOrders / redeemedOrders React state is not reset when account.id changes, and this catch block now only sets loadError. If the first refresh for the new account fails (for example, network/API failure), the scene can continue rendering stale orders from the prior user session.

Useful? React with 👍 / 👎.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed. Added a ref-based account ID check after useState declarations that resets activeOrders, redeemedOrders, isLoading, and loadError when the account changes mid-session.

}

// Don't attempt API calls while offline
if (!isConnected) return

Choose a reason for hiding this comment

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

P1 Badge Exit initial loading state when offline on focus

This early return bypasses loadOrdersFromApi, so its finally (which clears isLoading) never runs. On first entry to the scene (or after cache reset, where loading starts true), visiting while offline leaves an indefinite spinner with no actionable state until connectivity changes, effectively blocking the gift card list offline.

Useful? React with 👍 / 👎.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed. The early return for !isConnected now calls setIsLoading(false) before returning, so the scene falls through to the offline error state instead of spinning indefinitely.

}

// Don't attempt API calls while offline
if (!isConnected) return
Copy link

Choose a reason for hiding this comment

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

Infinite loader on first offline visit to list scene

Medium Severity

When the scene is opened for the first time while offline, the early return on !isConnected prevents loadOrdersFromApi from ever being called. Since isLoading is only set to false inside that function's finally block, it remains true and the UI shows FillLoader indefinitely with no offline indication. Before this change, the API call would be attempted, fail, and the finally block would clear isLoading, letting the scene fall through to the "No Gift Cards" or error state.

Additional Locations (2)

Fix in Cursor Fix in Web

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed. Same as above — setIsLoading(false) is now called in the !isConnected early return path.

(id, i) => `Identity ${i + 1}:\n${JSON.stringify(id, null, 2)}`
)
.join('\n\n')
)
Copy link

Choose a reason for hiding this comment

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

Debug modal exposes userApiKey authentication credential in plain text

Low Severity

The handleShowIdentities function uses JSON.stringify on full identity objects (both current StoredIdentity and legacy PhazeUser), which include the userApiKey field — an authentication credential sent as the user-api-key header in Phaze API requests. Since this modal is designed for sharing with support, the credential could leak inadvertently. The userApiKey should be redacted or omitted before display.

Additional Locations (1)

Fix in Cursor Fix in Web

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No longer applicable. The handleShowIdentities modal and raw identity JSON display were removed in favor of a dedicated GiftCardAccountInfoScene that only shows email and user ID — no userApiKey is exposed.

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 1 potential issue.

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

return 'failed'
if (order.vouchers.length > 0) return 'available'
if (order.txid != null) return 'confirming'
return 'pending'
Copy link

Choose a reason for hiding this comment

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

Pending card status is unreachable dead code

Medium Severity

The 'pending' return in getCardStatus is unreachable for any displayed order. The relevantOrders filter requires order.vouchers.length > 0 || order.txid != null, but getCardStatus only falls through to 'pending' when both vouchers.length === 0 AND txid == null — exactly the condition the filter excludes. This means the "Pending Delivery, Please Wait..." label and its shimmer overlay can never appear. All non-failed orders without vouchers show "Awaiting Payment Confirmations..." instead, contradicting the PR's stated intent to distinguish both states.

Additional Locations (2)

Fix in Cursor Fix in Web

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed. getCardStatus now checks for Phaze API status === 'processing' (payment confirmed, generating vouchers) and returns 'pending' in that case, before falling through to the txid check which returns 'confirming'.

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.
@Jon-edge Jon-edge force-pushed the jon/fix/phaze-3 branch 4 times, most recently from 9625034 to a2fb45e Compare February 14, 2026 01:34
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.
@Jon-edge Jon-edge force-pushed the jon/fix/phaze-3 branch 2 times, most recently from d799b3a to 39150e5 Compare February 16, 2026 20:57
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.
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.

1 participant