No login screen inside MiniPay, not even for a frame - #225
Merged
Conversation
OWNER, testing in MiniPay: *"masih sempet muncul halaman loginnya, meskipun
sekedip langsung hilang, tetapi masih muncul, itu betulan mengganggu kedepannya
jika game ku berhasil listing."* Right on both counts. A screen between the
player and the game is what MiniPay's listing rules reject, and "only for a
moment" is not a defence.
The rule was never wrong; the TIMING was. `isMiniPay` is read from
window.ethereum inside WagmiIsland, and lib/Web3Providers.tsx mounts that island
on requestIdleCallback with a 1500ms ceiling. Until it mounts the bridge serves
its defaults — `isMiniPay: false` — so shouldOfferSignIn() answered "yes, ask
them" to a MiniPay player for up to a second and a half.
The obvious fix was to hold the gate until `walletReady`. It was written,
measured, and thrown away:
inside MiniPay gate never appeared ✓
outside map at 50ms, gate at 1272ms ✗
A login landing on top of a map the player has been looking at for a second is
the FIRST complaint wearing a different hat. So the wait is gone and the
guarantee moved to where it costs nothing: privyGateFlag reads
window.ethereum.isMiniPay directly, needs nothing mounted, and is therefore
right on the very first render. It runs before the query-string override too —
there is no argument for a URL that can force a login screen into MiniPay.
A synchronous read has exactly one failure mode: a provider injected a moment
late. So the flag is re-evaluated every 100ms for 1.5s, the same ceiling wagmi
gets, and it can only ever flip the gate OFF.
Measured after the change, polling every 30ms for 5 seconds against a build
carrying a real app id:
inside MiniPay 0 of 165 polls — never appeared
outside appears, as it should
Verified: tsc clean, build unchanged at 142/242 kB, 27/27 test:privy,
check:copy clean, lint 35.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017A764RdnwpyWnG7uCNhMiQ
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
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 owner found this by opening the game inside MiniPay: the login screen appeared and vanished. He is right that it matters — a screen between the player and the game is what MiniPay's listing rules reject, and "only for a moment" is not a defence.
The rule was never wrong. The timing was.
isMiniPayis read fromwindow.ethereuminsideWagmiIsland, andlib/Web3Providers.tsxmounts that island onrequestIdleCallbackwith a 1500 ms ceiling. Until it mounts, the bridge serves its defaults —isMiniPay: false— soshouldOfferSignIn()answered "yes, ask them" to a MiniPay player for up to a second and a half.The obvious fix was measured and thrown away
Holding the gate until
walletReady:A login landing on top of a map the player has already been looking at for a second is the first complaint wearing a different hat. So the wait is gone.
Where the guarantee lives instead
privyGateFlagreadswindow.ethereum.isMiniPaydirectly. It needs nothing mounted — MiniPay injects the provider before page scripts run — so it is correct on the very first render, which is exactly the window the gate was flashing in. It runs before the query-string override, because there is no argument for a URL that can force a login screen into MiniPay.A synchronous read has one failure mode: a provider injected a moment late. So the flag is re-evaluated every 100 ms for 1.5 s — the same ceiling wagmi gets — and it can only ever flip the gate off. Three independent guards now, and every one of them is one-way.
Measured after the change
Polling every 30 ms for 5 seconds, against a build carrying a real app id:
Testing
The screen itself did not change, so the previously approved screenshot still stands.
One thing this does not fix, reported separately rather than buried here: outside MiniPay the world map is in the prerendered HTML, so it paints before any JavaScript runs and is briefly visible under the gate. That is deliberate — it is what
/game's LCP optimisation buys — and removing it would cost MiniPay its fast first paint. Worth a decision, not a silent change.Generated by Claude Code