From openfort
Always use this skill when the user asks about embedded wallets, client-side wallets, user-facing wallets, wallet integration in React/React Native/Swift/Unity/JS apps, or non-custodial wallets with Openfort. Covers all client SDKs. Trigger on: "embedded wallet", "client wallet", "user wallet", "@openfort/react", "@openfort/react-native", "OpenfortSwift", "openfort-csharp-unity", "@openfort/openfort-js", "OpenfortProvider", "OpenfortButton", "wallet setup", "wallet integration", "passkey recovery", "gasless transaction client", "auth modal", or any client-side wallet operation with Openfort.
How this skill is triggered — by the user, by Claude, or both
Slash command
/openfort:embedded-walletThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Embedded wallets provide a seamless experience by abstracting away wallet management. Users interact with your app without needing to understand private keys, seed phrases, or blockchain concepts.
Embedded wallets provide a seamless experience by abstracting away wallet management. Users interact with your app without needing to understand private keys, seed phrases, or blockchain concepts.
Openfort provides embedded wallet SDKs for multiple platforms:
| Platform | Package | Best for |
|---|---|---|
| React / Next.js | @openfort/react | Web apps with pre-built UI modal |
| React Native / Expo | @openfort/react-native | Mobile apps (iOS + Android) |
| iOS / Swift | OpenfortSwift | Native iOS apps |
| Unity / C# | openfort-csharp-unity | Games (Windows, macOS, Android, iOS, WebGL) |
| Vanilla JS / TS | @openfort/openfort-js | Custom UIs, any JS framework, bare-metal access |
Which SDK should I use?
- If you're building a React or Next.js web app → use
@openfort/react(includes pre-built auth modal + wallet UI)- If you're building a React Native / Expo mobile app → use
@openfort/react-native- If you're building a native iOS app → use
OpenfortSwift- If you're building a Unity game → use
openfort-csharp-unity- If you're building with Svelte, Vue, Angular, vanilla JS, or need custom login flows → use
@openfort/openfort-js
For detailed API references per SDK, see the reference files:
references/openfort-react.md — React / Next.jsreferences/openfort-react-native.md — React Native / Exporeferences/openfort-swift.md — iOS / Swiftreferences/openfort-unity.md — Unity / C#references/openfort-js.md — Vanilla JS / TSThe fastest way to get started with a web app is the Openfort CLI:
npm create openfort@latest
# or
pnpm create openfort@latest
# or
yarn create openfort
This scaffolds a new project with all dependencies, configurations, and a working embedded wallet integration. You can select:
The CLI currently scaffolds React web apps. For other platforms, follow the manual setup below.
Before integrating any SDK, get your keys from the Openfort Dashboard:
pk_test_...) — identifies your projectyour-shield-publishable-key) — for embedded wallet encryptionpol_..., optional) — for gasless transactions@openfort/reactPre-built auth modal + wallet UI. Supports Ethereum (EVM) and Solana chains.
# Ethereum (EVM) — with wagmi
npm install @openfort/react @tanstack/react-query wagmi viem
# Solana — no wagmi needed
npm install @openfort/react @tanstack/react-query @solana/kit
VITE_OPENFORT_PUBLISHABLE_KEY=pk_test_...
VITE_SHIELD_PUBLISHABLE_KEY=your-shield-publishable-key
VITE_WALLET_CONNECT_PROJECT_ID=... # Optional — enables external wallets (EVM only)
VITE_FEE_SPONSORSHIP_ID=pol_... # Optional — gasless transactions
VITE_CREATE_ENCRYPTED_SESSION_ENDPOINT=https://... # Backend endpoint for automatic recovery
For Next.js, use NEXT_PUBLIC_ prefix instead of VITE_.
The provider stack is: QueryClientProvider → WagmiProvider → OpenfortWagmiBridge → OpenfortProvider.
"use client" // Required in Next.js App Router
import { OpenfortProvider, AuthProvider } from '@openfort/react'
import { getDefaultConfig, OpenfortWagmiBridge } from '@openfort/react/wagmi'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { base, baseSepolia } from 'viem/chains'
import { createConfig, http, WagmiProvider } from 'wagmi'
const config = createConfig(
getDefaultConfig({
appName: 'My App',
chains: [base, baseSepolia],
walletConnectProjectId: import.meta.env.VITE_WALLET_CONNECT_PROJECT_ID,
transports: {
[base.id]: http('https://your-base-rpc.com'),
[baseSepolia.id]: http(),
},
}),
)
const queryClient = new QueryClient()
const walletConfig = {
shieldPublishableKey: import.meta.env.VITE_SHIELD_PUBLISHABLE_KEY!,
ethereum: {
ethereumFeeSponsorshipId: import.meta.env.VITE_FEE_SPONSORSHIP_ID,
},
createEncryptedSessionEndpoint: import.meta.env.VITE_CREATE_ENCRYPTED_SESSION_ENDPOINT,
connectOnLogin: true,
}
export function Providers({ children }: { children: React.ReactNode }) {
return (
<QueryClientProvider client={queryClient}>
<WagmiProvider config={config}>
<OpenfortWagmiBridge>
<OpenfortProvider
publishableKey={import.meta.env.VITE_OPENFORT_PUBLISHABLE_KEY!}
walletConfig={walletConfig}
uiConfig={{
theme: 'midnight',
mode: 'dark',
authProviders: [AuthProvider.GOOGLE, AuthProvider.EMAIL_OTP, AuthProvider.WALLET],
}}
>
{children}
</OpenfortProvider>
</OpenfortWagmiBridge>
</WagmiProvider>
</QueryClientProvider>
)
}
No wagmi, no bridge — just QueryClientProvider → OpenfortProvider.
"use client"
import { OpenfortProvider, AuthProvider, ChainTypeEnum } from '@openfort/react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
const queryClient = new QueryClient()
const walletConfig = {
shieldPublishableKey: import.meta.env.VITE_SHIELD_PUBLISHABLE_KEY!,
chainType: ChainTypeEnum.SVM,
solana: { cluster: 'mainnet-beta' },
createEncryptedSessionEndpoint: import.meta.env.VITE_CREATE_ENCRYPTED_SESSION_ENDPOINT,
connectOnLogin: true,
}
export function Providers({ children }: { children: React.ReactNode }) {
return (
<QueryClientProvider client={queryClient}>
<OpenfortProvider
publishableKey={import.meta.env.VITE_OPENFORT_PUBLISHABLE_KEY!}
walletConfig={walletConfig}
uiConfig={{
theme: 'midnight',
mode: 'dark',
authProviders: [AuthProvider.GOOGLE, AuthProvider.EMAIL_OTP],
}}
>
{children}
</OpenfortProvider>
</QueryClientProvider>
)
}
OpenfortButton adapts to user state automatically:
import { OpenfortButton } from '@openfort/react'
function App() {
return <OpenfortButton />
}
// Auth
import { useUser, useEmailAuth, useEmailOtpAuth, usePhoneOtpAuth, useOAuth, useGuestAuth, useSignOut } from '@openfort/react'
// Wallet
import { useEthereumEmbeddedWallet } from '@openfort/react/ethereum'
import { useSolanaEmbeddedWallet } from '@openfort/react/solana'
// UI control
import { useUI } from '@openfort/react' // open/close modal programmatically
// wagmi integration
import { useWalletAuth, useChainIsSupported } from '@openfort/react/wagmi'
uiConfig={{
theme: 'midnight', // 'auto' | 'web95' | 'retro' | 'soft' | 'midnight' | 'minimal' | 'rounded' | 'nouns'
mode: 'dark', // 'light' | 'dark' | 'auto'
authProviders: [AuthProvider.GOOGLE, AuthProvider.EMAIL_OTP, AuthProvider.WALLET],
authProvidersLength: 4, // How many to show before "More options"
walletRecovery: {
allowedMethods: [RecoveryMethod.AUTOMATIC, RecoveryMethod.PASSKEY],
defaultMethod: RecoveryMethod.AUTOMATIC,
},
// termsOfServiceUrl, privacyPolicyUrl, disclaimer, customTheme, logo, etc.
}}
@openfort/react-nativeNative mobile SDK. Supports Ethereum and Solana embedded wallets.
npx --yes expo install expo-apple-authentication expo-application expo-crypto expo-secure-store expo-constants
npm install react-native-get-random-values @openfort/react-native
# Optional:
npm install react-native-passkeys # For passkey recovery
npx expo install expo-web-browser expo-linking # For OAuth
react-native-get-random-values must be imported first:
// entrypoint.ts
import "react-native-get-random-values";
import "expo-router/entry";
Update package.json: { "main": "entrypoint.ts" }
import { OpenfortProvider, RecoveryMethod } from "@openfort/react-native";
import Constants from "expo-constants";
export default function RootLayout() {
return (
<OpenfortProvider
publishableKey={Constants.expoConfig?.extra?.openfortPublishableKey}
walletConfig={{
shieldPublishableKey: Constants.expoConfig?.extra?.openfortShieldPublishableKey,
recoveryMethod: RecoveryMethod.AUTOMATIC,
feeSponsorshipId: Constants.expoConfig?.extra?.openfortPolicyId,
createEncryptedSessionEndpoint: Constants.expoConfig?.extra?.openfortShieldRecoveryEndpoint,
}}
supportedChains={[{
id: 84532,
name: 'Base Sepolia',
nativeCurrency: { name: 'Base Sepolia Ether', symbol: 'ETH', decimals: 18 },
rpcUrls: { default: { http: ['https://sepolia.base.org'] } },
}]}
verbose={__DEV__}
>
{/* Your app */}
</OpenfortProvider>
);
}
No wagmi, no bridge, no QueryClientProvider, no manual WebView — just OpenfortProvider.
import { useEmbeddedEthereumWallet } from '@openfort/react-native' // EVM
import { useEmbeddedSolanaWallet } from '@openfort/react-native' // Solana
import { AuthBoundary } from '@openfort/react-native' // Auth state boundary
import { useUser, useEmailAuth, useEmailAuthOtp, useOAuth, useGuestAuth, useSignOut } from '@openfort/react-native'
<AuthBoundary
loading={<LoadingScreen />}
unauthenticated={<LoginScreen />}
error={(error) => <ErrorScreen error={error} />}
>
<MainApp />
</AuthBoundary>
OpenfortSwiftNative Swift SDK for iOS apps. Ethereum-only (EVM).
Add via Swift Package Manager: https://github.com/openfort-xyz/swift-sdk.git
Add OFConfig.plist to your Xcode project:
openfortPublishableKey (required)shieldPublishableKey (required)shieldEncryptionKey or shieldEncryptionEndpoint (for recovery)import OpenfortSwift
// In AppDelegate or App init:
try OFSDK.initialize()
// With third-party auth:
try OFSDK.initialize(thirdPartyAuth: .init(
provider: .firebase,
getAccessToken: { try await Auth.auth().currentUser?.getIDToken() ?? "" }
))
let sdk = OFSDK.shared
// Authenticate
try await sdk.logInWithEmailPassword(email: "[email protected]", password: "pass")
try await sdk.initOAuth(provider: .google, redirectTo: "myapp://callback")
// Configure embedded wallet (auto create or recover)
let account = try await sdk.configureEmbeddedWallet(
chainId: 80002,
recoveryMethod: .automatic(encryptionSession: session)
)
// Get EIP-1193 provider
let provider = try sdk.getEthereumProvider(policy: "pol_...")
// Send transaction
let txHash = try await provider.request(method: "eth_sendTransaction", params: [...])
openfort-csharp-unityGame SDK supporting Windows, macOS, Android, iOS, and WebGL.
Via UPM git URL: https://github.com/openfort-xyz/openfort-csharp-unity.git?path=/src/Packages/OpenfortSDK
Requires UniTask v2.3.3.
using Openfort;
var sdk = await OpenfortSDK.Init("pk_test_...", "your-shield-publishable-key");
// Authenticate
await sdk.LogInWithEmailPassword("[email protected]", "pass");
// Configure embedded wallet
var account = await sdk.ConfigureEmbeddedWallet(
chainId: 80002,
recoveryMethod: RecoveryMethod.Automatic,
encryptionSession: session
);
// Get provider and send transaction
var provider = sdk.GetEthereumProvider(policy: "pol_...");
var txHash = await provider.Request("eth_sendTransaction", new object[] { txParams });
@openfort/openfort-jsLow-level SDK for custom login flows and bare-metal API access. Works with any framework (Svelte, Vue, Angular, etc.) or no framework at all.
npm install @openfort/openfort-js@latest
import { Openfort } from '@openfort/openfort-js'
const openfort = new Openfort({
baseConfiguration: { publishableKey: 'pk_test_...' },
shieldConfiguration: { shieldPublishableKey: 'your-shield-publishable-key' },
})
await openfort.waitForInitialization()
// Authenticate
await openfort.auth.logInWithEmailPassword({ email: '[email protected]', password: 'pass' })
// Or OAuth
const url = await openfort.auth.initOAuth({ provider: OAuthProvider.GOOGLE, redirectTo: '...' })
// Configure embedded wallet (auto create or recover)
const account = await openfort.embeddedWallet.configure({
chainId: 80002,
recoveryParams: {
recoveryMethod: RecoveryMethod.AUTOMATIC,
encryptionSession: await fetchEncryptionSession(),
},
})
// Get EIP-1193 provider
const provider = await openfort.embeddedWallet.getEthereumProvider({ policy: 'pol_...' })
// Send transaction
const txHash = await provider.request({
method: 'eth_sendTransaction',
params: [{ from: account.address, to: '0x...', value: '0x...', data: '0x' }],
})
// Viem
import { createWalletClient, custom } from 'viem'
const walletClient = createWalletClient({ chain: sepolia, transport: custom(provider) })
// Ethers.js v6
import { ethers } from 'ethers'
const ethersProvider = new ethers.BrowserProvider(provider)
const signer = await ethersProvider.getSigner()
All SDKs support the same auth methods:
Embedded wallets use client-side encryption. Recovery is needed when users switch devices:
Set up gas sponsorship in the dashboard under Policies and Fee Sponsorship, then pass the pol_... ID to your SDK config.
Openfort embedded wallets support any EVM chain and Solana. Configure chains in your SDK setup with chain IDs and RPC URLs.
npx claudepluginhub openfort-xyz/agent-skills --plugin openfortCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.