Overview
This example covers:- Creating a smart account for an EOA with
POST /smart-account - Waiting for the smart account to deploy on-chain
- Funding the smart account from the EOA (a standard ERC-20 transfer)
- Generating a deposit
userOperationwithGET /strategies/:id/bytecode?output=userOperation - Signing the userOperation (Safe 4337
SafeOpEIP-712) - Propagating it with
POST /aa/send-user-operation
The signer key is the smart account’s owner. The EOA you use to sign the userOperation must be the same
owner
you pass to POST /smart-account, or the Safe 4337 module rejects the signature (AA24).Prerequisites
- Node.js 18+
- Pods API key
- An EOA (private key) with USDC on Polygon to deposit
- Basic understanding of async/await
Gas is sponsored. The deposit userOperation is paid by a paymaster, so the smart account only needs the asset you
are depositing (USDC) — it does not need native MATIC for gas.
Installation
- ethers.js
- viem
Environment Variables
Create a.env file:
Step-by-Step Walkthrough
1. Initialize clients
- ethers.js
- viem
2. Create the smart account
Create a smart account owned by the EOA. The address is deterministic for anowner + chainId, so this call is
idempotent — repeated calls return the same record.
The endpoint returns
200 with the record immediately, while the Safe is deployed in the background. The next
step waits for that deployment to land on-chain.3. Wait for on-chain deployment
The smart account must have code on-chain before you can build a userOperation for it. Poll until it’s deployed.- ethers.js
- viem
4. Fund the smart account
Move the asset you want to deposit from the EOA to the smart account. This is a plain ERC-20transfer() — there is no
Pods endpoint for it.
- ethers.js
- viem
Only the deposit asset (USDC) is required — gas for the deposit userOperation is sponsored by a paymaster.
5. Request the deposit userOperation
Ask the API for the lend bytecode as a fully-populated (but unsigned) userOperation, using the smart account as the wallet. Gas limits andpaymasterAndData are filled in for you.
userOperation contains sender, nonce, initCode, callData, the gas fields, paymasterAndData, and an empty
signature you fill in next.
6. Sign the userOperation (SafeOp)
A Safe with the 4337 module validates the userOperation against the module’s
SafeOp EIP-712 hash — not the
vanilla ERC-4337 UserOperation hash. The EIP-712 verifyingContract is the Safe 4337 module, and the packed
signature is 12 zero bytes (validAfter + validUntil) followed by the 65-byte ECDSA signature.- ethers.js
- viem
7. Send the userOperation
Propagate the signed userOperation to the bundler. The endpoint returns theuserOpHash.
Numeric userOperation fields may be decimal or
0x-hex strings — the endpoint normalizes them, and the SafeOp
signature hashes the integer values, so signing the fields exactly as returned by Step 5 is correct.8. Track the deposit (optional)
Use theid from Step 5 to poll the action until it reaches a terminal state.
Error Handling
Expected Output
Next Steps
Strategy Deposit (EOA)
The same deposit flow signing directly with an EOA
Check Positions
Track the smart account’s positions
Strategy Withdrawal
Withdraw from strategies, including cross-chain
API Reference
View complete API documentation