Repository: thirdweb-dev/js
Pull request #7038: [SDK] Default to in-memory storage for inAppWallet outside browser
Author: login: joaquim-verges
Labels: name: packages
name: SDK
description: Involves changes to the thirdweb SDK
Created: 2025-05-13T21:34:14Z | Merged: 2025-05-14T01:32:37Z

<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the `inAppWallet` functionality by introducing default in-memory storage for non-browser environments, adding integration tests, and improving documentation regarding wallet strategies and features.

### Detailed summary
- Default storage switched to in-memory when not in the browser.
- New `getDefaultStorage()` function implemented.
- Added integration tests for `InAppWallet` covering backend and guest strategies.
- Enhanced documentation for `inAppWallet` with examples for EIP-7702 and EIP-4337.
- Updated login methods documentation, including email and phone verification.
- Added options for customizing the Connect UI with logo, icon, and name.
- Clarified storage behavior for wallet state management.

> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`

<!-- end pr-codex -->


Diff:
diff --git a/.changeset/thin-rockets-walk.md b/.changeset/thin-rockets-walk.md
new file mode 100644
index 00000000000..bde5e20d8f2
--- /dev/null
+++ b/.changeset/thin-rockets-walk.md
@@ -0,0 +1,5 @@
+---
+"thirdweb": patch
+---
+
+Default to in-memory storage when creating inapp wallets outside the browser
diff --git a/packages/thirdweb/src/wallets/in-app/web/in-app.ts b/packages/thirdweb/src/wallets/in-app/web/in-app.ts
index 11597f42ff8..1e60d716543 100644
--- a/packages/thirdweb/src/wallets/in-app/web/in-app.ts
+++ b/packages/thirdweb/src/wallets/in-app/web/in-app.ts
@@ -23,7 +23,7 @@ import type { InAppWalletCreationOptions } from "../core/wallet/types.js";
  * const account = await wallet.connect({
  *   client,
  *   chain,
- *   strategy: "google",
+ *   strategy: "google", // or "apple", "facebook","discord", "github", "twitch", "x", "telegram", "line", "coinbase", etc
  * });
  * ```
  *
@@ -31,15 +31,21 @@ import type { InAppWalletCreationOptions } from "../core/wallet/types.js";
  *
  * ### Enable smart accounts and sponsor gas for your users:
  *
+ * With the `executionMode` option, you can enable smart accounts and sponsor gas for your users.
+ *
+ * **Using EIP-7702** (recommended):
+ *
+ * On chains with EIP-7702 enabled, you can upgrade the inapp wallet to a smart account, keeping the same address and performance as the regular EOA.
+ *
  * ```ts
  * import { inAppWallet } from "thirdweb/wallets";
  * import { sepolia } from "thirdweb/chains";
  *
  * const wallet = inAppWallet({
- *  smartAccount: {
- *   chain: sepolia,
+ *  executionMode: {
+ *   mode: "EIP7702",
  *   sponsorGas: true,
- * },
+ *  },
  * });
  *
  * // account will be a smart account with sponsored gas enabled
@@ -49,8 +55,28 @@ import type { InAppWalletCreationOptions } from "../core/wallet/types.js";
  * });
  * ```
  *
+ * **Using EIP-4337**:
+ *
+ * On chains without EIP-7702 enabled, you can still use smart accounts using EIP-4337, this will return a different address (the smart contract address) than the regular EOA.
+ *
+ * ```ts
+ * import { inAppWallet } from "thirdweb/wallets/in-app";
+ *
+ * const wallet = inAppWallet({
+ *  executionMode: {
+ *   mode: "EIP4337",
+ *   smartAccount: {
+ *    chain: sepolia, // chain required for EIP-4337
+ *    sponsorGas: true,
+ *   }
+ *  },
+ * });
+ * ```
+ *
  * ### Login with email
  *
+ * To login with email, you can use the `preAuthenticate` function to first send a verification code to the user's email, then login with the verification code.
+ *
  * ```ts
  * import { inAppWallet, preAuthenticate } from "thirdweb/wallets/in-app";
  *
@@ -73,22 +99,10 @@ import type { InAppWalletCreationOptions } from "../core/wallet/types.js";
  * });
  * ```
  *
- * ### Login with SIWE
- * ```ts
- * import { inAppWallet, createWallet } from "thirdweb/wallets";
- *
- * const rabby = createWallet("io.rabby");
- * const inAppWallet = inAppWallet();
+ * ### Login with phone number
  *
- * const account = await inAppWallet.connect({
- *    strategy: "wallet",
- *    chain: mainnet,
- *    wallet: rabby,
- *    client: MY_CLIENT
- * });
- * ```
+ * Similar to email, you can login with a phone number by first sending a verification code to the user's phone number, then login with the verification code.
  *
