Skip to content

A Google player can pay, and no MiniPay player pays for it - #232

Merged
0xward merged 1 commit into
mainfrom
claude/nullstate-onchain-text-q6g2a3
Aug 3, 2026
Merged

A Google player can pay, and no MiniPay player pays for it#232
0xward merged 1 commit into
mainfrom
claude/nullstate-onchain-text-q6g2a3

Conversation

@0xward

@0xward 0xward commented Aug 3, 2026

Copy link
Copy Markdown
Owner

Reading Chessify (jadonamite/playchessify) was worth it — it is Privy + wagmi on Celo, and its Privy config is almost character-for-character the one merged an hour ago. But neither half of its architecture copies over, and both refusals are load-bearing.

It wraps the whole app in PrivyProvider. That would ship the Privy SDK to every MiniPay player, for a screen they are never shown, on the connections least able to afford the download — the exact cost WagmiIsland and walletBridge were built to avoid. So this follows the same shape instead: an island beside the app, publishing into an always-mounted context that imports neither Privy nor viem. /game grew 1 kB.

It pairs Privy with ERC-4337 and a Pimlico bundler so social players never need gas. On Celo that solves a problem the chain already solved: CIP-64 pays gas in the stablecoin being spent, and this app has done that since the MiniPay work. A player holding USDT and no CELO can buy with no bundler, no sponsor, and nothing to keep funded.

The shape

piece what it costs
lib/privySignerBridge.tsx context only — no SDK, always mounted, ~0
components/game/PrivySignerIsland.tsx lazy; mounts only when readPrivyGateFlag() is true
PrivySignerPublisher renders nothing; publishes a Celo-pinned client + payToTreasury

The island lives for the whole session — which the login screen cannot, since it unmounts the moment the player signs in. That was the actual blocker: a provider that dies with the gate can't sign at the shop an hour later.

Order matters in exactly one place

Privy's docs are explicit that switchChain does not update providers already handed out. So the wallet is moved to Celo before its EIP-1193 provider is taken. The other order returns a client that still signs for the old chain — precisely the failure hit in OKX.

Precedence, and the line that does not move

wagmi's wallet wins whenever there is one: a player who connected MiniPay or a browser wallet has said which wallet they mean. Privy's is used only when there is no other. Both spend paths resolve through one selector, so they cannot disagree.

address still resolves realAddress → authAddress → guestAddress. The save is keyed on the address derived in lib/authIdentity.ts, and re-pointing it at the embedded wallet would orphan every document already stored under it. The embedded wallet is where money comes from; it is not who the player is.

All four kinds of player, side by side

player signs with
MiniPay wagmi (injected) — untouched
Browser wallet (OKX, MetaMask) wagmi + auto-switch to Celo
Google / email via Privy embedded wallet, gas in stablecoin
Guest cannot spend, as before

Testing

✓ 17/17 test:privypay (new)   ✓ 24/24 test:privy   ✓ 20/20 test:network
✓ tsc clean   ✓ build 143/242 kB (+1 kB, the context)
✓ check:copy  ✓ lint 35

Not covered, stated rather than implied: no real Privy wallet signs anything here, because the sandbox has none. The assertions are source-level, including one that fails if anyone reintroduces an account-abstraction import.

Still open

Where the USDT comes from. Gas is solved; the price is not. A fresh embedded wallet still holds nothing — that decision is the owner's and is not made here.


Generated by Claude Code

OWNER: *"harus bisa pembayaran juga lewat privy"* … *"lanjut pakai CIP-64 aja,
jangan smart wallet."*

The owner pointed at Chessify (jadonamite/playchessify) as the model. Reading it
was worth it — it is Privy + wagmi on Celo, and its Privy config is almost
character-for-character the one merged an hour ago. But neither half of its
architecture copies over, and both refusals are load-bearing:

  · It wraps the WHOLE APP in PrivyProvider. That would ship the Privy SDK to
    every MiniPay player, for a screen they are never shown, on the connections
    least able to afford the download — the exact cost lib/WagmiIsland.tsx and
    lib/walletBridge.tsx were built to avoid. So this follows the same shape
    instead: an island beside the app, publishing into an always-mounted
    context that imports neither Privy nor viem. /game grew 1 kB.

  · It pairs Privy with ERC-4337 and a Pimlico bundler so social players never
    need gas. On Celo that solves a problem the chain already solved: CIP-64
    pays gas in the stablecoin being spent, and this app has done that since
    the MiniPay work (pickBestFeeCurrency). A player holding USDT and no CELO
    can buy with no bundler, no sponsor, and nothing to keep funded.

THE SHAPE. lib/privySignerBridge.tsx is context only — no SDK, always mounted,
costs nothing. components/game/PrivySignerIsland.tsx is lazy, mounts only when
readPrivyGateFlag() says yes (false inside MiniPay, false with no app id, false
by default), renders no UI, and lives for the whole session — which the login
screen cannot, since it unmounts the moment the player is signed in.

ORDER MATTERS IN ONE PLACE. Privy's docs are explicit that switchChain does not
update providers already handed out. So the wallet is moved to Celo BEFORE its
EIP-1193 provider is taken; the other order returns a client that still signs
for the old chain, which is precisely the failure the owner hit in OKX.

PRECEDENCE. wagmi's wallet wins whenever there is one — a player who connected
MiniPay or a browser wallet has said which wallet they mean. Privy's is used
only when there is no other. Both spend paths resolve through one selector, so
they cannot disagree.

AND ONE LINE THAT DOES NOT MOVE. `address` still resolves realAddress →
authAddress → guestAddress. The save is keyed on the address derived in
lib/authIdentity.ts, and re-pointing it at the embedded wallet would orphan
every document already stored under it. The embedded wallet is where money
comes FROM; it is not who the player IS.

Verified: 17/17 test:privypay, 24/24 test:privy, 20/20 test:network, tsc clean,
build 143/242 kB (+1 kB, the context), check:copy clean, lint 35.

NOT covered, and stated rather than implied: no real Privy wallet signs
anything here, because the sandbox has none. The assertions are source-level.

Still unanswered, and the owner's to answer: where the USDT comes from. Gas is
solved; the price is not.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017A764RdnwpyWnG7uCNhMiQ
@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.

@vercel

vercel Bot commented Aug 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
nullstate Ready Ready Preview Aug 3, 2026 7:11am

@0xward
0xward merged commit 567fb76 into main Aug 3, 2026
5 checks passed
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