No matter how your user signs up, whether it’s through social login such as Telegram, email or phone, or a branded wallet like MetaMask, you can create an embedded wallet for them using Dynamic. Simply choose when you want the wallet to be created and follow the guides below.

Please make sure you are on v4.20.6 before continuing.

During Signup (Automatic)

Creating Embedded Wallets

By default, embedded wallets are created automatically for users during sign-up if they don’t already have a wallet on the enabled chain. All you have to do is check that the “Create on Sign up” toggle is turned on in the Embedded Wallet configuration page.

Automatic embedded wallet creation only creates a single wallet for a user on each chain you have selected. If you want to create multiple wallets per chain, simply call the createWalletAccount method from the useDynamicWaas hook as shown below, and one wallet per enabled chain will be generated per call.

Creating Wallets for users with External Wallets

You can automatically create embedded wallets for users who sign in with external wallets like MetaMask. To enable this feature, open the “Create on Sign Up” card, expand the “Advanced Options” panel, and turn on the “Embedded Wallet for Third-Party Wallets” toggle.

Custom Logic (Manual)

Creating Wallets Any Time

If you do not want to create wallets for users automatically when they sign up, you can create wallets for users using custom logic. To do so, call the createWalletAccount method from the useDynamicWaas hook when you want to create a wallet for a user.

You can control which chains you create wallets on by passing an array of chains to the createWalletAccount method. See the useDynamicWaas documentation for more details.

import { useDynamicWaas, useUserWallets } from "@dynamic-labs/sdk-react-core";
import { ChainEnum } from "@dynamic-labs/sdk-api-core";
// component declaration and all other logic you might need

const { createWalletAccount, getWaasWallets } = useDynamicWaas();

const onCreateWalletHandler = async () => {
  try {
    const waasWallets = await getWaasWallets();
    if (waasWallets.length === 0) {
        await createWalletAccount([ChainEnum.Evm, ChainEnum.Sol]);
    }
  } catch (e) {
    console.error(e);
  }
};

Handling Errors while creating wallets manually

There can be infrequent errors while creating wallets and backing up shares due to network connectivity, etc. To handle these, catch errors from the createWalletAccount function to know which wallets to attempt to retry creating.

import React, { useState } from 'react';
import { ChainEnum } from '@dynamic-labs/sdk-api-core';
import { useDynamicWaas } from '../../../utils/hooks/useDynamicWaas';

export const CreateWallets = () => {
  const { createWalletAccount } = useDynamicWaas();
  const [status, setStatus] = useState<{
    loading: boolean;
    error?: string;
    retrying?: ChainEnum[];
  }>({ loading: false });

  const handleCreateWallet = async (chains: ChainEnum[]) => {
    try {
      const walletAccounts = await createWalletAccount(chains);
    } catch (err) {
      if (err.message.includes('Failed to create wallet')) {
        const failedChains = err.message.split(': ')[1]?.split(', ') || [];

        if (failedChains.length > 0) {
          setStatus({
            error: `Failed to create wallets for: ${failedChains.join(', ')}`,
            loading: false,
          });

          // Retry after 2 seconds
          setTimeout(
            () => handleCreateWallet(failedChains as ChainEnum[]),
            2000,
          );
        }
      } else {
        setStatus({ error: 'Failed to create wallets', loading: false });
      }
    }
  };

  const initialChains = [ChainEnum.Evm, ChainEnum.Sui, ChainEnum.Sol];

  return (
    <div>
      <button
        onClick={() => handleCreateWallet(initialChains)}
        disabled={status.loading}
      >
        {status.loading ? 'Creating...' : 'Create Wallets'}
      </button>

      {status.error && (
        <div style={{ color: 'red', marginTop: 10 }}>{status.error}</div>
      )}

      {status.retrying && (
        <div style={{ color: 'orange', marginTop: 10 }}>
          Retrying for chains: {status.retrying.join(', ')}
        </div>
      )}
    </div>
  );
};