> ## Documentation Index
> Fetch the complete documentation index at: https://developers.circle.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Before reading these docs, install the relevant Circle Skill to get pre-loaded context — skills are LLM-optimized and cover architecture decisions, correct flows, and common pitfalls. In Claude Code: run /plugin marketplace add circlefin/skills then /plugin install circle-skills@circle. With Vercel Skills CLI: run npx skills add circlefin/skills. Available skills: use-usdc https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-usdc/SKILL.md (balances, transfers, approvals on EVM and Solana); EURC has no skill — see https://developers.circle.com/stablecoins/what-is-eurc.md; bridge-stablecoin https://github.com/circlefin/skills/blob/master/plugins/circle/skills/bridge-stablecoin/SKILL.md (crosschain transfers via CCTP, USDC, EURC, and third-party assets); use-arc https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-arc/SKILL.md (Arc chain config, contract deployment, USDC bridging — Arc docs: https://docs.arc.io/llms.txt); use-circle-wallets https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-circle-wallets/SKILL.md (choose wallet type); use-developer-controlled-wallets https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-developer-controlled-wallets/SKILL.md (custodial wallets for payouts and treasury); use-user-controlled-wallets https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-user-controlled-wallets/SKILL.md (embedded wallets with Web2 login); use-modular-wallets https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-modular-wallets/SKILL.md (smart contract wallets with passkeys and ERC-4337); use-gateway https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-gateway/SKILL.md (unified USDC balance, nanopayments); use-smart-contract-platform https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-smart-contract-platform/SKILL.md (deploy, interact, monitor contracts). Pair any skill with the Circle MCP server for live SDK signatures, contract addresses, and chain IDs: {"mcpServers":{"circle":{"url":"https://api.circle.com/v1/codegen/mcp"}}}.
> Read the product overview first. Each product has an overview explaining when and why to use it. Read it before quickstarts.
> Pick the right wallet type. Developer-controlled (you hold keys), user-controlled (end user holds keys via PIN/social login), or modular (smart contract wallets with passkeys). See https://developers.circle.com/wallets.md.
> Use CCTP V2 for crosschain transfers. CCTP natively transfers USDC and EURC via burn-and-mint, and supports permissionless wrapping of third-party assets via lock-and-mint. V1 is legacy; always use V2 unless V1 is specified or the chain requires it (Noble, Sui, and Aptos still require V1). Migration guide: https://developers.circle.com/cctp/migration-from-v1-to-v2.md.
> Use Bridge Kit for frontend bridging. Wraps CCTP with a simpler SDK for user-facing apps. Use CCTP directly for backend transfers.
> Gas Station vs Paymaster. Gas Station sponsors gas for Circle Wallet transactions. Paymaster lets users pay gas in USDC. Different use cases — read both overviews.
> Gateway Nanopayments for sub-cent payments. Gasless USDC micropayments down to $0.000001 via x402 and batched settlement. For pay-per-request APIs, AI agent payments, streaming.
> Look up USDC addresses per chain. Never hardcode — use https://developers.circle.com/stablecoins/usdc-contract-addresses.md.
> Prefer SDKs over raw API calls. Node.js and Python SDKs handle auth, retries, and errors.
> API key required. Bearer token in Authorization header. Testnet and mainnet use separate keys and may use different base URLs depending on the product.
> Set up webhooks when available. Most operations are async. Webhooks deliver transaction confirmations and state changes.
> When calling list endpoints, paginate using pageSize and pageAfter until no nextPageAfter cursor is returned—stopping at the first page silently misses records.
> Building an AI agent? Start with the Agent Stack—Circle CLI, agent wallets, and nanopayments built for autonomous use cases: https://developers.circle.com/agent-stack.md.

# How-to: Use Dynamic as a signer

> Use a Dynamic-managed EOA as the signer for a modular wallet, instead of a passkey.

