A developer demo showcasing EIP-7702 mode with Particle Network's Universal Accounts and Privy authentication.
EIP-7702 lets an EOA act directly as a Universal Account—no separate contract deployment or asset transfers required. Your existing wallet address gains Universal Account features instantly.
Features demonstrated:
- Unified balance view across EVM chains + Solana
- Swap/bridge tokens to any supported chain via LI.FI for token discovery and Universal Account infrastructure for liquidity orchestration
- Withdraw USDC to external addresses
- Social login with Privy (email, Google, Twitter)
git clone https://github.com/soos3d/universal-accounts-7702
yarn installCopy .env.example to .env and add your credentials:
# Particle Network - https://dashboard.particle.network
NEXT_PUBLIC_PROJECT_ID="your-particle-project-id"
NEXT_PUBLIC_CLIENT_KEY="your-particle-client-key"
NEXT_PUBLIC_APP_ID="your-particle-app-id"
# Privy - https://dashboard.privy.io
NEXT_PUBLIC_PRIVY_APP_ID="your-privy-app-id"
NEXT_PUBLIC_PRIVY_CLIENT_ID="your-privy-client-id"yarn dev| Command | Description |
|---|---|
yarn dev |
Start development server |
yarn build |
Production build |
yarn start |
Start production server |
yarn lint |
Run ESLint |
Traditional Smart Accounts:
EOA (0xABC...) → Deploy Smart Account (0xDEF...) → Transfer assets → Use features
EIP-7702 Mode:
EOA (0xABC...) → Sign authorization → EOA becomes Universal Account
Key difference: Same address, no transfers, zero friction.
const ua = new UniversalAccount({
projectId: process.env.NEXT_PUBLIC_PROJECT_ID!,
projectClientKey: process.env.NEXT_PUBLIC_CLIENT_KEY!,
projectAppUuid: process.env.NEXT_PUBLIC_APP_ID!,
smartAccountOptions: {
useEIP7702: true, // Enable 7702 mode
ownerAddress: wallet.address,
},
});const transaction = await ua.createUniversalTransaction({
chainId: CHAIN_ID.BASE_MAINNET,
expectTokens: [{ tokenAddress: USDC_ADDRESS, amount: "10" }],
transactions: [{ to: recipient, data: "0x", value: "0" }],
});On first transaction per chain, the SDK returns userOps that need 7702 authorization. This demo uses Privy's useSign7702Authorization hook:
// Check each userOp for required authorization
for (const userOp of transaction.userOps) {
if (userOp.eip7702Auth && !userOp.eip7702Delegated) {
// Sign with Privy's hook
const auth = await signAuthorization({
contractAddress: userOp.eip7702Auth.address,
chainId: userOp.eip7702Auth.chainId,
nonce: userOp.eip7702Auth.nonce,
});
// Serialize signature for SDK
const sig = Signature.from({ r: auth.r, s: auth.s, yParity: auth.yParity });
authorizations.push({
userOpHash: userOp.userOpHash,
signature: sig.serialized,
});
}
}// Sign the transaction root hash
const { signature } = await signMessage({ message: transaction.rootHash });
// Send with authorizations
const result = await ua.sendTransaction(transaction, signature, authorizations);- First tx per chain: Requires EIP-7702 authorization signature
- Subsequent txs: No re-authorization needed (
eip7702Delegatedwill betrue) - Signature format: Privy returns
r, s, yParity; SDK expects serialized hex viaethers.Signature
See lib/eip7702.ts for the full implementation.
Chains supporting 7702: Ethereum, Arbitrum, Base, Optimism, Polygon, BNB Chain, Sonic, Berachain
MIT