fix(app): unblock wallet connect from social in-app browsers (X) - #5
Merged
Conversation
The LP-reward accounting fix added lp_user_info to four contexts, but the IDL committed in 8e4454d carried it for add_liquidity, claim_lp_rewards and remove_liquidity only. checkpoint_lp, the very subject of that commit, was left with 9 accounts while the deployed program (slot 477943093) expects 10. Confirmed against the production bundle, which serves the stale shape. It went unnoticed because LpEmissions.tsx passes lpUserInfo inside an `as any` cast, so TypeScript never saw the missing account, and the component is not mounted in page.tsx, so no tester could reach the path. Harmless today, broken the moment that component is wired back in. Resynced verbatim from target/idl/soladrome.json. Note the on-chain published IDL is stale too (checkpoint_lp with 9 accounts): cosmetic, affects explorers and third-party clients, fix with `anchor idl upgrade`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… dead end
Users arriving from a shared X link cannot connect a wallet at all, and the app
never tells them. The counter of on-chain wallets has not moved since 14/07 while
links circulate: 0 new wallets on 21/07 and 22/07, against 351 on 04/07.
The cause is one predicate in @solana/wallet-adapter-base. isIosAndRedirectable()
gates the Phantom and Solflare universal links on (iphone|ipad) && ua contains
"safari". X's iOS WebView reports "... Mobile/21E236 Twitter for iPhone/11.x",
with no safari token, so Phantom stays NotDetected and tapping it lands on
window.open('https://phantom.app') via WalletProviderBase, i.e. the App Store
page. The modal lists it as a normal option with no warning, because WalletModal
shows every non-installed wallet flat when none is Installed.
Android is the mirror image: X's WebView carries the `wv` token, so providers.tsx
keeps Phantom/Solflare, and MWA is offered rather than hidden. Its getIsSupported()
only tests isSecureContext && /android/i, with no WebView check, contrary to what
the comment there claimed. That comment is corrected here.
So we detect the in-app browser ourselves and hand the user the universal link the
adapters refused to build. Two guards matter:
- the decision is gated on CAPABILITY, not the UA: if any wallet is Installed we
never switch. A wallet's own in-app browser is a WebView too, and would
otherwise be misclassified.
- the URL is read at CLICK time, not at render, so the ?ref= referral captured
from the shared link survives the hop into the wallet browser.
Detection verified against 11 real user agents: X iOS, X Android, Instagram iOS
and Android WebView are caught; Safari iOS, CriOS, FxiOS, Chrome Android and
desktop are not.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
OxToF
added a commit
that referenced
this pull request
Jul 28, 2026
New "Meme Contest" campaign (#5) in the Missions card: post a meme on X tagging @soladrome (judged for the 5x 50 SOLA prize) and share it in the Discord #memes-art channel with your wallet. Submitting BOTH links credits +10 participation points and logs the entry for judging. - app/lib/quests.ts: MEME group + meme_contest quest, memeVerify flag, exported DISCORD_MEME_ART, group `link` field. - app/lib/xcode.ts: memeIntentUrl() + SOLADROME_HANDLE. - app/components/Quests.tsx: two-input submission panel (X + Discord). - app/app/api/meme-verify/route.ts: verifies the X post (oEmbed, tags @soladrome) + the Discord message (image via attachment OR embed, wallet in the same message via bot REST), dedup on the Discord message id. - supabase/quests.sql: meme_contest (+10), meme_submissions ledger + claim_meme_submission (stores both links). Prize (50 SOLA x5) is judged manually and paid out-of-band, like the bug bounty. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The problem
Visitors arriving from a shared X link cannot connect a wallet at all, and the app never tells them. It looks like a working page with two working buttons.
The on-chain wallet counter has not moved since 14/07 while links circulate. New wallets per day, from
quest_completions:The counter itself was verified correct (prod API returns the same number as a recomputation from the database, cache MISS). The ingestion is what stopped.
Root cause
isIosAndRedirectable()in@solana/wallet-adapter-basegates the Phantom/Solflare universal links on(iphone|ipad) && ua.includes('safari'). X's iOS WebView reports... Mobile/21E236 Twitter for iPhone/11.x— nosafaritoken. So:NotDetected→window.open('https://phantom.app')→ App Store page. Dead end.It works everywhere except exactly where the traffic comes from.
WalletModallists non-installed wallets flat when none isInstalled, so there is no warning either.Also corrects a false comment in
providers.tsx: MWA is not hidden in a WebView.getIsSupported()in@solana-mobile/wallet-adapter-mobile@2.2.9only testsisSecureContext && /android/i.The fix
Detect the in-app browser and hand the user the universal link the adapters refused to build. Two design points:
Installed, never switch. A wallet's own in-app browser is a WebView too and the UA alone would misclassify it.?ref=referral from the shared link survives into the wallet browser (verified end to end).Verification
Select Wallet, no console errors), in-app state shows the escape screenyarn buildpassesAlso carries a separate one-file commit: the IDL for
checkpoint_lpwas missinglp_user_info, so production served 9 accounts where the deployed program expects 10. Harmless today (the component is not mounted) but wrong.🤖 Generated with Claude Code