Fix buy crash on wallets that return a numeric chainId

The chain guard did cur.toLowerCase() on the eth_chainId result. Per EIP-695
that's a hex string, but some wallets (Orlando's) return a number, so
cur.toLowerCase was undefined -> "cur.toLowerCase is not a function" aborted the
purchase. Compare chain ids numerically via a chainNum() normalizer (handles
hex string, decimal string, and number) in both the sendTx guard and ensureChain.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-09-08 11:51:42 -05:00
parent 2cc21457bd
commit 8be30bef13
3 changed files with 15 additions and 6 deletions
+13 -4
View File
@@ -6,6 +6,15 @@ window.IAPWallet = (function () {
const SEL_BUY = '0xfd095e97'; // buy(uint32,uint32)
const SEL_ACTIVATE = '0x1a93ec95'; // activate(uint32)
const pad = v => BigInt(v).toString(16).padStart(64, '0');
// Normalize a chainId to a decimal number. eth_chainId is meant to return a
// hex string, but some wallets return a number or a decimal string — compare
// numerically so a wallet's shape never crashes the flow.
const chainNum = v => {
if (v == null) return NaN;
if (typeof v === 'number') return v;
const s = String(v).trim();
return /^0x/i.test(s) ? parseInt(s, 16) : parseInt(s, 10);
};
const APPKIT_URL = 'https://cdn.jsdelivr.net/npm/@reown/appkit-cdn@1.8.23/dist/appkit.js';
let modal = null, akPromise = null, provider = null;
@@ -95,7 +104,7 @@ window.IAPWallet = (function () {
async function ensureChain(c) {
const want = '0x' + Number(c.chainId).toString(16);
let cur; try { cur = await eth().request({ method: 'eth_chainId' }); } catch (e) { return; }
if (cur === want) return;
if (chainNum(cur) === Number(c.chainId)) return;
try {
await eth().request({ method: 'wallet_switchEthereumChain', params: [{ chainId: want }] });
} catch (e) {
@@ -130,12 +139,12 @@ window.IAPWallet = (function () {
// AppKit's own modal) don't complete it. Never sign on the wrong chain —
// a value tx to a contract that doesn't exist on that chain would look like
// it "succeeded" while doing nothing.
const want = '0x' + Number(c.chainId).toString(16);
const wantNum = Number(c.chainId);
let cur; try { cur = await eth().request({ method: 'eth_chainId' }); } catch (e) {}
if (cur && cur.toLowerCase() !== want.toLowerCase()) {
if (!isNaN(chainNum(cur)) && chainNum(cur) !== wantNum) {
await ensureChain(c);
try { cur = await eth().request({ method: 'eth_chainId' }); } catch (e) {}
if (cur && cur.toLowerCase() !== want.toLowerCase())
if (!isNaN(chainNum(cur)) && chainNum(cur) !== wantNum)
throw new Error('Your wallet is on the wrong network. Switch it to ' + (c.chainName || 'the correct network') + ', then try again.');
}
const tx = { from: addr, to: c.contract, data };