Skip to content

Route MoonPay iOS buys through a Private Relay interstitial check - #6151

Open
j0ntz wants to merge 2 commits into
developfrom
jon/moonpay-relay-interstitial
Open

Route MoonPay iOS buys through a Private Relay interstitial check#6151
j0ntz wants to merge 2 commits into
developfrom
jon/moonpay-relay-interstitial

Conversation

@j0ntz

@j0ntz j0ntz commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Technical Design Document

moonpay-private-relay-interstitial.md

CHANGELOG

Does this branch warrant an entry to the CHANGELOG?

  • Yes
  • No

Dependencies

EdgeApp/edge-info-server#160 (soft dependency: without it the app falls back to today's bound flow, so this PR is safe to land first)

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)

No visual changes: the buy flow's screens are unchanged; only the URL handed to the external Safari view differs.

Description

Asana task

Closes the iCloud Private Relay gap in the MoonPay iOS buy flow. iOS buy opens the widget in an SFSafariViewController whose traffic can egress through Private Relay, so the widget URL bound to the app-fetch IP mismatches what MoonPay observes for relay users; once MoonPay enforces IP matching, those buys fail with an Unverified Connection error.

  • iOS buy now asks the info server for a relay-check interstitial URL (fetchMoonpayInterstitialUrl) and opens that in the Safari view. The server observes the Safari view's own egress and 302s to the widget URL signed with the IP binding when the addresses agree, or without it when they diverge (relay detected). The app never handles an IP.
  • Any interstitial failure (server without relay-check support, network error, malformed response) falls back to today's bound flow, so this cannot regress buys even against un-upgraded servers.
  • Sell and Android buy are untouched (app networking stack / Custom Tabs; relay never applies).
  • MOONPAY_RELAY_CHECK_SIGN_PROXY (env.json, dev builds only, __DEV__-gated) reroutes the one relay-check POST through an alternate egress so the unbound branch is reproducible on a simulator.
  • The TDD linked above documents both repos' changes, including the token design and the outcomes matrix.

The physical-device pass (iCloud+ account with Private Relay enabled) is a manual item; MoonPay IP-match enforcement for our key stays off until it completes.


Note

Medium Risk
Changes the critical fiat on-ramp URL path for all iOS MoonPay buys; fallback to bound signing limits regression risk if the info server is behind.

Overview
iOS MoonPay buys no longer open a directly IP-bound signed widget URL in SFSafariViewController. They call fetchMoonpayInterstitialUrl (relayCheck: true) so the info server can compare app vs Safari egress and redirect to a bound or unbound signed widget. Any failure (old server, network, bad response) falls back to signMoonpayUrl as today.

Android buy and sell still use the direct bound signing path only.

Adds MOONPAY_RELAY_CHECK_SIGN_PROXY in envConfig (dev-only via __DEV__) to route the relay-check POST through alternate egress for simulator testing of the unbound branch.

CHANGELOG entry and src/docs/moonpay-private-relay-interstitial.md document the cross-repo design (depends on edge-info-server#160).

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

@j0ntz

j0ntz commented Aug 13, 2026

Copy link
Copy Markdown
Contributor Author

📸 Test evidence

moonpay buy quotes

moonpay buy quotes

safari widget fallback bound

safari widget fallback bound

safari interstitial unbound

safari interstitial unbound

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

@j0ntz
j0ntz force-pushed the jon/moonpay-relay-interstitial branch 2 times, most recently from 1c042b5 to 4cf563e Compare August 13, 2026 20:19
@j0ntz
j0ntz marked this pull request as ready for review August 13, 2026 20:21
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@j0ntz
j0ntz force-pushed the jon/moonpay-relay-interstitial branch from 4cf563e to bbb7713 Compare August 13, 2026 20:22
iOS buy opens the MoonPay widget in an SFSafariViewController whose
traffic can egress through iCloud Private Relay, so a widget URL bound
to the app-fetch IP mismatches what MoonPay observes for relay users
and will fail their buys once IP-match enforcement turns on.

The buy path now asks the info server for a relay-check interstitial
URL and opens that in the Safari view: the server observes the Safari
view's own egress and 302s to the widget URL signed with the IP binding
when the addresses agree, or without it when they diverge. Any
interstitial failure falls back to today's bound flow, so the change
cannot regress buys even against servers without relay-check support.
Sell and Android are untouched.

MOONPAY_RELAY_CHECK_SIGN_PROXY (dev builds only) reroutes the one
relay-check POST through an alternate egress so the unbound branch is
reproducible on a simulator. The TDD at
src/docs/moonpay-private-relay-interstitial.md documents both repos'
changes.
@j0ntz
j0ntz force-pushed the jon/moonpay-relay-interstitial branch 4 times, most recently from 83ca9f4 to 18a9532 Compare August 13, 2026 23:59
@j0ntz
j0ntz force-pushed the jon/moonpay-relay-interstitial branch from 18a9532 to aab11af Compare August 14, 2026 07:22

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

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