Put idle balances to work. Earn in the same asset.
Give users yield without leaving your app. They deposit USDC into a curated vault straight from their embedded wallet, watch the balance grow in the same asset, and withdraw any time - no DeFi background required, built entirely on Dynamic.
Create the client
DocsOne Dynamic client per app, created at module scope. Earn is EVM-only, so the EVM extension is the only one this demo registers.
lib/dynamic/client.tsimport { createDynamicClient } from "@dynamic-labs-sdk/client"; import { addEvmExtension } from "@dynamic-labs-sdk/evm"; export const client = createDynamicClient({ environmentId: process.env.NEXT_PUBLIC_DYNAMIC_ENVIRONMENT_ID!, }); addEvmExtension(client);Wrap your app for hooks
DocsThe react-hooks package reads the client from context and uses TanStack Query underneath, so mount
QueryClientProvideroutsideDynamicProvideronce.app/providers.tsximport { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { DynamicProvider } from "@dynamic-labs-sdk/react-hooks"; import { client } from "@/lib/dynamic/client"; const queryClient = new QueryClient(); export function Providers({ children }: { children: React.ReactNode }) { return ( <QueryClientProvider client={queryClient}> <DynamicProvider client={client}>{children}</DynamicProvider> </QueryClientProvider> ); }Sign in with an email code
DocsSend a one-time passcode and verify it. The embedded wallet that signs every deposit belongs to the user this creates.
components/screens/auth-screen.tsximport { useSendEmailOTP, useVerifyOTP } from "@dynamic-labs-sdk/react-hooks"; const { mutate: sendOtp, data: otpVerification } = useSendEmailOTP(); const { mutate: verifyOtp } = useVerifyOTP(); sendOtp({ email }); // User types the 6-digit code from their inbox: verifyOtp({ otp: code, otpVerification });List the vaults
DocsEvery vault the environment can see, each with a best-effort live
netApyandtvlUsd. This is the first call after sign-in - and the only place avaultIdshould ever come from.hooks/use-vaults.tsimport { listYieldVaults } from "@dynamic-labs-sdk/client"; const vaults = await listYieldVaults(); for (const vault of vaults) { console.log(vault.vaultId, vault.curator, vault.assetSymbol, vault.netApy); }