Trade everything. One app, every market.

Users scatter across apps because no single one offers every market. Give them an invisible embedded MPC wallet at login - no seed phrase, no extension - and put token markets, real-world events, and onchain swaps behind one familiar interface and one unified portfolio. Become the place where your users trade everything - 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. The EVM extension registers the 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

    The login card on the left runs this flow: send a one-time passcode, verify it. No password, no seed phrase - the session lives in the client.

    components/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) });
  5. Create the embedded wallet

    Docs

    One call mints a non-custodial embedded (WaaS) wallet for the signed-in user - no extension, no seed phrase; keys never leave Dynamic's MPC. The hook lists every account and re-renders as they're created.

    lib/dynamic/wallets.ts
    import { createWaasWalletAccounts } from "@dynamic-labs-sdk/client/waas";
    import { useGetWalletAccounts } from "@dynamic-labs-sdk/react-hooks";
    
    await createWaasWalletAccounts({ chains: ["EVM"] });
    
    const { data: walletAccounts } = useGetWalletAccounts();
    const walletAccount = walletAccounts?.[0];
  6. Execute a swap

    Docs

    Wrap the wallet account in a viem-compatible client and send the router calldata your aggregator quoted - the user approves in place; keys never leave Dynamic's MPC.

    lib/trade/execute-swap.ts
    import { createWalletClientForWalletAccount } from "@dynamic-labs-sdk/evm/viem";
    
    const walletClient = await createWalletClientForWalletAccount({ walletAccount });
    
    // quote.transactionRequest comes from your swap aggregator's API.
    const hash = await walletClient.sendTransaction({
      to: quote.transactionRequest.to,
      data: quote.transactionRequest.data,
      value: BigInt(quote.transactionRequest.value ?? 0),
    });
  7. Track balances and the portfolio

    Docs

    Read token balances with one hook - the portfolio view renders straight from the query and stays fresh as trades settle.

    components/portfolio.tsx
    import { useGetTokenBalances } from "@dynamic-labs-sdk/react-hooks";
    
    const { data: balances } = useGetTokenBalances({ walletAccount });
Trade - Dynamic Demos