- * ### Login with phone number
  * ```ts
  * import { inAppWallet, preAuthenticate } from "thirdweb/wallets/in-app";
  *
@@ -111,8 +125,28 @@ import type { InAppWalletCreationOptions } from "../core/wallet/types.js";
  * });
  * ```
  *
+ * ### Login with another wallet (SIWE)
+ *
+ * You can also login to the in-app wallet with another existing wallet by signing a standard Sign in with Ethereum (SIWE) message.
+ *
+ * ```ts
+ * import { inAppWallet, createWallet } from "thirdweb/wallets";
+ *
+ * const rabby = createWallet("io.rabby");
+ * const inAppWallet = inAppWallet();
+ *
+ * const account = await inAppWallet.connect({
+ *    strategy: "wallet",
+ *    chain: mainnet,
+ *    wallet: rabby,
+ *    client: MY_CLIENT
+ * });
+ * ```
+ *
  * ### Login with passkey
  *
+ * You can also login with a passkey. This mode requires specifying whether it should create a new passkey, or sign in with an existing passkey. We recommend checking if the user has a passkey stored in their browser to automatically login with it.
+ *
  * ```ts
  * import { inAppWallet, hasStoredPasskey } from "thirdweb/wallets/in-app";
  *
@@ -128,6 +162,11 @@ import type { InAppWalletCreationOptions } from "../core/wallet/types.js";
  * ```
  *
  * ### Connect to a guest account
+ *
+ * You can also connect to a guest account, this will create a new account for the user instantly and store it in the browser's local storage.
+ *
+ * You can later "upgrade" this account by linking another auth method, like email or phone for example. This will preserve the account's address and history.
+ *
  * ```ts
  * import { inAppWallet } from "thirdweb/wallets";
  *
@@ -141,19 +180,19 @@ import type { InAppWalletCreationOptions } from "../core/wallet/types.js";
  *
  * ### Connect to a backend account
  *
- * for usage in backends, you might also need to provide a 'storage' to store auth tokens. In-memory usually works for most purposes.
+ * For usage in backends, you can create wallets with the `backend` strategy and a stable walletSecret.
+ *
+ * Make sure to keep that walletSecret safe as it is the key to access that wallet, never expose it to the client.
  *
  * ```ts
  * import { inAppWallet } from "thirdweb/wallets";
  *
- * const wallet = inAppWallet({
- *   storage: inMemoryStorage, // for usage in backends/scripts
- * });
+ * const wallet = inAppWallet();
  *
  * const account = await wallet.connect({
  *   client,
  *   strategy: "backend",
- *   walletSecret: "...", // Provided by your app
+ *   walletSecret: "...", // Your own secret, keep it safe
  * });
  * ```
  *
@@ -189,16 +228,21 @@ import type { InAppWalletCreationOptions } from "../core/wallet/types.js";
  * });
  * ```
  *
