From b24d4fce29f5240196effbbb572b1efe315dec4e Mon Sep 17 00:00:00 2001 From: emauja Date: Fri, 20 Mar 2026 21:16:36 +0100 Subject: [PATCH 1/3] Add Openfort as a third-party signer (#1140) * Add Openfort as a third-party signer Add documentation for using Openfort's embedded wallet as a signer with Alchemy Smart Wallets. Follows the same structure as the existing Privy integration guide with React and JavaScript tabs. Co-Authored-By: Claude Opus 4.6 * fix: use @openfort/react SDK in React tab instead of @openfort/openfort-js The React tab was incorrectly using @openfort/openfort-js with a manually built React context. Now uses the proper @openfort/react SDK with: - OpenfortProvider + wagmi + React Query provider setup - useUser, useUI, useSignOut hooks for authentication - useWalletClient from wagmi for signer access - getDefaultConfig for wagmi configuration The JavaScript tab remains unchanged, correctly using @openfort/openfort-js with its imperative/class-based API. Co-Authored-By: Claude Opus 4.6 --------- Co-authored-by: Agent Swarm Co-authored-by: Claude Opus 4.6 --- content/docs.yml | 2 + .../signers/custom-integration.mdx | 1 + .../pages/third-party/signers/openfort.mdx | 295 ++++++++++++++++++ 3 files changed, 298 insertions(+) create mode 100644 content/wallets/pages/third-party/signers/openfort.mdx diff --git a/content/docs.yml b/content/docs.yml index 24fa0c982..dfd539c9f 100644 --- a/content/docs.yml +++ b/content/docs.yml @@ -1044,6 +1044,8 @@ navigation: contents: - page: Privy path: wallets/pages/third-party/signers/privy.mdx + - page: Openfort + path: wallets/pages/third-party/signers/openfort.mdx - page: Turnkey path: wallets/pages/third-party/signers/turnkey.mdx - page: Other signers diff --git a/content/wallets/pages/third-party/signers/custom-integration.mdx b/content/wallets/pages/third-party/signers/custom-integration.mdx index 586790d40..35b732a68 100644 --- a/content/wallets/pages/third-party/signers/custom-integration.mdx +++ b/content/wallets/pages/third-party/signers/custom-integration.mdx @@ -129,5 +129,6 @@ console.log("Transaction confirmed:", txStatus.receipts?.[0]?.transactionHash); See full integration guides for supported providers: +* [Openfort](/docs/wallets/third-party/signers/openfort) * [Privy](/docs/wallets/third-party/signers/privy) * [Turnkey](/docs/wallets/third-party/signers/turnkey) diff --git a/content/wallets/pages/third-party/signers/openfort.mdx b/content/wallets/pages/third-party/signers/openfort.mdx new file mode 100644 index 000000000..af2ecddf9 --- /dev/null +++ b/content/wallets/pages/third-party/signers/openfort.mdx @@ -0,0 +1,295 @@ +--- +title: Openfort +description: Use Openfort with Smart Wallets for EIP-7702, sponsorship, and batching +slug: wallets/third-party/signers/openfort +--- + +`@alchemy/wallet-apis` (v5.x.x) is currently in beta but is the recommended replacement for `@account-kit/wallet-client` (v4.x.x). If you run into any issues, please [reach out](mailto:support@alchemy.com). + +Upgrade existing Openfort embedded wallets to Smart Wallets to enable gasless transactions, batching, and more. Keep Openfort for authentication and wallet management, no wallet migration needed. Add battle-tested transaction infrastructure using EIP-7702 to upgrade your wallets to Smart Wallets: + +* [#1 gas abstraction infrastructure](https://www.bundlebear.com/erc4337-bundlers/all) on the market +* [370M+](https://www.bundlebear.com/erc4337-paymasters/all) sponsored transactions +* 99.9% SLAs +* Trusted by Worldcoin, JP Morgan, Gensyn, and more + + + + ## Setup + + Follow these steps to use Openfort signers with the Wallet Client SDK using the `@openfort/react` SDK. + + ### Installation + + + ```shell npm + npm install @alchemy/wallet-apis @openfort/react wagmi viem @tanstack/react-query + ``` + + ```shell bun + bun add @alchemy/wallet-apis @openfort/react wagmi viem @tanstack/react-query + ``` + + ```shell yarn + yarn add @alchemy/wallet-apis @openfort/react wagmi viem @tanstack/react-query + ``` + + ```shell pnpm + pnpm add @alchemy/wallet-apis @openfort/react wagmi viem @tanstack/react-query + ``` + + + ### Prerequisites: Get your keys (API key, Policy ID, Openfort Publishable Key) + + * Alchemy API key: + * Go to the [Alchemy Dashboard](https://dashboard.alchemy.com/) + * Create or select an app and copy the API key + * Gas sponsorship Policy ID (Gas Manager): + * Create a gas sponsorship policy in the [dashboard](https://dashboard.alchemy.com/services/gas-manager/configuration) and copy its Policy ID + * Openfort Publishable Key: + * Go to the [Openfort Dashboard](https://dashboard.openfort.xyz/) + * Create or select a project and copy the Publishable Key + * Openfort Shield Publishable Key: + * In the [Openfort Dashboard](https://dashboard.openfort.xyz/), navigate to Shield settings and copy the Shield Publishable Key + + + The gas sponsorship policy must be linked to the application behind your Alchemy API key for sponsorship to work. + + + ### 1. Configure OpenfortProvider + + Wrap your app with `OpenfortProvider` from `@openfort/react`, along with wagmi and React Query providers: + + ```tsx + import { OpenfortProvider, getDefaultConfig } from "@openfort/react"; + import { WagmiProvider, createConfig } from "wagmi"; + import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; + import { arbitrumSepolia } from "viem/chains"; + + const config = createConfig( + getDefaultConfig({ + appName: "My App", + chains: [arbitrumSepolia], + }) + ); + + const queryClient = new QueryClient(); + + export function App() { + return ( + + + + + + + + ); + } + ``` + + ### 2. Get a signer from Openfort + + Use wagmi's `useWalletClient` hook to get a viem `WalletClient` from the Openfort embedded wallet: + + ```tsx + import { useWalletClient } from "wagmi"; + import type { WalletClient } from "viem"; + + const useOpenfortSigner = (): WalletClient | undefined => { + const { data: walletClient } = useWalletClient(); + return walletClient; + }; + ``` + + ### 3. Handle login + + Use Openfort's React hooks to manage authentication state and conditionally render your wallet UI: + + ```tsx + import { useUser, useUI, useSignOut } from "@openfort/react"; + + function OpenfortWallet() { + const { user, isAuthenticated } = useUser(); + const { setOpen } = useUI(); + const { signOut } = useSignOut(); + const signer = useOpenfortSigner(); + + if (!user) { + return

Loading...

; + } + + if (!isAuthenticated) { + return ; + } + + return ( +
+ + {signer ? :

Loading signer...

} +
+ ); + } + ``` + + ### 4. Create the client and send a transaction + + Pass the Openfort signer to `createSmartWalletClient` and use it to send transactions: + + ```tsx + import { useMemo, useCallback } from "react"; + import { zeroAddress } from "viem"; + import { createSmartWalletClient, alchemyWalletTransport } from "@alchemy/wallet-apis"; + import { arbitrumSepolia } from "viem/chains"; + import type { WalletClient } from "viem"; + + function SendTransaction({ signer }: { signer: WalletClient }) { + const client = useMemo( + () => + createSmartWalletClient({ + signer, + transport: alchemyWalletTransport({ + apiKey: "YOUR_ALCHEMY_API_KEY", + }), + chain: arbitrumSepolia, + paymaster: { + policyId: "YOUR_GAS_MANAGER_POLICY_ID", + }, + }), + [signer], + ); + + const handleSend = useCallback(async () => { + // Send the transaction + const { id } = await client.sendCalls({ + calls: [{ to: zeroAddress, value: BigInt(0), data: "0x" }], + }); + + // Wait for the transaction to be confirmed + const result = await client.waitForCallsStatus({ id }); + console.log(`Transaction hash: ${result.receipts?.[0]?.transactionHash}`); + }, [client]); + + return ; + } + ``` + + ### Notes + + * The `@openfort/react` SDK integrates with [wagmi](https://wagmi.sh/), so the signer is obtained via wagmi's `useWalletClient` hook. Since Openfort provides a `WalletClient` (not a `LocalAccount`), for EIP-7702 delegation you may need to use [non-7702 mode](/wallets/transactions/using-eip-7702#how-to-use-non-7702-mode). See the [EIP-7702 guide](/wallets/transactions/using-eip-7702) for details. + * See the [Sponsor gas](/wallets/transactions/sponsor-gas) guide for more on gas sponsorship configuration. + * Learn more about Openfort's React SDK in the [Openfort documentation](https://www.openfort.io/docs/products/embedded-wallet/react/quickstart). +
+ + + ## Setup + + Use the `@openfort/openfort-js` package with the Wallet Client SDK in a server or Node.js environment. + + ### Installation + + + ```shell npm + npm install @openfort/openfort-js @alchemy/wallet-apis viem + ``` + + ```shell bun + bun add @openfort/openfort-js @alchemy/wallet-apis viem + ``` + + ```shell yarn + yarn add @openfort/openfort-js @alchemy/wallet-apis viem + ``` + + ```shell pnpm + pnpm add @openfort/openfort-js @alchemy/wallet-apis viem + ``` + + + ### Prerequisites: Get your keys + + * Alchemy API key: + * Go to the [Alchemy Dashboard](https://dashboard.alchemy.com/) + * Create or select an app and copy the API key + * Gas sponsorship Policy ID (Gas Manager): + * Create a gas sponsorship policy in the [dashboard](https://dashboard.alchemy.com/services/gas-manager/configuration) and copy its Policy ID + * Openfort Publishable Key: + * Go to the [Openfort Dashboard](https://dashboard.openfort.xyz/) + * Create or select a project and copy the Publishable Key + * Openfort Shield Publishable Key: + * In the [Openfort Dashboard](https://dashboard.openfort.xyz/), navigate to Shield settings and copy the Shield Publishable Key + + + Both the Smart Wallets configuration and the gas sponsorship policy must be + linked to the application behind your Alchemy API key for sponsorship to work. + + + ### Send a transaction + + ```ts + import Openfort from "@openfort/openfort-js"; + import { createWalletClient, custom } from "viem"; + import { createSmartWalletClient, alchemyWalletTransport } from "@alchemy/wallet-apis"; + import { arbitrumSepolia } from "viem/chains"; + + // Initialize Openfort + const openfort = new Openfort({ + baseConfiguration: { + publishableKey: process.env.OPENFORT_PUBLISHABLE_KEY!, + }, + shieldConfiguration: { + shieldPublishableKey: process.env.OPENFORT_SHIELD_PUBLISHABLE_KEY!, + }, + }); + + // Authenticate the user (e.g., via email OTP) + await openfort.auth.requestEmailOTP({ email: "user@example.com" }); + // await openfort.auth.verifyEmailOTP({ email, code }); + + // Get the EIP-1193 provider from Openfort + const provider = await openfort.embeddedWallet.getEthereumProvider(); + const [address] = await provider.request({ method: "eth_requestAccounts" }); + + // Create a viem WalletClient from the Openfort provider + const signer = createWalletClient({ + account: address, + chain: arbitrumSepolia, + transport: custom(provider), + }); + + // Create the Smart Wallet client + const client = createSmartWalletClient({ + signer, + transport: alchemyWalletTransport({ apiKey: process.env.ALCHEMY_API_KEY! }), + chain: arbitrumSepolia, + paymaster: { policyId: process.env.ALCHEMY_POLICY_ID! }, + }); + + // Send the transaction + const { id } = await client.sendCalls({ + calls: [ + { + to: "0x0000000000000000000000000000000000000000", + value: BigInt(0), + data: "0x", + }, + ], + }); + + // Wait for the transaction to be confirmed + const result = await client.waitForCallsStatus({ id }); + console.log(`Transaction hash: ${result.receipts?.[0]?.transactionHash}`); + ``` + + ### Notes + + * Openfort provides an EIP-1193 provider, so the signer is created as a `WalletClient`. For EIP-7702, which requires `signAuthorization` on a `LocalAccount`, you may need to use [non-7702 mode](/wallets/transactions/using-eip-7702#how-to-use-non-7702-mode). See the [EIP-7702 guide](/wallets/transactions/using-eip-7702) for details. + * See the [Sponsor gas](/wallets/transactions/sponsor-gas) guide for more on gas sponsorship configuration. + * Learn more about Openfort's embedded wallets in the [Openfort documentation](https://www.openfort.io/docs). + +
From 7095cd6d8b9639a566ea38e75a12daf6745d3bd9 Mon Sep 17 00:00:00 2001 From: jakehobbs Date: Fri, 20 Mar 2026 15:13:18 -0700 Subject: [PATCH 2/3] docs: tweak openfort signer docs Co-Authored-By: Claude --- .../signers/custom-integration.mdx | 2 +- .../pages/third-party/signers/openfort.mdx | 40 ++++++++++++------- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/content/wallets/pages/third-party/signers/custom-integration.mdx b/content/wallets/pages/third-party/signers/custom-integration.mdx index 35b732a68..082fdd1de 100644 --- a/content/wallets/pages/third-party/signers/custom-integration.mdx +++ b/content/wallets/pages/third-party/signers/custom-integration.mdx @@ -129,6 +129,6 @@ console.log("Transaction confirmed:", txStatus.receipts?.[0]?.transactionHash); See full integration guides for supported providers: -* [Openfort](/docs/wallets/third-party/signers/openfort) * [Privy](/docs/wallets/third-party/signers/privy) +* [Openfort](/docs/wallets/third-party/signers/openfort) * [Turnkey](/docs/wallets/third-party/signers/turnkey) diff --git a/content/wallets/pages/third-party/signers/openfort.mdx b/content/wallets/pages/third-party/signers/openfort.mdx index af2ecddf9..b7cb42f19 100644 --- a/content/wallets/pages/third-party/signers/openfort.mdx +++ b/content/wallets/pages/third-party/signers/openfort.mdx @@ -6,7 +6,7 @@ slug: wallets/third-party/signers/openfort `@alchemy/wallet-apis` (v5.x.x) is currently in beta but is the recommended replacement for `@account-kit/wallet-client` (v4.x.x). If you run into any issues, please [reach out](mailto:support@alchemy.com). -Upgrade existing Openfort embedded wallets to Smart Wallets to enable gasless transactions, batching, and more. Keep Openfort for authentication and wallet management, no wallet migration needed. Add battle-tested transaction infrastructure using EIP-7702 to upgrade your wallets to Smart Wallets: +Upgrade existing Openfort embedded wallets to Smart Wallets to enable gasless transactions, batching, and more in under 10 minutes. Keep Openfort for authentication, no wallet migration needed. Add battle-tested transaction infrastructure using EIP-7702 to upgrade your wallets to Smart Wallets: * [#1 gas abstraction infrastructure](https://www.bundlebear.com/erc4337-bundlers/all) on the market * [370M+](https://www.bundlebear.com/erc4337-paymasters/all) sponsored transactions @@ -17,7 +17,7 @@ Upgrade existing Openfort embedded wallets to Smart Wallets to enable gasless tr ## Setup - Follow these steps to use Openfort signers with the Wallet Client SDK using the `@openfort/react` SDK. + Follow these steps to use Openfort signers with the Wallet Client SDK. ### Installation @@ -115,12 +115,12 @@ Upgrade existing Openfort embedded wallets to Smart Wallets to enable gasless tr import { useUser, useUI, useSignOut } from "@openfort/react"; function OpenfortWallet() { - const { user, isAuthenticated } = useUser(); + const { isLoading, isAuthenticated } = useUser(); const { setOpen } = useUI(); const { signOut } = useSignOut(); const signer = useOpenfortSigner(); - if (!user) { + if (isLoading) { return

Loading...

; } @@ -137,9 +137,9 @@ Upgrade existing Openfort embedded wallets to Smart Wallets to enable gasless tr } ``` - ### 4. Create the client and send a transaction + ### 4. Request an account and send a transaction - Pass the Openfort signer to `createSmartWalletClient` and use it to send transactions: + Openfort provides a `WalletClient` signer, which does not support EIP-7702 authorization signing. Use [`requestAccount`](/wallets/transactions/using-eip-7702#how-to-use-non-7702-mode) to create a smart wallet, then pass the account address to `sendCalls`: ```tsx import { useMemo, useCallback } from "react"; @@ -165,8 +165,14 @@ Upgrade existing Openfort embedded wallets to Smart Wallets to enable gasless tr ); const handleSend = useCallback(async () => { - // Send the transaction + // Request a smart wallet (required for WalletClient signers) + const { address } = await client.requestAccount({ + creationHint: { accountType: "sma-b" }, + }); + + // Send the transaction using the smart wallet address const { id } = await client.sendCalls({ + account: address, calls: [{ to: zeroAddress, value: BigInt(0), data: "0x" }], }); @@ -181,7 +187,6 @@ Upgrade existing Openfort embedded wallets to Smart Wallets to enable gasless tr ### Notes - * The `@openfort/react` SDK integrates with [wagmi](https://wagmi.sh/), so the signer is obtained via wagmi's `useWalletClient` hook. Since Openfort provides a `WalletClient` (not a `LocalAccount`), for EIP-7702 delegation you may need to use [non-7702 mode](/wallets/transactions/using-eip-7702#how-to-use-non-7702-mode). See the [EIP-7702 guide](/wallets/transactions/using-eip-7702) for details. * See the [Sponsor gas](/wallets/transactions/sponsor-gas) guide for more on gas sponsorship configuration. * Learn more about Openfort's React SDK in the [Openfort documentation](https://www.openfort.io/docs/products/embedded-wallet/react/quickstart).
@@ -189,7 +194,7 @@ Upgrade existing Openfort embedded wallets to Smart Wallets to enable gasless tr ## Setup - Use the `@openfort/openfort-js` package with the Wallet Client SDK in a server or Node.js environment. + Use the `@openfort/openfort-js` package with the Wallet Client SDK in a browser environment. ### Installation @@ -225,8 +230,7 @@ Upgrade existing Openfort embedded wallets to Smart Wallets to enable gasless tr * In the [Openfort Dashboard](https://dashboard.openfort.xyz/), navigate to Shield settings and copy the Shield Publishable Key - Both the Smart Wallets configuration and the gas sponsorship policy must be - linked to the application behind your Alchemy API key for sponsorship to work. + The gas sponsorship policy must be linked to the application behind your Alchemy API key for sponsorship to work. ### Send a transaction @@ -247,9 +251,9 @@ Upgrade existing Openfort embedded wallets to Smart Wallets to enable gasless tr }, }); - // Authenticate the user (e.g., via email OTP) + // Authenticate the user — verification is required before using the wallet await openfort.auth.requestEmailOTP({ email: "user@example.com" }); - // await openfort.auth.verifyEmailOTP({ email, code }); + await openfort.auth.verifyEmailOTP({ email: "user@example.com", code: "123456" }); // Get the EIP-1193 provider from Openfort const provider = await openfort.embeddedWallet.getEthereumProvider(); @@ -270,8 +274,14 @@ Upgrade existing Openfort embedded wallets to Smart Wallets to enable gasless tr paymaster: { policyId: process.env.ALCHEMY_POLICY_ID! }, }); - // Send the transaction + // Request a Smart Contract Account (required for WalletClient signers) + const { address: accountAddress } = await client.requestAccount({ + creationHint: { accountType: "sma-b" }, + }); + + // Send the transaction using the SCA address const { id } = await client.sendCalls({ + account: accountAddress, calls: [ { to: "0x0000000000000000000000000000000000000000", @@ -288,8 +298,8 @@ Upgrade existing Openfort embedded wallets to Smart Wallets to enable gasless tr ### Notes - * Openfort provides an EIP-1193 provider, so the signer is created as a `WalletClient`. For EIP-7702, which requires `signAuthorization` on a `LocalAccount`, you may need to use [non-7702 mode](/wallets/transactions/using-eip-7702#how-to-use-non-7702-mode). See the [EIP-7702 guide](/wallets/transactions/using-eip-7702) for details. * See the [Sponsor gas](/wallets/transactions/sponsor-gas) guide for more on gas sponsorship configuration. + * This example uses Openfort's `@openfort/openfort-js` client-side package. `@alchemy/wallet-apis` can be used in any JavaScript environment. * Learn more about Openfort's embedded wallets in the [Openfort documentation](https://www.openfort.io/docs). From 8ea9c22d9634aadd57cb6b3efc4d701e409da1a5 Mon Sep 17 00:00:00 2001 From: jakehobbs Date: Fri, 20 Mar 2026 15:48:08 -0700 Subject: [PATCH 3/3] docs: mention SCA address is stable Co-Authored-By: Claude --- content/wallets/pages/third-party/signers/openfort.mdx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/content/wallets/pages/third-party/signers/openfort.mdx b/content/wallets/pages/third-party/signers/openfort.mdx index b7cb42f19..85a3ad956 100644 --- a/content/wallets/pages/third-party/signers/openfort.mdx +++ b/content/wallets/pages/third-party/signers/openfort.mdx @@ -139,7 +139,7 @@ Upgrade existing Openfort embedded wallets to Smart Wallets to enable gasless tr ### 4. Request an account and send a transaction - Openfort provides a `WalletClient` signer, which does not support EIP-7702 authorization signing. Use [`requestAccount`](/wallets/transactions/using-eip-7702#how-to-use-non-7702-mode) to create a smart wallet, then pass the account address to `sendCalls`: + Openfort provides a `WalletClient` signer, which does not support EIP-7702 authorization signing. Use [`requestAccount`](/wallets/transactions/using-eip-7702#how-to-use-non-7702-mode) to create a smart wallet, then pass the account address to `sendCalls`. The returned address is stable for a given signer and can be stored — you don't need to call `requestAccount` before every transaction: ```tsx import { useMemo, useCallback } from "react"; @@ -274,12 +274,13 @@ Upgrade existing Openfort embedded wallets to Smart Wallets to enable gasless tr paymaster: { policyId: process.env.ALCHEMY_POLICY_ID! }, }); - // Request a Smart Contract Account (required for WalletClient signers) + // Request a smart wallet (required for WalletClient signers) + // The returned address is stable for a given signer and can be stored for later use const { address: accountAddress } = await client.requestAccount({ creationHint: { accountType: "sma-b" }, }); - // Send the transaction using the SCA address + // Send the transaction using the smart wallet address const { id } = await client.sendCalls({ account: accountAddress, calls: [