Documentation Index Fetch the complete documentation index at: https://docs.privy.io/llms.txt
Use this file to discover all available pages before exploring further.
Deframe allows apps to access diversified DeFi yield strategies across multiple protocols through a single API. Apps fetch strategies from Deframe and execute the returned transaction bytecodes using Privy wallets. This enables deposits into lending, staking, and protocol-native yield strategies without managing complex transaction flows.
Resources
Deframe Docs Official documentation for Deframe strategies and API.
Starter repo Full working example of Deframe + Privy integration.
Using Deframe with Privy
For this walkthrough, the examples use the Aave USDT strategy on Polygon. The same patterns work across all Deframe-supported strategies and networks—explore the complete list via the Deframe API .
Setup
Below is a minimal setup for the Privy provider. To customize the provider, follow the Privy Quickstart .
import { PrivyProvider } from '@privy-io/react-auth' ;
export function App () {
return (
< PrivyProvider appId = "your-privy-app-id" > { /* Your application components */ } </ PrivyProvider >
);
}
Obtain your API credentials from the Deframe Dashboard:
const DEFRAME_API_URL = 'https://api.deframe.io' ;
const DEFRAME_API_KEY = 'your-deframe-api-key' ;
List available strategies
Fetch the yield strategies available for users:
const fetchStrategies = async () => {
const response = await fetch ( ` ${ DEFRAME_API_URL } /strategies?limit=100` , {
method: 'GET' ,
headers: {
'x-api-key' : DEFRAME_API_KEY
}
});
const { data : strategies } = await response . json ();
return strategies ;
};
Each strategy includes fields like id, protocol, assetName, network, and availableActions.
Deposit into a yield strategy
1. Get the user's wallet address
import { useWallets } from '@privy-io/react-auth' ;
const { wallets } = useWallets ();
const walletAddress = wallets [ 0 ]?. address ;
2. Generate transaction bytecodes from Deframe
Request the bytecodes needed to execute a deposit action: const strategyId = 'Aave-USDT-polygon' ;
const action = 'lend' ;
const amount = '1500000' ; // 1.5 USDT (6 decimals)
const response = await fetch (
` ${ DEFRAME_API_URL } /strategies/ ${ strategyId } /bytecode?action= ${ action } &wallet= ${ walletAddress } &amount= ${ amount } ` ,
{
method: 'GET' ,
headers: {
'x-api-key' : DEFRAME_API_KEY
}
}
);
const bytecodeResponse = await response . json ();
The response contains an array of transactions to execute: type DeframeBytecodeResponse = {
feeCharged : string ;
metadata : {
isCrossChain : boolean ;
isSameChainSwap : boolean ;
crossChainQuoteId : string ;
};
bytecode : {
to : string ;
value : string ;
data : string ;
chainId : string ;
}[];
};
3. Execute the transactions with Privy
Use Privy’s useSendTransaction to execute each bytecode: import { useSendTransaction } from '@privy-io/react-auth' ;
const { sendTransaction } = useSendTransaction ();
const executeDeframeStrategy = async ( bytecodeResponse : DeframeBytecodeResponse ) => {
for ( const tx of bytecodeResponse . bytecode ) {
await sendTransaction ({
to: tx . to as `0x ${ string } ` ,
data: tx . data as `0x ${ string } ` ,
value: BigInt ( tx . value ),
chainId: Number ( tx . chainId )
});
}
};
Check strategy position
Fetch the user’s current position and APY for a strategy:
const fetchPosition = async ( strategyId : string , walletAddress : string ) => {
const response = await fetch (
` ${ DEFRAME_API_URL } /strategies/ ${ strategyId } ?wallet= ${ walletAddress } ` ,
{
method: 'GET' ,
headers: {
'x-api-key' : DEFRAME_API_KEY
}
}
);
const strategy = await response . json ();
return {
apy: strategy . apy ,
avgApy: strategy . avgApy ,
position: strategy . position
};
};
Withdraw from a strategy
To withdraw, use the withdraw action and execute the returned bytecodes:
import { useSendTransaction } from '@privy-io/react-auth' ;
const { sendTransaction } = useSendTransaction ();
const withdrawFromStrategy = async ( strategyId : string , walletAddress : string , amount : string ) => {
const response = await fetch (
` ${ DEFRAME_API_URL } /strategies/ ${ strategyId } /bytecode?action=withdraw&wallet= ${ walletAddress } &amount= ${ amount } ` ,
{
method: 'GET' ,
headers: {
'x-api-key' : DEFRAME_API_KEY
}
}
);
const bytecodeResponse = await response . json ();
for ( const tx of bytecodeResponse . bytecode ) {
await sendTransaction ({
to: tx . to as `0x ${ string } ` ,
data: tx . data as `0x ${ string } ` ,
value: BigInt ( tx . value ),
chainId: Number ( tx . chainId )
});
}
};
For a faster integration, Deframe provides a pre-built EarnWidget component that handles strategy selection, deposits, and withdrawals with a built-in UI.
Install the Deframe SDK
npm install deframe-sdk @deframe-sdk/components @reduxjs/toolkit react-redux redux permissionless
If your app uses Vite, install the Node polyfills plugin and add it to vite.config.ts: npm install --save-dev vite-plugin-node-polyfills
import { defineConfig } from 'vite' ;
import { nodePolyfills } from 'vite-plugin-node-polyfills' ;
export default defineConfig ({
plugins: [ nodePolyfills ()]
}) ;
import { DeframeProvider , EarnWidget } from 'deframe-sdk' ;
import { useSmartWallets } from '@privy-io/react-auth/smart-wallets' ;
import { usePrivy } from '@privy-io/react-auth' ;
const { user } = usePrivy ();
const { client : smartWalletClient , getClientForChain } = useSmartWallets ();
const config = {
DEFRAME_API_URL: 'https://api.deframe.io' ,
DEFRAME_API_KEY: 'your-deframe-api-key' ,
walletAddress: smartWalletClient ?. account . address ,
userId: user ?. id ,
globalCurrency: 'USD' ,
globalCurrencyExchangeRate: 1 ,
theme: { mode: 'dark' , preset: 'default' }
};
Implement the bytecode processor
The widget returns bytecode for the app to execute using Privy smart wallets:
import type { BytecodeTransaction , UpdateTxStatus } from 'deframe-sdk' ;
const processBytecode = async (
payload : { clientTxId : string ; bytecodes : BytecodeTransaction []; simulateError ?: boolean },
ctx : { updateTxStatus : UpdateTxStatus }
) => {
ctx . updateTxStatus ({ type: 'HOST_ACK' , clientTxId: payload . clientTxId });
const chainId = Number ( payload . bytecodes [ 0 ]. chainId );
const chainClient = await getClientForChain ({ id: chainId });
const calls = payload . bytecodes . map (( b ) => ({
to: b . to as `0x ${ string } ` ,
data: b . data as `0x ${ string } ` ,
value: BigInt ( b . value )
}));
ctx . updateTxStatus ({ type: 'SIGNATURE_PROMPTED' , clientTxId: payload . clientTxId });
const txHash = await chainClient . sendTransaction ({ calls });
ctx . updateTxStatus ({ type: 'TX_SUBMITTED' , clientTxId: payload . clientTxId , txHash });
};
< DeframeProvider config = { config } processBytecode = { processBytecode } >
< EarnWidget autoHeight />
</ DeframeProvider >
Key integration tips
Handle token decimals : The amount parameter must respect the token’s decimal places. USDT and USDC use 6 decimals; most other tokens use 18.
Execute transactions in order : Deframe may return multiple bytecodes for a single action. Execute them sequentially.
Verify available actions : Each strategy has an availableActions array. Check that the action exists before requesting bytecodes.
Handle errors gracefully : Wrap transaction execution in try/catch blocks to handle user rejection, insufficient funds, and network issues.
For advanced use cases, refer to the Deframe Docs , or reach out in Slack .