MEW Wallet obfuscates MoonPay purchase URLs using a 3-layer anti-bot scheme.
This doc explains the decryption flow step by step so your dev can replicate it in any language.
| Layer | What it does |
|---|---|
| 1. MEW /buy endpoint | Returns a form URL with a short-lived token |
| 2. MEW /form/moonpay | Returns obfuscated JS — XOR arrays + positions + verify token |
| 3. MEW /form/verify | Returns XOR key k after server-side validation |
| XOR decrypt | Client-side: XOR arrays with key → positions → MoonPay URL |
This returns JSON with all provider entries. Grab the MoonPay form URL.
curl -s 'https://mainnet.mewwallet.dev/v5/purchase/buy?id=0x7dcf9a8ebbb9f59881ed9d64d30a22e64af2e6cb&address=YOUR_WALLET&fiatCurrency=USD&amount=150&cryptoCurrency=USDC&chain=POL&iso=US&platform=web' \
-H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36' \
-H 'Accept: */*'
Extract: .url field from the MOONPAY entry → parse token=XYZ from it.
Request the form page with the token. Extract the inline <script> tag.
curl -s 'https://mainnet.mewwallet.dev/v5/purchase/form/moonpay?token=TOKEN_FROM_STEP1' \
-H 'User-Agent: Mozilla/5.0 ...' \
-H 'Referer: https://mainnet.mewwallet.dev/v5/purchase/buy?...'
Parse from the script tag:
const arrays = [[...], [...]]; — JSON 2D array of XOR-encoded stringsconst positions = '...'; — character position instruction stringget('/v5/purchase/form/verify?token=VERIFY_TOKEN') — verify token for step 3k
curl -s 'https://mainnet.mewwallet.dev/v5/purchase/form/verify?token=VERIFY_TOKEN' \
-H 'User-Agent: Mozilla/5.0 ...' \
-H 'Referer: https://mainnet.mewwallet.dev/v5/purchase/buy?...' \
-H 'Origin: https://mainnet.mewwallet.dev'
Response: {"k": "abc123...", ...}
With arrays, positions, and k:
arrays: XOR each substring with key k at the corresponding indexpositions, pick characters out of the decoded result to build the final URLSee decrypt.js for the exact algorithm — it's the same for all providers.
Pass JSON on stdin: {"arrays": [...], "positions": "...", "k": "..."}
echo '{"arrays":[[...],[...]],"positions":"...","k":"..."}' | node decrypt.js
Output: the fully resolved MoonPay purchase URL.
| File | Purpose |
|---|---|
decrypt.js | XOR decryptor (Node.js, no deps) |
server.py | Flask server — orchestrates steps 1-4, exposes /api/generate |
index.html | Web UI (standalone — works locally without server) |
cd mew-moonpay-generator
python3 server.py # Flask on :8080 — needs decrypt.js + internet
# OR just open index.html in browser # standalone — calls the same /api/generate
If you want to skip Node.js, the XOR decrypt is trivial to port:
import json
def xor_decrypt(arrays, positions, k):
results = []
for pair in arrays:
parts = []
for i, s in enumerate(pair):
key_char = k[i % len(k)]
decoded = ''.join(chr(ord(c) ^ ord(key_char)) for c in s)
parts.append(decoded)
results.append(''.join(parts))
# Build URL from decoded results and position instructions
url = ''
for pos in positions.split(','):
num = int(pos)
which = '' # positive → result index, negative → char index
url += results[abs(num)]
return url
Exact implementation is in decrypt.js — translate the 15-line function.