Privy Integration

Build Yield Strategies with Deframe & Privy

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.

Resources

Resource
Description

Official documentation for Deframe strategies

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):

yarn create vite
  • 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:

cd deframe-privy-integration
yarn dev

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 Quickstartarrow-up-right 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 Dashboardarrow-up-right

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

Both Deframe values can be obtained from the Deframe Dashboardarrow-up-right.

Add TypeScript support for environment variables

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

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).

Enable Smart Wallets in the Privy Dashboard

  1. Open your app and find the Wallet infrastructure / Smart Wallets settings

  2. Enable Smart Wallets for your target chains (i.e. Ethereum, Polygon, Gnosis, Arbitrum, Base and HyperEVM, this last as Custom Chain)


Authentication (required)

Before creating wallets or calling Deframe endpoints that depend on a wallet address, users must be logged in and authenticated.

At a minimum, your app should provide:

  • Start login: trigger an authentication flow (for example, email OTP, OAuth, etc.)

  • Complete login: confirm the user session is established after the user finishes the login step

  • Check authentication: expose a boolean (or equivalent) to decide whether to show the authenticated app or the login screen

  • Logout (recommended): allow the user to end the session

Helpful Privy hooks

usePrivy() (from @privy-io/react-auth)

Property
Description

ready

SDK is ready to be used

authenticated

Whether the user is authenticated

user

User object (profile + linked accounts)

logout()

End the session

useLoginWithEmail() (from @privy-io/react-auth) (if using email OTP)

Property
Description

sendCode({ email })

Send an OTP to the email

loginWithCode({ code })

Complete login with the OTP

state.status

Current state (e.g. initial, sending-code, awaiting-code-input, submitting-code, done, error)

state.error

Error details (when state.status === 'error')

For the next steps in this recipe, assume the user is authenticated.


EOA & Smart Wallet usage

Create the EOA (embedded wallet)

useWallets() (from @privy-io/react-auth)

Property
Description

ready

Wallets list is ready

wallets

Array of wallets linked/created for the user (EOA is typically here)

useCreateWallet() (from @privy-io/react-auth)

Property
Description

createWallet()

Creates an embedded wallet for the user (when they don't have one yet)

Create the Smart Wallet

useSmartWallets() (from @privy-io/react-auth/smart-wallets)

Property
Description

client

Smart wallet client instance (when available)

client.account.address

The Smart Wallet address (Account Abstraction)

Warning

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.

Last updated