- * ### Specify a logo for your login page (Connect UI)
+ * ### Specify a logo, icon and name for your login page (Connect UI)
+ *
+ * You can specify a logo, icon and name for your login page to customize how in-app wallets are displayed in the Connect UI components (ConnectButton and ConnectEmbed).
+ *
  * ```ts
  * import { inAppWallet } from "thirdweb/wallets";
  * const wallet = inAppWallet({
  *  metadata: {
- *   image: {
- *    src: "https://example.com/logo.png",
- *    alt: "My logo",
- *    width: 100,
- *    height: 100,
+ *    name: "My App",
+ *    icon: "https://example.com/icon.png",
+ *    image: {
+ *      src: "https://example.com/logo.png",
+ *      alt: "My logo",
+ *      width: 100,
+ *      height: 100,
  *   },
  *  },
  * });
@@ -206,6 +250,8 @@ import type { InAppWalletCreationOptions } from "../core/wallet/types.js";
  *
  * ### Hide the ability to export the private key within the Connect Modal UI
  *
+ * By default, the Connect Modal will show a button to export the private key of the wallet. You can hide this button by setting the `hidePrivateKeyExport` option to `true`.
+ *
  * ```ts
  * import { inAppWallet } from "thirdweb/wallets";
  * const wallet = inAppWallet({
@@ -228,7 +274,7 @@ import type { InAppWalletCreationOptions } from "../core/wallet/types.js";
  *
  * ### Override storage for the wallet state
  *
- * By default, wallet state is stored in the browser's local storage. You can override this behavior by providing a custom storage object, useful for server side integrations.
+ * By default, wallet state is stored in the browser's local storage if in the browser, or in-memory storage if not in the browser. You can override this behavior by providing a custom storage object, useful for server side and CLI integrations.
  *
  * ```ts
  * import { inAppWallet } from "thirdweb/wallets";
diff --git a/packages/thirdweb/src/wallets/in-app/web/lib/in-app-backend.test.ts b/packages/thirdweb/src/wallets/in-app/web/lib/in-app-backend.test.ts
deleted file mode 100644
index 8da74d7c2eb..00000000000
--- a/packages/thirdweb/src/wallets/in-app/web/lib/in-app-backend.test.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import { describe, expect, it } from "vitest";
-import { TEST_CLIENT } from "~test/test-clients.js";
-import { sepolia } from "../../../../chains/chain-definitions/sepolia.js";
-import { inMemoryStorage } from "../../../../utils/storage/inMemoryStorage.js";
-import { inAppWallet } from "../in-app.js";
-
-describe("InAppWallet", () => {
-  it("should sign a message with backend strategy", async () => {
-    const wallet = inAppWallet({
-      smartAccount: {
-        chain: sepolia,
-        sponsorGas: true,
-      },
-      storage: inMemoryStorage,
-    });
-    const account = await wallet.connect({
-      client: TEST_CLIENT,
-      strategy: "backend",
-      walletSecret: "test-secret",
-    });
-    expect(account.address).toBeDefined();
-    const message = await account.signMessage({
-      message: "Hello, world!",
-    });
-    expect(message).toBeDefined();
-  });
-});
diff --git a/packages/thirdweb/src/wallets/in-app/web/lib/in-app-integration.test.ts b/packages/thirdweb/src/wallets/in-app/web/lib/in-app-integration.test.ts
new file mode 100644
index 00000000000..97fd4eea3f5
--- /dev/null
+++ b/packages/thirdweb/src/wallets/in-app/web/lib/in-app-integration.test.ts
@@ -0,0 +1,112 @@
+import { describe, expect, it } from "vitest";
+import { TEST_CLIENT } from "~test/test-clients.js";
+import { sepolia } from "../../../../chains/chain-definitions/sepolia.js";
+import { parseEventLogs } from "../../../../event/actions/parse-logs.js";
+import { userOperationEventEvent } from "../../../../extensions/erc4337/__generated__/IEntryPoint/events/UserOperationEvent.js";
+import { executedEvent } from "../../../../extensions/erc7702/__generated__/MinimalAccount/events/Executed.js";
+import { sendAndConfirmTransaction } from "../../../../transaction/actions/send-and-confirm-transaction.js";
+import { prepareTransaction } from "../../../../transaction/prepare-transaction.js";
+import { inAppWallet } from "../in-app.js";
+describe("InAppWallet Integration Tests", () => {
+  it("should sign a message with backend strategy", async () => {
+    const wallet = inAppWallet();
+    const account = await wallet.connect({
+      client: TEST_CLIENT,
+      strategy: "backend",
+      walletSecret: "test-secret",
+    });
+    expect(account.address).toBeDefined();
+    const message = await account.signMessage({
+      message: "Hello, world!",
+    });
+    expect(message).toBeDefined();
+  });
+
+  it("should sign a message with guest strategy", async () => {
+    const wallet = inAppWallet();
+    const account = await wallet.connect({
+      client: TEST_CLIENT,
+      strategy: "guest",
+    });
+    expect(account.address).toBeDefined();
+    const message = await account.signMessage({
+      message: "Hello, world!",
+    });
+    expect(message).toBeDefined();
+  });
+
+  it("should sponsor gas for a 7702 smart account", async () => {
+    const chain = sepolia;
+    const wallet = inAppWallet({
+      executionMode: {
+        mode: "EIP7702",
+        sponsorGas: true,
+      },
+    });
+    const account = await wallet.connect({
+      client: TEST_CLIENT,
+      strategy: "guest",
+      chain,
+    });
+    expect(account.address).toBeDefined();
+    const tx = await sendAndConfirmTransaction({
+      transaction: prepareTransaction({
+        chain,
+        client: TEST_CLIENT,
+        to: account.address,
+        value: 0n,
+      }),
+      account,
+    });
+    expect(tx.transactionHash).toBeDefined();
+    const logs = parseEventLogs({
+      logs: tx.logs,
+      events: [executedEvent()],
+    });
+    const executedLog = logs[0];
+    if (!executedLog) {
+      throw new Error("No executed log found");
+    }
+    expect(executedLog.args.to).toBe(account.address);
+    expect(executedLog.args.value).toBe(0n);
+  });
+
+  it("should sponsor gas for a 4337 smart account", async () => {
+    const chain = sepolia;
+    const wallet = inAppWallet({
+      executionMode: {
+        mode: "EIP4337",
+        smartAccount: {
+          chain,
+          sponsorGas: true,
+        },
+      },
+    });
+    const account = await wallet.connect({
+      client: TEST_CLIENT,
+      strategy: "guest",
+      chain,
+    });
+    expect(account.address).toBeDefined();
+    const tx = await sendAndConfirmTransaction({
+      transaction: prepareTransaction({
+        chain,
+        client: TEST_CLIENT,
+        to: account.address,
+        value: 0n,
+      }),
+      account,
+    });
+    expect(tx.transactionHash).toBeDefined();
+    const logs = parseEventLogs({
+      logs: tx.logs,
+      events: [userOperationEventEvent()],
+    });
+    const executedLog = logs[0];
+    if (!executedLog) {
+      throw new Error("No executed log found");
+    }
+    expect(executedLog.args.sender).toBe(account.address);
+    expect(executedLog.args.success).toBe(true);
+  });
+});
diff --git a/packages/thirdweb/src/wallets/in-app/web/lib/web-connector.ts b/packages/thirdweb/src/wallets/in-app/web/lib/web-connector.ts
index 2b8b1b07028..db7ab3124b8 100644
--- a/packages/thirdweb/src/wallets/in-app/web/lib/web-connector.ts
+++ b/packages/thirdweb/src/wallets/in-app/web/lib/web-connector.ts
@@ -1,5 +1,7 @@
 import type { ThirdwebClient } from "../../../../client/client.js";
 import { getThirdwebBaseUrl } from "../../../../utils/domains.js";
+import type { AsyncStorage } from "../../../../utils/storage/AsyncStorage.js";
+import { inMemoryStorage } from "../../../../utils/storage/inMemoryStorage.js";
 import { webLocalStorage } from "../../../../utils/storage/webStorage.js";
 import type { SocialAuthOption } from "../../../../wallets/types.js";
 import type { Account } from "../../../interfaces/wallet.js";
@@ -86,7 +88,7 @@ export class InAppWebConnector implements InAppConnector {
     this.ecosystem = ecosystem;
     this.passkeyDomain = passkeyDomain;
     this.storage = new ClientScopedStorage({
-      storage: storage ?? webLocalStorage,
+      storage: storage ?? getDefaultStorage(),
       clientId: client.clientId,
       ecosystem: ecosystem,
     });
@@ -489,3 +491,11 @@ export class InAppWebConnector implements InAppConnector {
 function assertUnreachable(x: never, message?: string): never {
   throw new Error(message ?? `Invalid param: ${x}`);
 }
+
+function getDefaultStorage(): AsyncStorage {
+  if (typeof window !== "undefined" && window.localStorage) {
+    return webLocalStorage;
+  }
+  // default to in-memory storage if we're not in the browser
+  return inMemoryStorage;
+}


Reviews:
user: login: graphite-app[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-13T21:52:57Z
user: login: graphite-app[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-13T21:55:00Z

Review comments:
diff_hunk: @@ -33,7 +33,7 @@ export type InAppWalletConstructorType = ClientIdConstructorType & {
   /**
    * The storage to use for storing wallet state
    */
-  storage?: AsyncStorage;
+  storage: AsyncStorage;
path: packages/thirdweb/src/wallets/in-app/web/types.ts
user: login: graphite-app[bot]
body: The storage property should be marked as optional with a question mark since the implementation provides a default value when it's not provided.

*Spotted by [Diamond](https://app.graphite.dev/diamond/?org=thirdweb-dev&ref=ai-review-comment) (based on CI logs)*<i class='graphite__hidden'><br /><br />Is this helpful? React 👍 or 👎 to let us know.</i>
created_at: 2025-05-13T21:52:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -86,7 +86,7 @@ export class InAppWebConnector implements InAppConnector {
     this.ecosystem = ecosystem;
     this.passkeyDomain = passkeyDomain;
     this.storage = new ClientScopedStorage({
-      storage: storage ?? webLocalStorage,
+      storage,
       clientId: client.clientId,
path: packages/thirdweb/src/wallets/in-app/web/lib/web-connector.ts
user: login: graphite-app[bot]
body: The constructor should use the getDefaultStorage function when no storage is provided. Update the storage initialization to: 'this.storage = new ClientScopedStorage({ storage: storage ?? getDefaultStorage(), clientId: client.clientId, ecosystem: ecosystem, });'

*Spotted by [Diamond](https://app.graphite.dev/diamond/?org=thirdweb-dev&ref=ai-review-comment) (based on CI logs)*<i class='graphite__hidden'><br /><br />Is this helpful? React 👍 or 👎 to let us know.</i>
created_at: 2025-05-13T21:54:58Z
author_association: CONTRIBUTOR
diff_hunk: @@ -264,8 +313,16 @@ export function inAppWallet(
       return new InAppWebConnector({
         client,
         passkeyDomain: createOptions?.auth?.passkeyDomain,
-        storage: createOptions?.storage,
+        storage: createOptions?.storage ?? getDefaultStorage(),
       });
     },
   }) as Wallet<"inApp">;
 }
+
+function getDefaultStorage(): AsyncStorage {
+  if (typeof window !== "undefined" && window.localStorage) {
+    return webLocalStorage;
+  }
+  // default to in-memory storage if we're not in the browser
+  return inMemoryStorage;
+}
path: packages/thirdweb/src/wallets/in-app/web/in-app.ts
user: login: graphite-app[bot]
body: The getDefaultStorage function should be exported so it can be used in other files that instantiate InAppWebConnector. Change 'function getDefaultStorage()' to 'export function getDefaultStorage()'.

*Spotted by [Diamond](https://app.graphite.dev/diamond/?org=thirdweb-dev&ref=ai-review-comment) (based on CI logs)*<i class='graphite__hidden'><br /><br />Is this helpful? React 👍 or 👎 to let us know.</i>
created_at: 2025-05-13T21:54:59Z
author_association: CONTRIBUTOR

PR comments:
user: login: vercel[bot]
created_at: 2025-05-13T21:34:16Z
body: [vc]: #4/d8ig5K5gLvklGTuJd6jEabPQGoz3+uLYWhw3p4Z6o=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJsb2dpbiIsInJvb3REaXJlY3RvcnkiOiJhcHBzL2xvZ2luIiwiaW5zcGVjdG9yVXJsIjoiaHR0cHM6Ly92ZXJjZWwuY29tL3RoaXJkd2ViL2xvZ2luLzhwOERhWmhienh1NUw3MWZIV3pyRjM5RTVFVEIiLCJwcmV2aWV3VXJsIjoibG9naW4tZ2l0LWRlZmF1bHR0b2luLW1lbW9yeXN0b3JhZ2Vmb3JpbmFwcHdhbGxldG91dHNpZGVicm93c2VyLnRoaXJkd2ViLXByZXZpZXcuY29tIiwibmV4dENvbW1pdFN0YXR1cyI6IkRFUExPWUVEIiwibGl2ZUZlZWRiYWNrIjp7InJlc29sdmVkIjowLCJ1bnJlc29sdmVkIjowLCJ0b3RhbCI6MCwibGluayI6ImxvZ2luLWdpdC1kZWZhdWx0dG9pbi1tZW1vcnlzdG9yYWdlZm9yaW5hcHB3YWxsZXRvdXRzaWRlYnJvd3Nlci50aGlyZHdlYi1wcmV2aWV3LmNvbSJ9fSx7Im5hbWUiOiJ0aGlyZHdlYl9wbGF5Z3JvdW5kIiwicm9vdERpcmVjdG9yeSI6ImFwcHMvcGxheWdyb3VuZC13ZWIiLCJpbnNwZWN0b3JVcmwiOiJodHRwczovL3ZlcmNlbC5jb20vdGhpcmR3ZWIvdGhpcmR3ZWJfcGxheWdyb3VuZC8yTmNUZHNTYm9USGFXTUdzUDRwOFg3d2hFN3JoIiwicHJldmlld1VybCI6InRoaXJkd2VicGxheWdyb3VuZC1naXQtZGVmYXVsdHRvaW4tbWVtb3J5c3RvcmFnZWZvcmluYXBwLTZjYWI4ZS50aGlyZHdlYi1wcmV2aWV3LmNvbSIsIm5leHRDb21taXRTdGF0dXMiOiJERVBMT1lFRCIsImxpdmVGZWVkYmFjayI6eyJyZXNvbHZlZCI6MCwidW5yZXNvbHZlZCI6MCwidG90YWwiOjAsImxpbmsiOiJ0aGlyZHdlYnBsYXlncm91bmQtZ2l0LWRlZmF1bHR0b2luLW1lbW9yeXN0b3JhZ2Vmb3JpbmFwcC02Y2FiOGUudGhpcmR3ZWItcHJldmlldy5jb20ifX0seyJuYW1lIjoid2FsbGV0LXVpIiwicm9vdERpcmVjdG9yeSI6ImFwcHMvd2FsbGV0LXVpIiwiaW5zcGVjdG9yVXJsIjoiaHR0cHM6Ly92ZXJjZWwuY29tL3RoaXJkd2ViL3dhbGxldC11aS9IVUpjdFJqQjhXeXVCRXpId01yMWRLNXNLNk03IiwicHJldmlld1VybCI6IndhbGxldC11aS1naXQtZGVmYXVsdHRvaW4tbWVtb3J5c3RvcmFnZWZvcmluYXBwd2FsbGV0b3V0LTE3OTRkOC50aGlyZHdlYi1wcmV2aWV3LmNvbSIsIm5leHRDb21taXRTdGF0dXMiOiJERVBMT1lFRCIsImxpdmVGZWVkYmFjayI6eyJyZXNvbHZlZCI6MCwidW5yZXNvbHZlZCI6MCwidG90YWwiOjAsImxpbmsiOiJ3YWxsZXQtdWktZ2l0LWRlZmF1bHR0b2luLW1lbW9yeXN0b3JhZ2Vmb3JpbmFwcHdhbGxldG91dC0xNzk0ZDgudGhpcmR3ZWItcHJldmlldy5jb20ifX0seyJuYW1lIjoidGhpcmR3ZWItd3d3Iiwicm9vdERpcmVjdG9yeSI6ImFwcHMvZGFzaGJvYXJkIiwiaW5zcGVjdG9yVXJsIjoiaHR0cHM6Ly92ZXJjZWwuY29tL3RoaXJkd2ViL3RoaXJkd2ViLXd3dy83Q2lWTkQ3alV1cHVFQVZ2R240Z1o1alZ1aVFuIiwicHJldmlld1VybCI6InRoaXJkd2ViLXd3dy1naXQtZGVmYXVsdHRvaW4tbWVtb3J5c3RvcmFnZWZvcmluYXBwd2FsbGV0LTgyMjg3MC50aGlyZHdlYi1wcmV2aWV3LmNvbSIsIm5leHRDb21taXRTdGF0dXMiOiJERVBMT1lFRCIsImxpdmVGZWVkYmFjayI6eyJyZXNvbHZlZCI6MCwidW5yZXNvbHZlZCI6MCwidG90YWwiOjAsImxpbmsiOiJ0aGlyZHdlYi13d3ctZ2l0LWRlZmF1bHR0b2luLW1lbW9yeXN0b3JhZ2Vmb3JpbmFwcHdhbGxldC04MjI4NzAudGhpcmR3ZWItcHJldmlldy5jb20ifX0seyJuYW1lIjoiZG9jcy12MiIsInJvb3REaXJlY3RvcnkiOiJhcHBzL3BvcnRhbCIsImluc3BlY3RvclVybCI6Imh0dHBzOi8vdmVyY2VsLmNvbS90aGlyZHdlYi9kb2NzLXYyL0JEOVR6U1BoVUttNEJRYTNDeGNLUnZQRDVOcEYiLCJwcmV2aWV3VXJsIjoiZG9jcy12Mi1naXQtZGVmYXVsdHRvaW4tbWVtb3J5c3RvcmFnZWZvcmluYXBwd2FsbGV0b3V0c2ktODY2YzJhLnRoaXJkd2ViLXByZXZpZXcuY29tIiwibmV4dENvbW1pdFN0YXR1cyI6IkRFUExPWUVEIiwibGl2ZUZlZWRiYWNrIjp7InJlc29sdmVkIjowLCJ1bnJlc29sdmVkIjowLCJ0b3RhbCI6MCwibGluayI6ImRvY3MtdjItZ2l0LWRlZmF1bHR0b2luLW1lbW9yeXN0b3JhZ2Vmb3JpbmFwcHdhbGxldG91dHNpLTg2NmMyYS50aGlyZHdlYi1wcmV2aWV3LmNvbSJ9fV19
**The latest updates on your projects**. Learn more about [Vercel for Git ↗︎](https://vercel.link/github-learn-more)

| Name | Status | Preview | Comments | Updated (UTC) |
| :--- | :----- | :------ | :------- | :------ |
| **docs-v2** | ✅ Ready ([Inspect](https://vercel.com/thirdweb/docs-v2/BD9TzSPhUKm4BQa3CxcKRvPD5NpF)) | [Visit Preview](https://docs-v2-git-defaulttoin-memorystorageforinappwalletoutsi-866c2a.thirdweb-preview.com) | 💬 [**Add feedback**](https://vercel.live/open-feedback/docs-v2-git-defaulttoin-memorystorageforinappwalletoutsi-866c2a.thirdweb-preview.com?via=pr-comment-feedback-link) | May 14, 2025 1:29am |
| **login** | ✅ Ready ([Inspect](https://vercel.com/thirdweb/login/8p8DaZhbzxu5L71fHWzrF39E5ETB)) | [Visit Preview](https://login-git-defaulttoin-memorystorageforinappwalletoutsidebrowser.thirdweb-preview.com) | 💬 [**Add feedback**](https://vercel.live/open-feedback/login-git-defaulttoin-memorystorageforinappwalletoutsidebrowser.thirdweb-preview.com?via=pr-comment-feedback-link) | May 14, 2025 1:29am |
| **thirdweb_playground** | ✅ Ready ([Inspect](https://vercel.com/thirdweb/thirdweb_playground/2NcTdsSboTHaWMGsP4p8X7whE7rh)) | [Visit Preview](https://thirdwebplayground-git-defaulttoin-memorystorageforinapp-6cab8e.thirdweb-preview.com) | 💬 [**Add feedback**](https://vercel.live/open-feedback/thirdwebplayground-git-defaulttoin-memorystorageforinapp-6cab8e.thirdweb-preview.com?via=pr-comment-feedback-link) | May 14, 2025 1:29am |
| **thirdweb-www** | ✅ Ready ([Inspect](https://vercel.com/thirdweb/thirdweb-www/7CiVND7jUupuEAVvGn4gZ5jVuiQn)) | [Visit Preview](https://thirdweb-www-git-defaulttoin-memorystorageforinappwallet-822870.thirdweb-preview.com) | 💬 [**Add feedback**](https://vercel.live/open-feedback/thirdweb-www-git-defaulttoin-memorystorageforinappwallet-822870.thirdweb-preview.com?via=pr-comment-feedback-link) | May 14, 2025 1:29am |
| **wallet-ui** | ✅ Ready ([Inspect](https://vercel.com/thirdweb/wallet-ui/HUJctRjB8WyuBEzHwMr1dK5sK6M7)) | [Visit Preview](https://wallet-ui-git-defaulttoin-memorystorageforinappwalletout-1794d8.thirdweb-preview.com) | 💬 [**Add feedback**](https://vercel.live/open-feedback/wallet-ui-git-defaulttoin-memorystorageforinappwalletout-1794d8.thirdweb-preview.com?via=pr-comment-feedback-link) | May 14, 2025 1:29am |






author_association: NONE
user: login: changeset-bot[bot]
created_at: 2025-05-13T21:34:17Z
body: ###  🦋  Changeset detected

Latest commit: 72eb633d00752eec254d547e93d296b55c00e84f

**The changes in this PR will be included in the next version bump.**

<details><summary>This PR includes changesets to release 2 packages</summary>

  | Name                        | Type  |
| --------------------------- | ----- |
| thirdweb                    | Patch |
| @thirdweb-dev/wagmi-adapter | Patch |

</details>

Not sure what this means? [Click here  to learn what changesets are](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md).

[Click here if you're a maintainer who wants to add another changeset to this PR](https://github.com/thirdweb-dev/js/new/Default_to_in-memory_storage_for_inAppWallet_outside_browser?filename=.changeset/moody-dodos-nail.md&value=---%0A%22thirdweb%22%3A%20patch%0A---%0A%0A%5BSDK%5D%20Default%20to%20in-memory%20storage%20for%20inAppWallet%20outside%20browser%0A)


author_association: NONE
user: login: joaquim-verges
created_at: 2025-05-13T21:34:29Z
body: * **#7038** <a href="https://app.graphite.dev/github/pr/thirdweb-dev/js/7038?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a> 👈 <a href="https://app.graphite.dev/github/pr/thirdweb-dev/js/7038?utm_source=stack-comment-view-in-graphite" target="_blank">(View in Graphite)</a>
* `main`
<hr />

## How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:
- <kbd>merge-queue</kbd> - adds this PR to the back of the merge queue
- <kbd>hotfix</kbd> - for urgent hot fixes, skip the queue and merge this PR next

You must have a Graphite account in order to use the merge queue. Sign up using [this link](https://app.graphite.dev/invite/github/thirdweb-dev?ref=merge-queue-instructions-in-stack-comment&prId=7038).

<h2></h2>
<sub>

An organization admin has enabled the [Graphite Merge Queue](https://graphite.dev/docs/graphite-merge-queue) in this repository.

</sub>

<sub>

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

</sub>

<h2></h2>

This stack of pull requests is managed by <a href="https://graphite.dev?utm-source=stack-comment"><b>Graphite</b></a>. Learn more about <a href="https://stacking.dev/?utm_source=stack-comment">stacking</a>.
<!-- Current dependencies on/for this PR: -->
author_association: MEMBER
user: login: github-actions[bot]
created_at: 2025-05-14T01:25:33Z
body: ## size-limit report 📦 
| Path                                    | Size           | Loading time (3g) | Running time (snapdragon) | Total time |
| --------------------------------------- | -------------- | ----------------- | ------------------------- | ---------- |
| thirdweb (esm)                          | 54.21 KB (0%)  | 1.1 s (0%)        | 172 ms (+65.65% 🔺)       | 1.3 s      |
| thirdweb (cjs)                          | 193.92 KB (0%) | 3.9 s (0%)        | 452 ms (+11.49% 🔺)       | 4.4 s      |
| thirdweb (minimal + tree-shaking)       | 5.68 KB (0%)   | 114 ms (0%)       | 74 ms (+1002.56% 🔺)      | 188 ms     |
| thirdweb/chains (tree-shaking)          | 524 B (0%)     | 11 ms (0%)        | 10 ms (+134.88% 🔺)       | 20 ms      |
| thirdweb/react (minimal + tree-shaking) | 19.53 KB (0%)  | 391 ms (0%)       | 91 ms (+347.08% 🔺)       | 481 ms     |
author_association: CONTRIBUTOR
user: login: codecov[bot]
created_at: 2025-05-14T01:27:12Z
body: ## [Codecov](https://app.codecov.io/gh/thirdweb-dev/js/pull/7038?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=thirdweb-dev) Report
Attention: Patch coverage is `62.50000%` with `3 lines` in your changes missing coverage. Please review.
> Project coverage is 55.51%. Comparing base [(`1c31a1e`)](https://app.codecov.io/gh/thirdweb-dev/js/commit/1c31a1e4df011bb8e611856dd16bc1094f5756ef?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=thirdweb-dev) to head [(`72eb633`)](https://app.codecov.io/gh/thirdweb-dev/js/commit/72eb633d00752eec254d547e93d296b55c00e84f?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=thirdweb-dev).
> Report is 2 commits behind head on main.

| [Files with missing lines](https://app.codecov.io/gh/thirdweb-dev/js/pull/7038?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=thirdweb-dev) | Patch % | Lines |
|---|---|---|
| [...irdweb/src/wallets/in-app/web/lib/web-connector.ts](https://app.codecov.io/gh/thirdweb-dev/js/pull/7038?src=pr&el=tree&filepath=packages%2Fthirdweb%2Fsrc%2Fwallets%2Fin-app%2Fweb%2Flib%2Fweb-connector.ts&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=thirdweb-dev#diff-cGFja2FnZXMvdGhpcmR3ZWIvc3JjL3dhbGxldHMvaW4tYXBwL3dlYi9saWIvd2ViLWNvbm5lY3Rvci50cw==) | 62.50% | [3 Missing :warning: ](https://app.codecov.io/gh/thirdweb-dev/js/pull/7038?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=thirdweb-dev) |

:x: Your patch status has failed because the patch coverage (62.50%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the [target](https://docs.codecov.com/docs/commit-status#target) coverage.

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main    #7038      +/-   ##
==========================================
+ Coverage   54.89%   55.51%   +0.61%     
==========================================
  Files         909      909              
  Lines       58396    58403       +7     
  Branches     4035     4072      +37     
==========================================
+ Hits        32056    32420     +364     
+ Misses      26235    25877     -358     
- Partials      105      106       +1     
```

| [Flag](https://app.codecov.io/gh/thirdweb-dev/js/pull/7038/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=thirdweb-dev) | Coverage Δ | |
|---|---|---|
| [packages](https://app.codecov.io/gh/thirdweb-dev/js/pull/7038/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=thirdweb-dev) | `55.51% <62.50%> (+0.61%)` | :arrow_up: |

| [Files with missing lines](https://app.codecov.io/gh/thirdweb-dev/js/pull/7038?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=thirdweb-dev) | Coverage Δ | |
|---|---|---|
| [packages/thirdweb/src/wallets/in-app/web/in-app.ts](https://app.codecov.io/gh/thirdweb-dev/js/pull/7038?src=pr&el=tree&filepath=packages%2Fthirdweb%2Fsrc%2Fwallets%2Fin-app%2Fweb%2Fin-app.ts&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=thirdweb-dev#diff-cGFja2FnZXMvdGhpcmR3ZWIvc3JjL3dhbGxldHMvaW4tYXBwL3dlYi9pbi1hcHAudHM=) | `100.00% <ø> (ø)` | |
| [...irdweb/src/wallets/in-app/web/lib/web-connector.ts](https://app.codecov.io/gh/thirdweb-dev/js/pull/7038?src=pr&el=tree&filepath=packages%2Fthirdweb%2Fsrc%2Fwallets%2Fin-app%2Fweb%2Flib%2Fweb-connector.ts&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=thirdweb-dev#diff-cGFja2FnZXMvdGhpcmR3ZWIvc3JjL3dhbGxldHMvaW4tYXBwL3dlYi9saWIvd2ViLWNvbm5lY3Rvci50cw==) | `47.61% <62.50%> (+0.17%)` | :arrow_up: |

... and [15 files with indirect coverage changes](https://app.codecov.io/gh/thirdweb-dev/js/pull/7038/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=thirdweb-dev)

</details>
<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
- :package: [JS Bundle Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
</details>
author_association: NONE