Skip to content

feat(stellar): improve Stellar wallet UX#58

Open
akbarsaputrait wants to merge 8 commits into
masterfrom
feat/stellar-wallet-ux
Open

feat(stellar): improve Stellar wallet UX#58
akbarsaputrait wants to merge 8 commits into
masterfrom
feat/stellar-wallet-ux

Conversation

@akbarsaputrait

@akbarsaputrait akbarsaputrait commented Jul 22, 2026

Copy link
Copy Markdown
Member

Summary

Improve Stellar wallet UX and add Direct Settlement support.

Stellar Wallet UX

  • Always show Freighter & LOBSTR in wallet list, even without browser extension
  • Route through WalletConnect when extension not available
  • Modal close detection — properly rejects when user closes QR modal
  • Pre-fetch wallets in StellarContextProvider — no loading spinner
  • Cache kit synchronously — avoids flash on remount
  • Dynamic description text — "Scan QR" for WalletConnect, "Open wallet" for extension

Stellar Direct Settlement

Auto-detects same-chain Stellar USDC/EURC payments and routes directly:

  • Auto-detection: When source chain + token === destination chain + token (both Stellar USDC or both Stellar EURC), forces intent: "stellar_direct"
  • API field: intent sent as top-level field in POST /payments (separate from display title)
  • Response handling: settlementMode: "stellar_direct" → source IS destination, fee "0.00", direct send
  • Types: Added intent to CreateNewPaymentParams/CreatePaymentRequest, settlementMode to PaymentResponse

Files Changed

  • packages/pay-common/src/api/types.ts — Added intent + settlementMode fields
  • packages/pay-common/src/api/payment.ts — Pass intent to API request
  • packages/connectkit/src/payment/createPaymentPayload.ts — Auto-detect stellar_direct, pass intent
  • packages/connectkit/src/components/Pages/Stellar/PayWithStellarToken/index.tsx — Handle settlementMode response
  • packages/connectkit/src/provider/StellarContextProvider.tsx — Pre-fetch wallets, sync kit cache
  • packages/connectkit/src/utils/stellar/walletconnect.module.ts — Modal close detection
  • packages/connectkit/src/components/Pages/Stellar/ConnectStellar/index.tsx — Always show wallets, no spinner
  • packages/connectkit/src/components/Pages/Stellar/ConnectorStellar/index.tsx — Use WALLET_CONNECT_ID constant
  • packages/connectkit/src/components/RozoPayModal/index.tsx — Register routes
  • packages/connectkit/src/constants/routes.ts — Route definitions
  • examples/nextjs-app/package.json — workspace:* for local dev
  • packages/connectkit/package.json — workspace:* for local dev

Testing

Wallet UX:

  • Desktop with extension → extension popup
  • Desktop without extension → WalletConnect QR
  • Incognito → WalletConnect QR
  • Freighter Mobile Explorer → WalletConnect modal
  • Mobile browser → WalletConnect QR
  • Modal close → proper error (no stuck spinner)
  • No loading spinner on Connect Stellar page

Direct Settlement:

  • Stellar USDC → Stellar USDC → intent: "stellar_direct" auto-set
  • Stellar EURC → Stellar EURC → intent: "stellar_direct" auto-set
  • Cross-token (USDC → EURC) → no intent (normal hub path)
  • Response with settlementMode: "stellar_direct" → direct send

- Always show Freighter and LOBSTR in wallet list (even without extension)
- When extension not installed, route through WalletConnect
- Add WalletConnect QR page for desktop without extension
- Add modal close detection to WalletConnect (rejects on user dismiss)
- Update description text for WalletConnect flow
- Pre-fetch supported wallets in StellarContextProvider (no loading spinner)
- Cache kit singleton synchronously to avoid flash
@vercel

vercel Bot commented Jul 22, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
intent-example Ready Ready Preview, Comment Jul 24, 2026 3:27pm

Request Review

Comment thread packages/connectkit/src/components/Pages/Stellar/StellarWalletConnectQR/index.tsx Outdated
Comment thread packages/connectkit/src/utils/stellar/walletconnect.module.ts
Comment thread packages/connectkit/src/components/Pages/Stellar/ConnectStellar/index.tsx Outdated
Comment thread packages/connectkit/src/components/Pages/Stellar/ConnectStellar/index.tsx Outdated
Comment thread packages/connectkit/src/components/Pages/Stellar/ConnectorStellar/index.tsx Outdated

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

Copy link
Copy Markdown

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: 458b0636d3

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/connectkit/src/components/Pages/Stellar/ConnectStellar/index.tsx Outdated
- Remove dead StellarWalletConnectQR component (unreachable route, signing bug)
- Fix MutationObserver leak in walletconnect.module.ts (add finally block)
- Add walletsLoaded flag to StellarContextProvider (fix infinite spinner on error)
- Collapse duplicate isPlatformWrapper/else branches in ConnectStellar
- Use WALLET_CONNECT_ID constant in ConnectorStellar (no hardcoded string)
- Check hasWalletConnect before routing to WalletConnect (custom kit safety)
- Auto-detect Stellar→Stellar USDC/EURC same-chain payments
- Force intent: stellar_direct when source=destination chain+token
- Add settlementMode field to PaymentResponse
- Pass intent as top-level field in POST /payments
- Handle settlementMode in PayWithStellarToken (direct send)
- Add modal close detection to WalletConnect (MutationObserver)
- Update workspace deps for local dev mode
@shawnmuggle

Copy link
Copy Markdown
Member

Review — no P0, mergeable; 2 P1s worth a look first

Reviewed the signing / fund-routing path closely. No blocker. The stellar_direct auto-detection in createPaymentPayload.ts only sets a backend hint (intent: "stellar_direct"); it never mutates toAddress/toUnits, and settlementMode in PayWithStellarToken is log-only. So "source IS destination, fee 0.00" cannot misroute funds on the frontend. ✅

P1 — recommend before merge

  1. WalletConnect getAddress() blindly reuses live[0] (walletconnect.module.ts, getExistingSession/getAddress). Called with no address, it returns the first live session's publicKey without re-opening the modal. Multi-account scenario: user connected wallet A (session persisted), taps connect intending wallet B → silently re-bound to A, and signTransaction's wcSessionPaths[0] fallback signs from the unintended source account. Real mis-send risk for multi-account WC users. → match against an expected/requested address, or force a fresh connect when ambiguous.
  2. Modal-close observer race → stuck spinner (getAddress). document.querySelector(selector) is snapshotted once; if AppKit injects <appkit-modal> asynchronously or into a shadow root, the observer never fires. User closes the modal → Promise.race([approval(), modalClosed]) waits on approval() forever → spinner hangs, no cancel path. → prefer AppKit's subscribe/close callback over DOM-removal sniffing, or add a timeout.

P2 (non-blocking)

  • Forced intent override silently discards a consumer-supplied payParams.intent on same-token Stellar — intentional per comment, but no signal to the caller.
  • wcSessionPaths seeded from localStorage at module load before signClient exists; validated later via restorePersistedSessions, but any early signTransaction fallback would use an unvalidated entry. Add a guard.
  • Dropping payParams.intent from the title fallback is a behavioral change — confirm no consumer used intent as a display title.
  • supportedWallets: any[] loses type safety on id/isAvailable; settlementMode as a string-literal type will misrepresent any future backend mode.

Verdict: mergeable. Fund-safety path verified clean. The multi-account live[0] P1 has genuine mis-send potential for WC users — worth fixing now or as an immediate follow-up.

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