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..082fdd1de 100644 --- a/content/wallets/pages/third-party/signers/custom-integration.mdx +++ b/content/wallets/pages/third-party/signers/custom-integration.mdx @@ -130,4 +130,5 @@ console.log("Transaction confirmed:", txStatus.receipts?.[0]?.transactionHash); See full integration guides for supported providers: * [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 new file mode 100644 index 000000000..85a3ad956 --- /dev/null +++ b/content/wallets/pages/third-party/signers/openfort.mdx @@ -0,0 +1,306 @@ +--- +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 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 +* 99.9% SLAs +* Trusted by Worldcoin, JP Morgan, Gensyn, and more + + + + ## Setup + + Follow these steps to use Openfort signers with the Wallet Client 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 { isLoading, isAuthenticated } = useUser(); + const { setOpen } = useUI(); + const { signOut } = useSignOut(); + const signer = useOpenfortSigner(); + + if (isLoading) { + return

Loading...

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

Loading signer...

} +
+ ); + } + ``` + + ### 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`. 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"; + 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 () => { + // 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" }], + }); + + // Wait for the transaction to be confirmed + const result = await client.waitForCallsStatus({ id }); + console.log(`Transaction hash: ${result.receipts?.[0]?.transactionHash}`); + }, [client]); + + return ; + } + ``` + + ### Notes + + * 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 browser 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 + + + 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 — verification is required before using the wallet + await openfort.auth.requestEmailOTP({ email: "user@example.com" }); + await openfort.auth.verifyEmailOTP({ email: "user@example.com", code: "123456" }); + + // 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! }, + }); + + // 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 smart wallet address + const { id } = await client.sendCalls({ + account: accountAddress, + 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 + + * 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). + +