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_BUY = '0xfd095e97'; // buy(uint32,uint32)
const SEL_ACTIVATE = '0x1a93ec95'; // activate(uint32) const SEL_ACTIVATE = '0x1a93ec95'; // activate(uint32)
const pad = v => BigInt(v).toString(16).padStart(64, '0'); 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'; const APPKIT_URL = 'https://cdn.jsdelivr.net/npm/@reown/appkit-cdn@1.8.23/dist/appkit.js';
let modal = null, akPromise = null, provider = null; let modal = null, akPromise = null, provider = null;
@@ -95,7 +104,7 @@ window.IAPWallet = (function () {
async function ensureChain(c) { async function ensureChain(c) {
const want = '0x' + Number(c.chainId).toString(16); const want = '0x' + Number(c.chainId).toString(16);
let cur; try { cur = await eth().request({ method: 'eth_chainId' }); } catch (e) { return; } 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 { try {
await eth().request({ method: 'wallet_switchEthereumChain', params: [{ chainId: want }] }); await eth().request({ method: 'wallet_switchEthereumChain', params: [{ chainId: want }] });
} catch (e) { } catch (e) {
@@ -130,12 +139,12 @@ window.IAPWallet = (function () {
// AppKit's own modal) don't complete it. Never sign on the wrong chain — // 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 // a value tx to a contract that doesn't exist on that chain would look like
// it "succeeded" while doing nothing. // 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) {} 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); await ensureChain(c);
try { cur = await eth().request({ method: 'eth_chainId' }); } catch (e) {} 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.'); 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 }; const tx = { from: addr, to: c.contract, data };
+1 -1
View File
@@ -439,7 +439,7 @@
</section> </section>
<script src="/assets/common.js?v=20260908c"></script> <script src="/assets/common.js?v=20260908c"></script>
<script src="/assets/wallet.js?v=20260908q"></script> <script src="/assets/wallet.js?v=20260908r"></script>
<script src="/assets/home.js?v=20260906m"></script> <script src="/assets/home.js?v=20260906m"></script>
<script src="/assets/chat.js?v=20260906m"></script> <script src="/assets/chat.js?v=20260906m"></script>
</body> </body>
+1 -1
View File
@@ -695,7 +695,7 @@
</div> </div>
</div> </div>
<script src="/assets/common.js?v=20260908c"></script> <script src="/assets/common.js?v=20260908c"></script>
<script src="/assets/wallet.js?v=20260908q"></script> <script src="/assets/wallet.js?v=20260908r"></script>
<script src="/assets/my.js?v=20260908l"></script> <script src="/assets/my.js?v=20260908l"></script>
<script src="/assets/chat.js?v=20260907l"></script> <script src="/assets/chat.js?v=20260907l"></script>
</body> </body>