Enable users to access DeFi yield strategies with a Web2-grade experience by combining Privy's embedded wallets with Deframe's strategy execution layer. This recipe shows how to route user funds into diversified yield strategies—spanning lending, staking, and protocol-native yields—while Deframe handles bytecode generation, protocol routing, and execution. Privy simplifies onboarding and wallet management, allowing users to earn yield across DeFi without interacting directly with contracts or managing complex transaction flows.
Privy Wallets are a powerful tool for helping users interact with DeFi
Install and configure the Vite project
Commands/selections used (as shown in the create-vite wizard):
yarncreatevite
Project name: deframe-privy-integration
Select a framework: React
Select a variant: TypeScript + SWC
Use rolldown-vite (Experimental)?: No
Install with yarn and start now?: Yes
Then, to run locally:
cddeframe-privy-integrationyarndev
Vite requirement (Privy SDK)
If (and only if) your app is built with Vite, you must add Node polyfills so the Privy SDK works correctly in the browser.
1) Install the polyfills plugin
Run the following command (this is required for Vite projects):
2) Enable it in vite.config.ts
Add the import and the plugin call:
Privy's SDK setup
Below is a minimal setup for Privy and Alchemy provider setup. To customize your Privy provider, follow the instructions in the Privy Quickstart to get your app set up with Privy.
Configure secrets
This application relies on environment variables to connect to Privy and Deframe. These values are injected at build time by Vite and must be prefixed with VITE_ to be exposed to the client.
Create the .env file
Create a .env file at the root of your project and define the following variables:
Variable
Description
VITE_APP_PRIVY_APP_ID
Your Privy application identifier. You can find this value in the Privy Dashboard
VITE_APP_DEFRAME_API_URL
The base API URL provided by Deframe for executing protocol interactions and strategy flows
VITE_APP_DEFRAME_API_KEY
Your Deframe API key, used to authenticate requests to the Deframe API
To ensure full TypeScript support when accessing environment variables via import.meta.env, create the following file:
This file:
Enables type safety when accessing environment variables
Prevents TypeScript errors when using import.meta.env
Ensures better DX when working with Privy and Deframe configs
Install and configure Privy's SDK
Privy's SDK installation
Enable Smart Wallets + gas sponsorship (recommended)
To make the UX feel "Web2 smooth" (no wallet popups, no manual gas management), enable Privy Smart Wallets and sponsor gas via a paymaster (use Alchemy or Pimlico).
Smart wallets are typically counterfactual: you may have an address even if the contract is not deployed yet on a given chain. Before you call Deframe endpoints that depend on a smart wallet on a specific network, make sure the smart wallet is deployed on that target chain.
How to verify deployment: query the chain for contract bytecode (if the result is 0x, it is not deployed).
How to deploy: send a minimal "no-op" transaction (e.g. to: smartWalletAddress, value: 0, data: 0x) using the smart wallet client for that chain. This triggers the deployment flow.
Paymaster note: if you're using a paymaster for gas sponsorship, it must have sufficient credit/balance; deployment still consumes gas.
Example: verify whether the Smart Wallet is deployed (Viem getCode)
Example: trigger deployment with a minimal transaction (Privy getClientForChain)
Note: We'll use the Smart Wallet address to request bytecodes from Deframe's API
Fetching strategies from Deframe's API
All requests below use:
Base URL: VITE_APP_DEFRAME_API_URL
Auth header: x-api-key: VITE_APP_DEFRAME_API_KEY
1) List strategies
Fetch the available strategies that the user can interact with.
Parameter
Value
Method
GET
Path
/strategies
Query params (optional)
limit: number of items per page, page: page number
Example request:
Expected response shape (simplified):
data: list of strategies
pagination: paging metadata (when available)
Each strategy item commonly includes fields like:
id
protocol
assetName
network
availableActions
logourl
underlyingDecimals / assetDecimals
2) Strategy details for a wallet
Fetch specific information for a given strategy, such as apy (protocol UI apy), avgApy (last 30 days) and inceptionApy (since contract was deployed). If wallet was passed as query param, the wallet's spot position is returned.
Parameter
Value
Method
GET
Path
/strategies/:strategy-id
Query params
wallet: the user's wallet address
Example request:
3) Generate bytecodes for an action
Request the transaction bytecodes needed to execute a strategy action for a wallet.
Parameter
Value
Method
GET
Path
/strategies/:strategy-id/bytecode
Query params
action (required): one of the strategy availableActions (example: lend), wallet (required): the user's wallet address, amount (required): the amount (considering decimals) the user wants to execute for the action
Example request:
Response type (shape):
Notes:
Ensure amount respects the token decimals.
The response is intended to be executed by the user's wallet.
Executing the bytecodes
After you receive the response from /strategies/:strategy-id/bytecode, you must execute each item in bytecode[] as a smart-wallet transaction (usually on the same chain specified by chainId).
Key points:
The smart wallet must be deployed on the target chain (see the Smart Wallet deployment warning above).
Use the Smart Wallet client for the target chain (example: getClientForChain({ id: chainId })).
Convert types:
to and data must be 0x-prefixed hex strings (e.g. `0x${string}`).
value should be a bigint (convert using BigInt(value)).
Example (execute bytecode[] as calls):
Notes:
The SDK may return a transaction hash or an object depending on the configured client—log it and optionally wait for confirmations.
If you are using a paymaster, ensure it has enough credit/balance; execution consumes gas.