Skip to content

Conversation

@Fabcien
Copy link

@Fabcien Fabcien commented Feb 9, 2026

Cashtab will still be called via a redirection if no app handles the link first. This makes this code compatible with both mobile and desktop with no special case.

Works together with PayButton/paybutton-server#1106.

Summary by CodeRabbit

  • New Features
    • Added deeplink support for XEC payments, enabling seamless browser-to-payment-app flow for enhanced transaction processing.

Cashtab will still be called via a redirection if no app handles the link first. This makes this code compatible with both mobile and desktop with no special case.

Works together with PayButton/paybutton-server#1106.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 9, 2026

📝 Walkthrough

Walkthrough

The pull request adds a convertBip21ToDeeplink helper function to transform BIP21 URLs into PayButton deeplink URLs. The handleButtonClick function is updated for XEC addresses to generate a deeplink and call openCashtabPayment with both the original URL and deeplink, enabling direct browser-to-payment-app flow.

Changes

Cohort / File(s) Summary
BIP21 Deeplink Conversion
react/lib/components/Widget/Widget.tsx
Added convertBip21ToDeeplink helper function to convert BIP21 URLs to PayButton deeplinks. Updated handleButtonClick for XEC addresses to generate deeplinks and pass both original URL and deeplink to openCashtabPayment, enabling payment app integration.

Sequence Diagram

sequenceDiagram
    participant User
    participant Widget as Widget Component
    participant Converter as BIP21 Converter
    participant Cashtab as Cashtab Payment

    User->>Widget: Click PayButton (XEC Address)
    Widget->>Widget: handleButtonClick triggered
    Widget->>Converter: convertBip21ToDeeplink(bip21Url)
    Converter-->>Widget: deeplink URL
    Widget->>Cashtab: openCashtabPayment(bip21Url, deeplink)
    Cashtab-->>User: Open Payment App
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A link through the BIP21 haze,
Now deepens to payment app days,
From browser to wallet so fine,
One click and the coins align,
Cashtab flows in quantum praise! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The description is incomplete. Required template sections like 'Related to #', 'Test plan', and detailed 'Description' are missing or minimal. Complete the description template by filling in related issues, providing a detailed description of changes, and outlining the test plan for the deeplink functionality.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically summarizes the main change: generating deeplinks instead of calling Cashtab directly, which aligns with the actual code modifications.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
react/lib/components/Widget/Widget.tsx (1)

949-969: Consider extracting convertBip21ToDeeplink outside the component.

This is a pure function with no dependency on component state or props. Defining it inside the component body means it's recreated on every render. Move it to module scope (or a utility file) to avoid unnecessary allocations.

Also, bip21Url.split('?') will silently truncate everything after a second ? character. While this is unlikely given how resolveUrl constructs the URL today, using the URL or a single indexOf('?') + substring approach would be more robust:

♻️ Suggested refactor
-  const convertBip21ToDeeplink = (bip21Url: string): string => {
-    // Parse BIP21 URL: ecash:address?amount=100&opreturnraw=xxx
-    const [addressPart, queryPart] = bip21Url.split('?')
-    const params = new URLSearchParams()
-    params.set('address', addressPart)
-    
-    if (queryPart) {
-      const queryParams = new URLSearchParams(queryPart)
-      // Add all query parameters from the BIP21 string
-      queryParams.forEach((value, key) => {
-        params.set(key, value)
-      })
-    }
-    
-    // Add b=1 to the deeplink URL to indicate that the payment app should move
-    // back to the browser after the payment is complete.
-    params.set('b', '1')
-    
-    // Return absolute URL for the deeplink
-    return `https://paybutton.org/app?${params.toString()}`
-  }

At module scope (before the component):

function convertBip21ToDeeplink(bip21Url: string): string {
  const qIndex = bip21Url.indexOf('?')
  const params = new URLSearchParams()

  if (qIndex === -1) {
    params.set('address', bip21Url)
  } else {
    params.set('address', bip21Url.substring(0, qIndex))
    const queryParams = new URLSearchParams(bip21Url.substring(qIndex + 1))
    queryParams.forEach((value, key) => {
      params.set(key, value)
    })
  }

  params.set('b', '1')
  return `https://paybutton.org/app?${params.toString()}`
}

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Klakurka Klakurka self-requested a review February 9, 2026 21:01
@Klakurka Klakurka added the enhancement (UI/UX/feature) New feature or request label Feb 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement (UI/UX/feature) New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants