Skip to main content
This example demonstrates how to deposit funds into a DeFi yield strategy using the Deframe API and EIP-7702. Instead of sending each transaction individually, EIP-7702 collapses the entire sequence into a single atomic operation executed directly from your EOA — no smart-contract wallet or contract deployment required.

Overview

This example covers:
  • Fetching available strategies
  • Getting strategy details
  • Generating transaction bytecode
  • Batching and executing via EIP-7702
  • Verifying the deposit

Prerequisites

  • Node.js 18+
  • Deframe API key
  • Ethereum wallet with USDC balance
  • Basic understanding of async/await

Installation

npm install axios viem

Environment Variables

Create a .env file:
DEFRAME_API_KEY=your-api-key
PRIVATE_KEY=0x...
VITE_RPC_URL=https://eth-mainnet.g.alchemy.com/v2/your-key
Never commit your .env file to version control. Add it to .gitignore.

Step-by-Step Walkthrough

1. Initialize API Client

import axios from 'axios'

const deframe = axios.create({
  baseURL: 'https://api.deframe.io',
  headers: {
    'x-api-key': process.env.DEFRAME_API_KEY,
    'Content-Type': 'application/json'
  }
})

2. Fetch Available Strategies

const { data: strategies } = await deframe.get('/strategies', {
  params: { page: '1', limit: '10' }
})

console.log('Available strategies:')
strategies.data.forEach(strategy => {
  console.log(`- ${strategy.id} (${strategy.protocol})`)
  console.log(`  APY: ${(strategy.apy * 100).toFixed(2)}%`)
})

3. Get Strategy Details

const strategyId = 'aave-usdc-polygon'
const { data: strategy } = await deframe.get(`/strategies/${strategyId}`)

console.log('Strategy:', strategy.id)
console.log('Protocol:', strategy.protocol)
console.log('Network:', strategy.network)
console.log('Asset:', strategy.assetName)
console.log('APY:', (strategy.apy * 100).toFixed(2) + '%')
console.log('Status:', strategy.paused ? 'Paused' : 'Active')

4. Generate Bytecode

The amount parameter is in the token’s base units (e.g. 6 decimals for USDC: 1000000000 = 1000 USDC).
const { data: result } = await deframe.get('/strategies/aave-usdc-polygon/bytecode', {
  params: {
    action: 'lend',
    amount: '1000000000',
    wallet: walletAddress
  }
})

console.log('Transactions to execute:', result.bytecode.length)

5. Execute Transactions

The standard approach sends each transaction in a loop. With EIP-7702 you encode the entire result.bytecode array into one executeBatch call and send it as a single type-4 transaction. All steps succeed or all revert — no partial failures.
import { http, encodeFunctionData, createWalletClient, publicActions } from 'viem'
import { mainnet } from 'viem/chains'
import { privateKeyToAccount } from 'viem/accounts'

const SIMPLE_7702_ACCOUNT_ADDRESS = '0x4Cd241E8d1510e30b2076397afc7508Ae59C66c9'

const EIP7702AccountAbi = [
  { name: 'executeBatch', type: 'function', stateMutability: 'nonpayable',
    inputs: [{ name: 'calls', type: 'tuple[]', components: [
      { name: 'target', type: 'address' },
      { name: 'value',  type: 'uint256' },
      { name: 'data',   type: 'bytes'   }
    ]}], outputs: [] }
]

const account = privateKeyToAccount(process.env.PRIVATE_KEY)
const walletClient = createWalletClient({
  account,
  chain: mainnet,
  transport: http(process.env.VITE_RPC_URL)
}).extend(publicActions)
const walletAddress = account.address

// Map Deframe bytecode → executeBatch tuple format: [target, value, data]
const calls = result.bytecode.map(tx => [
  tx.to,
  BigInt(tx.value ?? '0'),
  tx.data
])

// Encode all calls into a single executeBatch calldata
const calldata = encodeFunctionData({
  abi: EIP7702AccountAbi,
  functionName: 'executeBatch',
  args: [calls]
})

// Sign EIP-7702 authorization — temporarily delegates your EOA to Simple7702Account
const authorization = await walletClient.signAuthorization({
  contractAddress: SIMPLE_7702_ACCOUNT_ADDRESS,
  executor: 'self'
})

// Send one type-4 transaction containing all the calls
const hash = await walletClient.sendTransaction({
  to: walletAddress,
  data: calldata,
  authorizationList: [authorization]
})

console.log('Transaction sent:', hash)

const receipt = await walletClient.waitForTransactionReceipt({ hash })
console.log('Confirmed in block:', receipt.blockNumber)

6. Verify Deposit

// Wait for indexing
await new Promise(resolve => setTimeout(resolve, 5000))

const { data: walletData } = await deframe.get(`/wallets/${walletAddress}`)

console.log('Wallet positions:')
walletData.positions.forEach(position => {
  console.log(`${position.strategy.id}:`)
  console.log(`  Balance: ${position.spotPosition.currentPosition.humanized} ${position.spotPosition.currentPosition.symbol}`)
  console.log(`  Value: $${position.spotPosition.underlyingBalanceUSD}`)
  console.log(`  APY: ${(position.spotPosition.apy * 100).toFixed(2)}%`)
})

console.log('Total portfolio value: $' + walletData.summary.totalUnderlyingBalanceUSD)

Error Handling

The example includes comprehensive error handling for both Deframe API errors and EIP-7702 wallet errors:
try {
  // Your code here
} catch (error) {
  if (error.response?.data?.error) {
    const apiError = error.response.data.error
    console.error('API Error:', apiError.code)
    console.error('Message:', apiError.message)

    if (apiError.code === 'STRATEGY_NOT_FOUND') {
      console.log('Strategy does not exist or is not available')
    } else if (apiError.code === 'INSUFFICIENT_BALANCE') {
      console.log('Wallet does not have enough tokens')
    }
  } else if (error?.code === 4001 || error?.message?.toLowerCase().includes('user rejected')) {
    console.error('User rejected the signature or transaction.')
  } else if (error?.code === 4200 || error?.message?.toLowerCase().includes('not supported')) {
    console.error('Wallet does not support EIP-7702 authorization signing.')
  } else {
    console.error('Unexpected error:', error.message)
  }
}

Running the Example

# Install dependencies
npm install

# Set environment variables
cp .env.example .env
# Edit .env with your values

# Run the example
node strategy-deposit-eip7702.js

Expected Output

1️⃣  Fetching available strategies...
✅ Available strategies:
   - aave-usdc-polygon (Aave)
     APY: 4.50%

2️⃣  Getting details for aave-usdc-polygon...
✅ Strategy details:
   Strategy: aave-usdc-polygon
   Protocol: Aave
   Network: polygon
   Asset: USDC
   APY: 4.50%
   Status: ✅ Active

3️⃣  Generating deposit bytecode...
✅ Bytecode generated:
   Transactions to batch: 2

4️⃣  Signing EIP-7702 authorization...
   Encoding executeBatch calldata...
   Sending type-4 transaction...
   Transaction sent: 0x123...
   ✅ Transaction confirmed in block 12345678

5️⃣  Verifying deposit...
✅ Wallet positions:
   aave-usdc-polygon:
      Balance: 1000.00 USDC
      Value: $1000.00
      APY: 4.17%

   Total Portfolio Value: $1000.00

🎉 Strategy deposit completed successfully!

Next Steps

Strategy Withdrawal

Learn how to withdraw from strategies

Cross-Chain Swap

Execute cross-chain token swaps

Check Positions

Track wallet positions

API Reference

View complete API documentation