Use mode: 'eoa-7702' for embedded wallet users (Privy, Dynamic, Turnkey) that support EIP-7702 delegation. This gives you smart account capabilities without deploying a separate contract.
How EIP-7702 Mode Works
EIP-7702 lets an EOA temporarily delegate to smart contract code. This means:
No separate smart account deployment
Single signature like smart accounts
No fundingTokens required
Native gas abstraction
First-time setup
User signs an authorization to delegate their EOA (once per chain)
Get quote
API returns a simple payload to sign
User signs
One signature for any operation
MEE executes
Transaction includes delegation + operations atomically
Basic Request
const quote = await fetch ( 'https://api.biconomy.io/v1/quote' , {
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'X-API-Key' : 'YOUR_API_KEY'
},
body: JSON . stringify ({
mode: 'eoa-7702' ,
ownerAddress: '0xYourUserAddress' ,
composeFlows: [{
type: '/instructions/intent-simple' ,
data: {
srcChainId: 8453 ,
dstChainId: 10 ,
srcToken: '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913' ,
dstToken: '0x94b008aa00579c1307b0ef2c499ad98a8ce58e58' ,
amount: '100000000' ,
slippage: 0.01
}
}]
})
}). then ( r => r . json ());
Required Parameters
Parameter Type Description mode'eoa-7702'Must be 'eoa-7702' ownerAddressstring User’s EOA address composeFlowsarray Operations to execute
No fundingTokens needed—7702 mode works like smart accounts but uses the EOA directly.
Handling First-Time Authorization
If the user hasn’t delegated their EOA yet, the API returns a 412 error with authorization data:
const response = await fetch ( 'https://api.biconomy.io/v1/quote' , {
method: 'POST' ,
body: JSON . stringify ({
mode: 'eoa-7702' ,
ownerAddress ,
composeFlows: [ ... ]
})
});
// First time? API returns 412
if ( response . status === 412 ) {
const error = await response . json ();
console . log ( 'Authorization needed:' , error . authorizations );
// Handle authorization flow...
}
412 Response Structure
{
"error" : "MISSING_AUTHORIZATION" ,
"message" : "EIP-7702 authorization required" ,
"authorizations" : [
{
"chainId" : 8453 ,
"address" : "0x00000069E0Fb590E092Dd0E36FF93ac28ff11a3a" ,
"nonce" : 38
}
]
}
Complete Authorization Flow
async function getQuoteWith7702 ( ownerAddress , composeFlows , walletClient ) {
// 1. Try without authorization
let response = await fetch ( 'https://api.biconomy.io/v1/quote' , {
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' },
body: JSON . stringify ({
mode: 'eoa-7702' ,
ownerAddress ,
composeFlows
})
});
// 2. Handle 412 - need authorization
if ( response . status === 412 ) {
const error = await response . json ();
// Sign each authorization
const signedAuths = await Promise . all (
error . authorizations . map ( async ( auth ) => {
const signed = await walletClient . signAuthorization ({
contractAddress: auth . address ,
chainId: auth . chainId ,
nonce: auth . nonce
});
return {
... signed ,
yParity: signed . yParity ,
v: signed . v ?. toString ()
};
})
);
// 3. Retry with authorizations
response = await fetch ( 'https://api.biconomy.io/v1/quote' , {
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' },
body: JSON . stringify ({
mode: 'eoa-7702' ,
ownerAddress ,
authorizations: signedAuths ,
composeFlows
})
});
}
return response . json ();
}
Authorization only happens once per chain. After the first transaction, subsequent quotes won’t return 412.
Quote Response
After authorization (or if already authorized), you get a normal quote:
{
"quoteType" : "simple" ,
"payloadToSign" : [{
"signablePayload" : {
"message" : {
"raw" : "0xed96a92aa94b8b1927fc7c52ca3b3fcd0d706147dfbeda34a62dc232f6993029"
}
}
}],
"fee" : { "amount" : "50000" , "token" : "0x..." , "chainId" : 8453 }
}
Signing the Payload
EIP-7702 mode uses simple message signing:
const payload = quote . payloadToSign [ 0 ];
const signature = await walletClient . signMessage ({
message: payload . signablePayload . message ,
account
});
Complete Example
import { createWalletClient , http , parseUnits } from 'viem' ;
import { base } from 'viem/chains' ;
const USDC_BASE = '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913' ;
const USDT_OP = '0x94b008aa00579c1307b0ef2c499ad98a8ce58e58' ;
async function swapWith7702 ( ownerAddress , walletClient ) {
// 1. Get quote (handles 412 automatically)
const quote = await getQuoteWith7702 (
ownerAddress ,
[{
type: '/instructions/intent-simple' ,
data: {
srcChainId: 8453 ,
dstChainId: 10 ,
srcToken: USDC_BASE ,
dstToken: USDT_OP ,
amount: parseUnits ( '100' , 6 ). toString (),
slippage: 0.01
}
}],
walletClient
);
// 2. Sign the execution payload
const payload = quote . payloadToSign [ 0 ];
const signature = await walletClient . signMessage ({
message: payload . signablePayload . message ,
account: walletClient . account
});
// 3. Execute
const result = await fetch ( 'https://api.biconomy.io/v1/execute' , {
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' },
body: JSON . stringify ({
... quote ,
payloadToSign: [{ ... payload , signature }]
})
}). then ( r => r . json ());
return result . supertxHash ;
}
Wallet Support
EIP-7702 requires wallet support for signAuthorization. Currently supported by:
Standard browser wallets (MetaMask, Rabby) don’t support EIP-7702 yet. Use mode: 'eoa' for those users.
When to Use EIP-7702 Mode
Best For
Embedded wallets (Privy, Dynamic, Turnkey)
Backend systems with private key access
Apps wanting smart account UX without deployment
Single-signature flows
Not For
MetaMask/Rabby users (use eoa mode)
Wallets without 7702 support
Users who need persistent smart accounts
Comparison with Other Modes
Feature EOA EIP-7702 Smart Account Wallet support All Embedded only All (with SA) Signatures 1 per token 1 always 1 always fundingTokens Required Not needed Not needed First-time setup None Authorization Account deploy Cross-chain gas Limited Yes Yes
Next Steps