If your app uses [Dynamic](https://www.dynamic.xyz/) for user authentication
(email, social login, wallet connection) instead of passkeys, use the
Dynamic-managed EOA as the signer for a modular wallet. The result is a modular
wallet whose smart account is signed by the user's Dynamic EOA. After setup,
every [transfer](/wallets/modular/transfer-tokens),
[signature](/wallets/modular/sign-and-verify-messages), and
[batched operation](/wallets/modular/batch-and-parallel-user-operations) is
signed by Dynamic automatically.

To use a passkey signer instead, see
[Create a modular wallet](/wallets/modular/create-a-modular-wallet).

## Before you begin

Before you begin, ensure that you've:

* Created a [Circle Console](https://console.circle.com/) account and a
  [client key](/api-reference/keys#client-keys) for the modular wallets SDK:
  **Console → Keys → Create a key → Client Key**.
* Created a [Dynamic Dashboard](https://app.dynamic.xyz/) account and obtained
  your **Environment ID**.
* Enabled email login and embedded wallets (WaaS) in your Dynamic environment,
  and added [Arc Testnet](/wallets/supported-blockchains) as a supported
  network. The examples below target Arc Testnet.
* Installed [Node.js 22+](https://nodejs.org/) and the modular wallets
  [Web SDK](https://www.npmjs.com/package/@circle-fin/modular-wallets-core).

## Steps

<Steps>
  <Step title="Configure environment variables">
    Make your Circle client key, modular wallets backend URL, and Dynamic
    environment ID available to your app. The backend URL is the same for every app:
    `https://modular-sdk.circle.com/v1/rpc/w3s/buidl`.

    ```text Web SDK (TypeScript) theme={null}
    # .env
    VITE_CLIENT_KEY=YOUR_CLIENT_KEY
    VITE_CLIENT_URL=https://modular-sdk.circle.com/v1/rpc/w3s/buidl
    VITE_DYNAMIC_ENV_ID=YOUR_DYNAMIC_ENVIRONMENT_ID
    ```
  </Step>

  <Step title="Install the Dynamic headless SDK packages">
    Dynamic's headless SDK (`@dynamic-labs-sdk/client`) works with any web
    framework. Install it alongside the Circle modular wallets SDK and `viem`.

    ```shell theme={null}
    npm install @circle-fin/modular-wallets-core @dynamic-labs-sdk/client @dynamic-labs-sdk/evm viem
    ```
  </Step>

  <Step title="Initialize the Dynamic client">
    Create a Dynamic client, register the EVM extension, and wait for initialization
    before reading wallet accounts. If Dynamic's network data for Arc Testnet omits
    RPC URLs, supply them in a `networkData` transformer.

    ```typescript Web SDK (TypeScript) theme={null}
    import {
      createDynamicClient,
      initializeClient,
      waitForClientInitialized,
    } from "@dynamic-labs-sdk/client";
    import { addEvmExtension } from "@dynamic-labs-sdk/evm";
    import { arcTestnet } from "viem/chains";

    const dynamicClient = createDynamicClient({
      autoInitialize: false,
      environmentId: dynamicEnvId,
      metadata: {
        name: "My App",
        universalLink: window.location.origin,
      },
      transformers: {
        networkData: (network) => {
          if (network.networkId !== String(arcTestnet.id)) return network;

          const rpcUrls = network.rpcUrls.http.filter((url): url is string =>
            Boolean(url),
          );
          if (rpcUrls.length > 0) return network;

          return {
            ...network,
            rpcUrls: { http: [...arcTestnet.rpcUrls.default.http] },
          };
        },
      },
    });

    addEvmExtension();
    await initializeClient();
    await waitForClientInitialized(dynamicClient);
    ```
  </Step>

  <Step title="Authenticate the user">
    Sign the user in with any Dynamic-supported auth flow. The snippet below uses
    email OTP; social login and external wallet connection work the same way once
    Dynamic reports an authenticated session.

    After authentication, create an embedded EVM wallet on your target chain if the
    user does not have one yet.

    ```typescript Web SDK (TypeScript) theme={null}
    import {
      getWalletAccounts,
      sendEmailOTP,
      verifyOTP,
    } from "@dynamic-labs-sdk/client";
    import {
      createWaasWalletAccounts,
      getChainsMissingWaasWalletAccounts,
    } from "@dynamic-labs-sdk/client/waas";
    import { isEvmWalletAccount } from "@dynamic-labs-sdk/evm";

    const otpVerification = await sendEmailOTP({ email });
    await verifyOTP({ otpVerification, verificationToken });

    const walletAccounts = await getWalletAccounts();
    if (!walletAccounts.some(isEvmWalletAccount)) {
      const missingChains = getChainsMissingWaasWalletAccounts();
      if (missingChains.length > 0) {
        await createWaasWalletAccounts({ chains: missingChains });
      }
    }
    ```
  </Step>

  <Step title="Create a transport">
    The modular transport routes user operations through Circle's bundler and
    paymaster for the blockchain you target. The example below uses Arc Testnet.

    ```typescript Web SDK (TypeScript) theme={null}
    import { toModularTransport } from "@circle-fin/modular-wallets-core";

    const modularTransport = toModularTransport(
      `${clientUrl}/arcTestnet`,
      clientKey,
    );
    ```
  </Step>

  <Step title="Create the bundler client and smart account">
    Switch the Dynamic wallet to your target network, convert it to a viem local
    account, and pass it as the `owner` to `toCircleSmartAccount`. The bundler
    client submits user operations through the MSCA; every operation is signed by
    the Dynamic-managed EOA automatically.

    ```typescript Web SDK (TypeScript) theme={null}
    import {
      addNetwork,
      getWalletAccounts,
      NetworkNotAddedError,
      switchActiveNetwork,
    } from "@dynamic-labs-sdk/client";
    import { isEvmWalletAccount } from "@dynamic-labs-sdk/evm";
    import { createWalletClientForWalletAccount } from "@dynamic-labs-sdk/evm/viem";
    import {
      toCircleSmartAccount,
      walletClientToLocalAccount,
    } from "@circle-fin/modular-wallets-core";
    import { createPublicClient } from "viem";
    import { createBundlerClient } from "viem/account-abstraction";
    import { arcTestnet } from "viem/chains";

    const evmAccount = (await getWalletAccounts()).find(isEvmWalletAccount);
    if (!evmAccount) {
      throw new Error(
        "No EVM wallet account found. Enable email login and embedded wallets in Dynamic.",
      );
    }

    try {
      await switchActiveNetwork({
        walletAccount: evmAccount,
        networkId: String(arcTestnet.id),
      });
    } catch (error) {
      if (error instanceof NetworkNotAddedError) {
        await addNetwork({
          walletAccount: evmAccount,
          networkData: error.networkData,
        });
        await switchActiveNetwork({
          walletAccount: evmAccount,
          networkId: String(arcTestnet.id),
        });
      } else {
        throw error;
      }
    }

    const walletClient = await createWalletClientForWalletAccount({
      walletAccount: evmAccount,
    });

    const client = createPublicClient({
      chain: arcTestnet,
      transport: modularTransport,
    });

    const smartAccount = await toCircleSmartAccount({
      client,
      owner: walletClientToLocalAccount(walletClient),
    });

    const bundlerClient = createBundlerClient({
      account: smartAccount,
      chain: arcTestnet,
      transport: modularTransport,
    });
    ```
  </Step>
</Steps>

The user now has a modular wallet, signed by their Dynamic-managed EOA.

## Next steps

* [Transfer tokens](/wallets/modular/transfer-tokens) from the wallet.
* [Sign and verify messages](/wallets/modular/sign-and-verify-messages) for
  Sign-In With Ethereum (SIWE) or EIP-712 typed data.
* [Batch and parallel user operations](/wallets/modular/batch-and-parallel-user-operations)
  for multi-call patterns.
