> ## Documentation Index
> Fetch the complete documentation index at: https://docs.immutable.com/llms.txt
> Use this file to discover all available pages before exploring further.

# FAQ

# Frequently Asked Questions

Common questions and solutions for build issues, authentication, transactions, and debugging with the TypeScript SDK.

## Build & Environment

> [accordion] "Buffer is not defined" or "process is not defined"
>
> Modern bundlers don't include Node.js polyfills by default.
>
> **Vite:**
>
> ```bash theme={null}
> npm install vite-plugin-node-polyfills
> ```
>
> ```typescript theme={null}
> // vite.config.ts
> import { nodePolyfills } from 'vite-plugin-node-polyfills';
>
> export default defineConfig({
>   plugins: [
>     nodePolyfills({
>       include: ['buffer', 'crypto', 'stream', 'util'],
>     }),
>   ],
> });
> ```
>
> **Next.js / Create React App:**
>
> ```typescript theme={null}
> // Add to top of your entry file
> import { Buffer } from 'buffer';
> if (typeof window !== 'undefined') {
>   window.Buffer = Buffer;
> }
> ```

> [accordion] "crypto is not defined"
>
> Add global polyfill to your bundler config:
>
> ```typescript theme={null}
> // vite.config.ts
> export default defineConfig({
>   define: {
>     global: 'globalThis',
>   },
> });
> ```

> [accordion] Module resolution issues or type errors
>
> Ensure `tsconfig.json` uses modern module resolution:
>
> ```json theme={null}
> {
>   "compilerOptions": {
>     "moduleResolution": "bundler", // or "node16"
>     "esModuleInterop": true
>   }
> }
> ```

> [accordion] Next.js: "Cannot find module" or ESM errors
>
> Import from modular packages instead of the umbrella SDK:
>
> ```typescript theme={null}
> // ❌ May cause issues with App Router
> import { config, auth } from '@imtbl/sdk';
>
> // ✅ Works correctly - use modular packages
> import { Auth } from '@imtbl/auth';
> import { connectWallet } from '@imtbl/wallet';
> import { Environment } from '@imtbl/config';
> ```
>
> If you see elliptic package errors, add to `next.config.js`:
>
> ```javascript theme={null}
> const nextConfig = {
>   experimental: {
>     esmExternals: false,
>   },
> };
> ```

> [accordion] Bundle size is too large
>
> Import modular packages instead of the umbrella package:
>
> ```typescript theme={null}
> // ❌ Imports everything
> import { auth, orderbook } from '@imtbl/sdk';
>
> // ✅ Imports only what you need
> import { Auth } from '@imtbl/auth';
> import { Orderbook } from '@imtbl/orderbook';
> ```
>
> > [!TIP]
> >
> > Using modular packages can significantly reduce your bundle size by importing only what you need.

