permissionless for ERC-4337 UserOperations. Single-chain (Polygon) by default.
For the complete one-shot LLM prompt, see
/llms-iframe-wagmi-viem.txt.Tech Stack
- React (18+) with TypeScript
- Vite as build tool
- Tailwind CSS for styling
- wagmi for wallet connection
- viem for Ethereum interactions
- permissionless for ERC-4337 smart accounts
- @tanstack/react-query (wagmi peer dependency)
Smart Account Constants
These constants are part of the Deframe protocol and must be used exactly as specified:Smart Account Derivation
Usepermissionless’s toSafeSmartAccount to derive the smart account address:
- Client: a viem
publicClientconnected to Polygon via Alchemy RPC - EntryPoint: version 0.6 (
entryPoint06Addressfromviem/account-abstraction) - Owners: the connected EOA wallet address
- Salt:
DEFRAME_SALT - Safe version:
'1.4.1' - Safe 4337 module:
SAFE_4337_MODULE_ADDRESS
safeAccount.address is passed to the iframe as smartAccountAddress.
The
toSafeSmartAccount API shape may vary by permissionless version. The key parameters above are stable — consult the permissionless docs for the exact call signature.Wallet Connection
Configure wagmi with:- Chain: Polygon (chain ID 137)
- Connector:
injected()(MetaMask, browser wallets) - Transport: Alchemy RPC (
https://polygon-mainnet.g.alchemy.com/v2/{ALCHEMY_RPC_ID})
WagmiProvider and QueryClientProvider.
Use wagmi hooks:
useAccount()— get connected address and statususeConnect()— connect with the injected connectoruseDisconnect()— disconnect wallet
UserOperation Flow
To process bytecodes into a signed ERC-4337 UserOperation:- Get EOA from the browser wallet (
window.ethereum) - Create a wallet client (viem) using the browser wallet as transport
- Create a public client (viem) connected to Polygon via Alchemy RPC
- Create a paymaster client (viem) using the same Alchemy RPC
- Create the Safe smart account using
toSafeSmartAccountwith Deframe constants - Create a smart account client (permissionless) with the safe account, paymaster, and bundler transport
- Transform bytecodes to calls:
{ to, data, value }— convertvaluestrings toBigInt - Prepare the UserOperation via the smart account client, passing the Alchemy
policyIdas paymaster context - Sign the UserOperation using the Safe smart account signing method
- Submit via
sendUserOperationon the bundler client - Poll for the transaction receipt using
getUserOperationReceiptandwaitForUserOperationReceipt
The exact methods for steps 8-10 depend on your
permissionless version. Some versions combine prepare + sign + send into a single call. Consult the docs for your version.Environment Variables
VITE_ prefix for Vite’s environment variable exposure. Default chain is Polygon (137).
UI Requirements
- Header with Connect Wallet button (shows address + Disconnect when connected), Earn/Swap toggle
- Before wallet connection: placeholder message (“Connect your wallet to begin”)
- While deriving smart account: loading spinner
- After connection + SA derived: render the Deframe iframe with correct URL params
- Iframe:
allow="clipboard-write", fills available space, not in DOM before wallet connection
Documentation References
- Iframe Overview — Protocol spec, query params, postMessage types
- Privy Wrapper — Alternative wrapper with Privy auth + multi-chain
- wagmi docs
- viem docs
- permissionless docs