> ## 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 title="&#x22;Buffer is not defined&#x22; or &#x22;process is not defined&#x22;">
  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>

<Accordion title="&#x22;crypto is not defined&#x22;">
  Add global polyfill to your bundler config:

  ```typescript theme={null}
  // vite.config.ts
  export default defineConfig({
    define: {
      global: 'globalThis',
    },
  });
  ```
</Accordion>

<Accordion title="Module resolution issues or type errors">
  Ensure `tsconfig.json` uses modern module resolution:

  ```json theme={null}
  {
    "compilerOptions": {
      "moduleResolution": "bundler", // or "node16"
      "esModuleInterop": true
    }
  }
  ```
</Accordion>

<Accordion title="Next.js: &#x22;Cannot find module&#x22; 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>

<Accordion title="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.
  </Tip>
</Accordion>

<Accordion title="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](/docs/sdks/typescript/overview#framework-setup) tabs in the overview.
</Accordion>

## Regional Support

<Accordion title="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).
</Accordion>

## Authentication

<Accordion title="&#x22;Redirect URI mismatch&#x22; 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.
  </Warning>
</Accordion>

<Accordion title="&#x22;Invalid client_id&#x22; 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>

<Accordion title="&#x22;Popup blocked&#x22; 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.
  </Warning>
</Accordion>

<Accordion title="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);
  }, []);
  ```
</Accordion>

## Transactions

<Accordion title="&#x22;User rejected the request&#x22;">
  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>

<Accordion title="&#x22;Insufficient funds&#x22; 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](/docs/products/checkout/fund).
</Accordion>

<Accordion title="&#x22;Nonce too low&#x22; error">
  Usually caused by pending transactions. Wait for pending transactions to confirm:

  ```typescript theme={null}
  const pendingNonce = await publicClient.getTransactionCount({
    address,
    blockTag: 'pending',
  });
  ```
</Accordion>

## Performance & Debugging

<Accordion title="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.
  </Tip>
</Accordion>

<Accordion title="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>

<Accordion title="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>

<Accordion title="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 |
</Accordion>

## Integration & Usage

<Accordion title="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>

<Accordion title="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>

<Accordion title="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>
  ```

  <Info>
    CDN deployment is useful for quick prototypes and static sites. For production applications, use npm packages with proper bundling.
  </Info>
</Accordion>

<Accordion title="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>

<Accordion title="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
  </Warning>
</Accordion>

***

## Still Need Help?

<CardGroup cols={2}>
  <Card title="TypeScript SDK" icon="code" href="/docs/sdks/typescript/overview">
    Complete TypeScript SDK documentation
  </Card>

  <Card title="GitHub Issues" icon="github" href="https://github.com/immutable/ts-immutable-sdk/issues">
    Report TypeScript SDK issues
  </Card>

  <Card title="Support" icon="headset" href="https://support.immutable.com">
    Contact support team
  </Card>

  <Card title="Documentation" icon="book" href="/docs/immutable">
    Browse all documentation
  </Card>
</CardGroup>