> [accordion] Module resolution errors, dependency conflicts, or build failures
>
> Clear your cache and reinstall dependencies:
>
> ```bash theme={null}
> # Remove node_modules and package lock
> rm -rf node_modules package-lock.json
>
> # Clear npm cache
> npm cache clean --force
>
> # Reinstall dependencies
> npm install
> ```
>
> **For Vite projects:**
>
> ```bash theme={null}
> rm -rf node_modules .vite package-lock.json
> npm cache clean --force
> npm install
> ```
>
> **For Next.js projects:**
>
> ```bash theme={null}
> rm -rf node_modules .next package-lock.json
> npm cache clean --force
> npm install
> ```
>
> For framework-specific bundler configuration, see the [Framework Setup](https://docs.immutable.com/docs/sdks/typescript/overview.md#framework-setup) tabs in the overview.

## Regional Support

> [accordion] What regions are supported?
>
> The Immutable Game SDK supports only the regions that Immutable Passport supports.
>
> Passport is a globally available product. However, our wallet infrastructure is subject to the regulation of the US Department of the Treasury's Office of Foreign Assets Control ("OFAC"). OFAC administers and enforces comprehensive and targeted economic and trade sanctions programs on multiple countries and regions.
>
> Users attempting to access Passport in any of the regions under OFAC sanction will have their access blocked and will be unable to use our product. Additionally, components of Passport's infrastructure also rely on technology provided by [Magic](https://magic.link/), which maintains further details regarding unsupported regions on their website [here](https://help.magic.link/knowledge/prohibited-regions).

## Authentication

> [accordion] "Redirect URI mismatch" error
>
> The `redirectUri` in your code must **exactly** match what's configured in [Hub](https://hub.immutable.com).
>
> Common mismatches:
>
> * `http` vs `https`
> * Trailing slash (`/callback` vs `/callback/`)
> * Port number differences
> * Different paths
>
> ```typescript theme={null}
> // ❌ Wrong - trailing slash mismatch
> redirectUri: 'http://localhost:3000/callback/'
>
> // ✅ Correct - matches Hub config exactly
> redirectUri: 'http://localhost:3000/callback'
> ```
>
> > [!WARNING]
> >
> > The redirect URI must match **exactly** including trailing slashes and port numbers.

> [accordion] "Invalid client\_id" error
>
> Verify the following:
>
> 1. `clientId` matches your Hub configuration
> 2. You're using the correct environment (Sandbox vs Production)
> 3. `publishableKey` is set correctly

> [accordion] "Popup blocked" when logging in
>
> Browsers block popups that aren't triggered by user interaction.
>
> ```typescript theme={null}
> // ❌ Wrong - called on page load
> useEffect(() => {
>   auth.login(); // Blocked!
> }, []);
>
> // ✅ Correct - triggered by user click
> <button onClick={() => auth.login()}>
>   Login
> </button>
> ```
>
> > [!WARNING]
> >
> > Always trigger authentication flows from user interactions (button clicks) to avoid popup blockers.

> [accordion] Callback page shows error or nothing happens
>
> Ensure `loginCallback()` is called on your redirect URI page:
>
> ```typescript theme={null}
> // app/callback/page.tsx
> useEffect(() => {
>   auth.loginCallback()
>     .then(() => router.push('/'))
>     .catch(console.error);
> }, []);
> ```

## Transactions

> [accordion] "User rejected the request"
>
> User cancelled the transaction in the Passport popup. Handle this gracefully:
>
> ```typescript theme={null}
> try {
>   await walletClient.sendTransaction({ to, value });
> } catch (error) {
>   if (error.name === 'UserRejectedRequestError') {
>     // User cancelled - show friendly message
>     return;
>   }
>   throw error;
> }
> ```

> [accordion] "Insufficient funds" error
>
> The user doesn't have enough IMX for the transaction + gas fees.
>
> ```typescript theme={null}
> import { formatEther } from 'viem';
>
> const balance = await publicClient.getBalance({ address });
> console.log('Balance:', formatEther(balance), 'IMX');
> ```
>
> Direct users to fund their wallet via the [Checkout widgets](https://docs.immutable.com/docs/products/checkout/fund.md).

> [accordion] "Nonce too low" error
>
> Usually caused by pending transactions. Wait for pending transactions to confirm:
>
> ```typescript theme={null}
> const pendingNonce = await publicClient.getTransactionCount({
>   address,
>   blockTag: 'pending',
> });
> ```

## Performance & Debugging

> [accordion] Slow SDK initialization
>
> Initialize once and reuse the instance:
>
> ```typescript theme={null}
> // ❌ Wrong - creates new instance every call
> function getAuth() {
>   return new Auth({ ... });
> }
>
> // ✅ Correct - singleton pattern
> let auth: Auth | null = null;
> function getAuth() {
>   if (!auth) {
>     auth = new Auth({ ... });
>   }
>   return auth;
> }
> ```
>
> > [!TIP]
> >
> > Use the singleton pattern to initialize SDK instances once and reuse them throughout your application.

> [accordion] How do I enable SDK debug logs?
>
> Enable debug logs in the browser console:
>
> ```typescript theme={null}
> // In browser console
> localStorage.setItem('debug', 'imtbl:*');
> ```
>
> Then refresh the page to see SDK debug output.

> [accordion] How do I inspect SDK network calls?
>
> SDK calls go to:
>
> * **Sandbox**: `api.sandbox.immutable.com`
> * **Production**: `api.immutable.com`
>
> Check the browser Network tab for failed requests and error responses.

> [accordion] Common HTTP error codes
>
> | Code | Meaning | Solution |
> | - | - | - |
> | 401 | Unauthorized | Check API key or access token |
> | 403 | Forbidden | Check permissions in Hub |
> | 429 | Rate limited | Implement exponential backoff |
> | 500 | Server error | Retry with backoff, contact support if persistent |

## Integration & Usage

> [accordion] How do I use the SDK with viem?
>
> viem has built-in Immutable Chain support:
>
> ```typescript theme={null}
> import { createWalletClient, createPublicClient, custom, http } from 'viem';
> import { immutableZkEvm, immutableZkEvmTestnet } from 'viem/chains';
> import { connectWallet } from '@imtbl/wallet';
>
> const provider = await connectWallet({ auth });
>
> const walletClient = createWalletClient({
>   chain: immutableZkEvmTestnet,
>   transport: custom(provider),
> });
>
> const publicClient = createPublicClient({
>   chain: immutableZkEvmTestnet,
>   transport: http(),
> });
>
> const [address] = await walletClient.getAddresses();
>
> const hash = await walletClient.sendTransaction({
>   to: '0x...',
>   value: parseEther('0.1'),
> });
> ```

> [accordion] How do I validate webhooks?
>
> Use `@imtbl/webhook` to verify incoming webhooks from Immutable:
>
> ```typescript theme={null}
> import { validateWebhook } from '@imtbl/webhook';
>
> app.post('/webhook', (req, res) => {
>   const signature = req.headers['x-immutable-signature'] as string;
>   const rawBody = req.body; // Must be raw body, not parsed JSON
>
>   const isValid = validateWebhook(
>     rawBody,
>     signature,
>     process.env.WEBHOOK_SECRET!
>   );
>
>   if (!isValid) {
>     return res.status(403).send('Invalid signature');
>   }
>
>   res.status(200).send('OK');
> });
> ```

> [accordion] Can I use the SDK via CDN?
>
> For browser-only applications without a build step:
>
> ```html theme={null}
> <script src="https://cdn.jsdelivr.net/npm/@imtbl/sdk"></script>
>
> <script>
>   const passport = new window.immutable.passport.Passport({
>     clientId: 'YOUR_CLIENT_ID',
>     redirectUri: 'https://your-app.com/callback',
>     logoutRedirectUri: 'https://your-app.com',
>     audience: 'platform_api',
>     scope: 'openid offline_access email transact'
>   });
>
>   passport.login();
> </script>
> ```
>
> > [!NOTE]
> >
> > CDN deployment is useful for quick prototypes and static sites. For production applications, use npm packages with proper bundling.

> [accordion] How do I enable code splitting?
>
> Requires TypeScript 5.0+ with `moduleResolution: "bundler"` in `tsconfig.json`.
>
> ```typescript theme={null}
> // ✅ Correct - imports only the module you need
> import { Passport } from '@imtbl/sdk/passport';
> import { Orderbook } from '@imtbl/sdk/orderbook';
> import { BlockchainData } from '@imtbl/sdk/blockchain-data';
>
> // ❌ Avoid - imports entire SDK
> import { Passport, Orderbook } from '@imtbl/sdk';
> ```

> [accordion] V2 SDK migration notes
>
> > [!WARNING]
> >
> > **Breaking Change**: V2 SDK uses **Ethers.js v6** (upgraded from v5). If your application uses Ethers.js, you must migrate. Key changes:
> >
> > * `WrappedBrowserProvider` for Checkout SDK
> > * `passport.connectEvm()` is now **async** — must `await` before passing to Checkout
> > * See [Ethers.js v6 migration guide](https://docs.ethers.org/v6/migrating/) for details

***

## Still Need Help?

> [card] [TypeScript SDK](https://docs.immutable.com/docs/sdks/typescript/overview.md)
>
> Complete TypeScript SDK documentation

> [card] [GitHub Issues](https://github.com/immutable/ts-immutable-sdk/issues)
>
> Report TypeScript SDK issues

> [card] [Player Support](https://play.immutable.com)
>
> Contact player support

> [card] [Documentation](https://docs.immutable.com/docs/immutable.md)
>
> Browse all documentation


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.