Fix MoonPay "Send with Edge" sell link#6056
Conversation
676c146 to
961a3fb
Compare
961a3fb to
bf4d1ea
Compare
bf4d1ea to
d2676b2
Compare
There was a problem hiding this comment.
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.
d2676b2 to
88e8509
Compare
88e8509 to
2b9c97f
Compare
2b9c97f to
a654892
Compare
a654892 to
fd3bad0
Compare
📸 Test evidence — payment-redirect deep link drives a populated Send scene (on-sim, slot UDID 15772779), plus cancel redirect no-ops with no erroragent proof 1209649066660320 01 payment send scene populated agent proof 1209649066660320 02 wallet picker eth agent proof 1209649066660320 03 cancel noop no error Captured by the agent's in-app test run (build-and-test). |
fd3bad0 to
dba233e
Compare
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.
dba233e to
77117ab
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 77117ab. Configure here.
| const rawAmount = query.baseCurrencyAmount ?? undefined | ||
| const amountNum = rawAmount != null ? Number(rawAmount) : Number.NaN | ||
| const amount = | ||
| Number.isFinite(amountNum) && amountNum > 0 ? rawAmount : undefined |
There was a problem hiding this comment.
Padded amount passes parser, breaks mul
Medium Severity
parsePaymentRedirect treats baseCurrencyAmount as valid when Number(rawAmount) is finite and positive, but still forwards the untrimmed query string as amount. Values that JavaScript parses successfully (leading or trailing whitespace, some exponential forms) can fail in biggystring mul after the wallet picker, surfacing an error instead of opening Send without an amount like other rejected amounts.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 77117ab. Configure here.







CHANGELOG
Does this branch warrant an entry to the CHANGELOG?
Dependencies
none
Requirements
If you have made any visual changes to the GUI. Make sure you have:
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_historypage) 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_PAYMENTinsrc/plugins/gui/providers/common.ts. It has beenhttps://edge.app/redirect/payment/since it was introduced (Oct 2023); it was never adeep.edge.appvalue, so this is not a value regression. The apexedge.apphost is not claimed as a universal link on iOS (ios/edge/edge.entitlements) or Android (AndroidManifest.xml) - onlydeep.edge.app,dl.edge.app, andreturn.edge.appare. 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 usedeep.edge.app; only the sell payment redirect used the unclaimed apex.Fix.
RETURN_URL_PAYMENTat the claimeddeep.edge.apphost, matching the buy redirects. In-app interception is host-agnostic (prefixstartsWith), so the existing webview flows (MoonPay and Paybis, ramp and legacy) are unaffected.redirect/paymentdeep link into a newpaymentRedirectlink 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 (viauniqueIdentifier). Both thedeep.edge.appand legacyedge.apphosts are parsed.No new user-facing strings; reuses the existing Send scene and wallet picker.
Testing.
deep.edge.apphost, and missing-param browser fallback).verify-repo.sh(eslint + jest) passes;tscclean.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
External deep links now drive the Send flow with provider-supplied addresses and amounts; guards reduce bad pre-fills, but users still must confirm the transaction and ticker collisions rely on wallet picker disambiguation.
Overview
Fixes MoonPay "Send with Edge" (and similar ramp sell flows) when users tap complete payment links outside the app—those links used to hit an unclaimed
edge.apphost and dead-end instead of opening Edge.Redirect URLs for payment, success, fail, and cancel now use the claimed
deep.edge.apphost (matching buy flows).isReturnUrlcentralizes WebView interception so bothdeep.edge.appand legacyedge.appURLs still work for in-flight orders.Deep linking:
/redirect/payment/parses to a newpaymentRedirecttype with deposit address, optional amount, and memo/tag; invalid or blank required params become a no-op instead of errors or browser fallback.success/fail/cancelopen the app as no-ops. Handling resolves assets by currency symbol (native + tokens, including custom), runs the wallet picker when needed, converts amounts safely, then opens Send pre-filled via the existing URI path.Unit tests cover parsing, return-URL matching, and edge cases (XRP tag, bad amounts, missing params).
Reviewed by Cursor Bugbot for commit 77117ab. Bugbot is set up for automated code reviews on this repo. Configure here.