Skip to content

Fix MoonPay "Send with Edge" sell link#6056

Open
j0ntz wants to merge 1 commit into
developfrom
jon/moonpay-payment-deeplink
Open

Fix MoonPay "Send with Edge" sell link#6056
j0ntz wants to merge 1 commit into
developfrom
jon/moonpay-payment-deeplink

Conversation

@j0ntz

@j0ntz j0ntz commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

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)

Description

Asana task

Asana: https://app.asana.com/1/9976422036640/project/1207384676342554/task/1209649066660320

Fixes the MoonPay "Send with Edge" sell link. When a user starts a MoonPay sell order but has not completed the crypto deposit, MoonPay shows a "complete payment" button (in their email and in the buy.moonpay.com/trade_history page) that reflects back the deposit redirect URL our app hands MoonPay. That button dead-ended on a static "Redirecting to Payment..." page, so the user could not finish the deposit (the reported lead case is an XRP sell that also needs a destination tag).

Root cause (regression analysis). The redirect URL we pass to MoonPay is RETURN_URL_PAYMENT in src/plugins/gui/providers/common.ts. It has been https://edge.app/redirect/payment/ since it was introduced (Oct 2023); it was never a deep.edge.app value, so this is not a value regression. The apex edge.app host is not claimed as a universal link on iOS (ios/edge/edge.entitlements) or Android (AndroidManifest.xml) - only deep.edge.app, dl.edge.app, and return.edge.app are. The constant was designed as an in-app webview interception sentinel (uri.startsWith(RETURN_URL_PAYMENT)), which works in-app but cannot open the app from an external click. The buy redirects already use deep.edge.app; only the sell payment redirect used the unclaimed apex.

Fix.

  • Point RETURN_URL_PAYMENT at the claimed deep.edge.app host, matching the buy redirects. In-app interception is host-agnostic (prefix startsWith), so the existing webview flows (MoonPay and Paybis, ramp and legacy) are unaffected.
  • Parse the redirect/payment deep link into a new paymentRedirect link type and route it to the Send scene, resolving the wallet from the base currency code and pre-filling the deposit address, amount, and destination tag/memo (via uniqueIdentifier). Both the deep.edge.app and legacy edge.app hosts are parsed.

No new user-facing strings; reuses the existing Send scene and wallet picker.

Testing.

  • Unit tests for the parser (real-world MoonPay URL, XRP with destination tag, deep.edge.app host, and missing-param browser fallback).
  • verify-repo.sh (eslint + jest) passes; tsc clean.
  • Driven on the iOS simulator: firing edge://redirect/payment/?baseCurrencyCode=btc&baseCurrencyAmount=0.001&depositWalletAddress=bc1q... opens the wallet picker (all BTC wallets) and then the Send scene pre-filled with the deposit address and 0.001 BTC. Screenshots below. The slider is not confirmed (no broadcast).

Note

Medium Risk
Changes fiat ramp redirect URLs and deep-link routing into Send with pre-filled amounts and memos; mistakes could mis-route deposits or break in-flight sell orders, though legacy URL matching and strict param validation reduce exposure.

Overview
Fixes MoonPay "Send with Edge" (and similar ramp sell) links that dead-ended outside the app by moving provider redirect URLs to the claimed deep.edge.app host and teaching the app to handle /redirect/payment/ end-to-end.

Redirect URLs in common.ts now default to https://deep.edge.app/redirect/... (payment, success, fail, cancel). A shared isReturnUrl matcher accepts both that host and legacy https://edge.app/redirect/... so in-WebView interceptors (MoonPay, Paybis, Banxa; GUI + ramp plugins) still catch orders created before the switch.

Deep links: DeepLinkParser adds paymentRedirect parsing (with validation for blank/invalid amount and memo) and treats success/fail/cancel as no-op app opens. DeepLinkingActions handles paymentRedirect by resolving wallets from the provider currency symbol (native + custom tokens), then opening Send with deposit address, converted amount, and destination tag.

Tests cover parser cases and isReturnUrl; CHANGELOG updated.

Reviewed by Cursor Bugbot for commit fd3bad0. Bugbot is set up for automated code reviews on this repo. Configure here.

@j0ntz

j0ntz commented Jun 24, 2026

Copy link
Copy Markdown
Contributor Author

📸 Test evidence (iOS sim)

agent proof 1209649066660320 01 wallet picker

agent proof 1209649066660320 01 wallet picker

agent proof 1209649066660320 02 send prefilled

agent proof 1209649066660320 02 send prefilled

