A wallet your users control. No seed phrase required.

Sign in with email, social, passkeys, or your own auth and every user gets a non-custodial MPC wallet in seconds - no seed phrase, no extension. Create wallets on any chain, read balances and history, sponsor your users' network fees, and verify sessions on your own backend - built entirely on Dynamic.

@dynamic-labs-sdk/client@dynamic-labs-sdk/react-hooks
  1. Create the client

    Docs

    One Dynamic client per app, created at module scope. Chain extensions register which networks the embedded wallet supports.

    lib/dynamic/client.ts
    import { 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);
  2. Wrap your app for hooks

    Docs

    The react-hooks package reads the client from context and uses TanStack Query under the hood, so mount QueryClientProvider outside DynamicProvider once - every hook below works anywhere inside.

    app/providers.tsx
    import { 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>
      );
    }
  3. Sign in with an email code

    Docs

    Send a one-time passcode and verify it. No password, no seed phrase - the session lives in the client.

    components/email-login.tsx
    import { 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 });
  4. Sign in with a social account

    Docs

    Kick off the provider's OAuth flow, then complete it when the user lands back - same session, same embedded wallet.

    components/social-login.tsx
    import {
      useCompleteSocialRedirect,
      useSignInWithSocialRedirect,
    } from "@dynamic-labs-sdk/react-hooks";
    
    const { mutate: signIn } = useSignInWithSocialRedirect();
    const { mutate: completeRedirect } = useCompleteSocialRedirect();
    
    signIn({ provider: "google", redirectUrl: window.location.origin });
    
    // ...and when the provider redirects back:
    completeRedirect({ url: new URL(window.location.href) });