Captured by the agent's in-app test run (build-and-test).

Comment thread src/util/DeepLinkParser.ts
Comment thread src/actions/DeepLinkingActions.tsx Outdated
@j0ntz j0ntz force-pushed the jon/moonpay-payment-deeplink branch from 676c146 to 961a3fb Compare June 24, 2026 23:35
@j0ntz j0ntz force-pushed the jon/moonpay-payment-deeplink branch from 961a3fb to bf4d1ea Compare July 9, 2026 21:31
Comment thread src/plugins/gui/providers/common.ts Outdated
@j0ntz j0ntz force-pushed the jon/moonpay-payment-deeplink branch from bf4d1ea to d2676b2 Compare July 9, 2026 21:42

@claude claude 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.

Claude Code Review

Claude Code Review is paused for this repository. To reconnect it, an admin of this repository's GitHub organization (or the account owner, for personal repositories) who can also manage your Claude organization's Code Review settings needs to re-link GitHub in Code Review settings. This is a one-time step.

Tip: disable this comment in your organization's Code Review settings.

@j0ntz j0ntz force-pushed the jon/moonpay-payment-deeplink branch from d2676b2 to 88e8509 Compare July 9, 2026 21:49
Comment thread src/actions/DeepLinkingActions.tsx Outdated
Comment thread src/util/DeepLinkParser.ts Outdated
Comment thread src/actions/DeepLinkingActions.tsx
Comment thread src/actions/DeepLinkingActions.tsx
Comment thread src/util/DeepLinkParser.ts Outdated
Comment thread src/util/DeepLinkParser.ts
Comment thread src/actions/DeepLinkingActions.tsx
Comment thread src/plugins/gui/providers/common.ts Outdated
@j0ntz j0ntz force-pushed the jon/moonpay-payment-deeplink branch from 88e8509 to 2b9c97f Compare July 10, 2026 19:28
Comment thread src/util/DeepLinkParser.ts Outdated
@j0ntz j0ntz force-pushed the jon/moonpay-payment-deeplink branch from 2b9c97f to a654892 Compare July 10, 2026 19:48

@cursor cursor 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.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit a654892. Configure here.

Comment thread src/util/DeepLinkParser.ts
MoonPay surfaces a "Send with Edge" button for pending sell orders (in
their email and order-history page) that reflects back the deposit
redirect URL our app hands them. That URL was RETURN_URL_PAYMENT =
https://edge.app/redirect/payment/, but the apex edge.app host is NOT
claimed as a universal link on iOS or Android (only deep.edge.app, dl,
and return are), so the button dead-ended on a static redirect page and
the user could not complete the deposit. The buy redirects already use
deep.edge.app; only the sell payment redirect used the unclaimed apex.

Point RETURN_URL_PAYMENT at the claimed deep.edge.app host (in-app
webview interception is host-agnostic via startsWith, so it is
unaffected) and parse the redirect/payment deep link into a new
paymentRedirect link that opens the Send scene, resolving the wallet
from the base currency code and pre-filling the deposit address, amount,
and destination tag (uniqueIdentifier).

Give the sibling ramp redirect URLs the same treatment: RETURN_URL_SUCCESS,
RETURN_URL_FAIL, and RETURN_URL_CANCEL now also live on the claimed
deep.edge.app host (was the apex edge.app), so an externally-reflected
terminal redirect opens the app instead of dead-ending. The host swap is
symmetric for the in-webview interception (Banxa matches by exact ===,
Paybis/MoonPay by startsWith), so no ramp flow changes behavior. These
terminal states carry no actionable payload, so the deep-link parser
resolves edge://redirect/{success,fail,cancel} to a no-op rather than the
former "Unknown deep link format" error, on the edge://, deep.edge.app,
and legacy apex edge.app hosts.
@j0ntz j0ntz force-pushed the jon/moonpay-payment-deeplink branch from a654892 to fd3bad0 Compare July 10, 2026 19:54
@j0ntz

j0ntz commented Jul 10, 2026

Copy link
Copy Markdown
Contributor Author

📸 Test evidence — payment-redirect deep link drives a populated Send scene (on-sim, slot UDID 15772779), plus cancel redirect no-ops with no error

agent proof 1209649066660320 01 payment send scene populated

agent proof 1209649066660320 01 payment send scene populated

agent proof 1209649066660320 02 wallet picker eth

agent proof 1209649066660320 02 wallet picker eth

agent proof 1209649066660320 03 cancel noop no error

agent proof 1209649066660320 03 cancel noop no error

Captured by the agent's in-app test run (build-and-test).

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