Skip to content

Creating an embedded wallet

If your app uses embedded wallets, you can configure Privy to create wallets automatically for your users as part of their login flow, or you can manually create wallets for your users when required.

Automatic wallet creation

When automatic wallet creation is enabled, Privy will create wallets for users when they login to your app––specifically, as part of Privy's login method.

To configure Privy to automatically create embedded wallets for your user when they login, set the config.embedded.ethereum.createOnLogin or config.embedded.solana.createOnLogin property of your PrivyProvider:

tsx
<PrivyProvider
  appId="your-privy-app-id"
  config={{
    embedded: { 
      ethereum: { 
        createOnLogin: 'users-without-wallets', // defaults to 'off'
      }, 
    }, 
  }}
>
  {children}
</PrivyProvider>

The possible values for createOnLogin are 'off', 'users-without-wallets', and 'all-users':

  • When 'off', Privy will not automatically create embedded wallets for your users, but you can always manually create wallets for them later. This is the default setting.
  • When set to 'users-without-wallets', Privy will automatically create an embedded wallet for users that do not already have another external wallet linked to their account.
  • When set to 'all-users', Privy will automatically create an embedded wallet for all users, including those that do have another external wallet linked to their account.

Manual wallet creation

To manually create an embedded wallet for your user, use the Privy Expo SDK's useEmbeddedWallet hook.

As a parameter to create, you should include an object including options for the wallet's recovery method. This recovery method will be used anytime the user interacts with their wallet on a new device. This object must at minimum contain a field called recoveryMethod, whose possible values are:

  • privy, the recovery material will be secured by Privy. This is also called automatic recovery.
  • user-passcode, the recovery share of the embedded wallet will be secured by a password provided by the user. With this recovery method, the recovery options object must also contain a field password containing the user's password as a string.
  • google-drive, the recovery secret will be backed up to the user's Google Drive account.
  • icloud, the recovery secret will be backed up to the user's iCloud account. Note: this is only supported on iOS devices.

INFO

iCloud recovery is only supported on iOS devices.

tsx
import {useEmbeddedWallet, isNotCreated} from '@privy-io/expo';

const CreateWalletButton = () => {
  const wallet = useEmbeddedWallet();

  if (isNotCreated(wallet)) {
    return <Button onPress={() => wallet.create({recoveryMethod: 'privy'})}>Create Wallet</Button>;
  }

  return null;
};
How can my app know if a user already has an embedded wallet?

To determine if the current user already has an embedded wallet, you can either:

  • obtain an object representation of the user from the Privy SDK's usePrivy hook, and check if it includes a wallet with a walletClientType of 'privy', or
  • use the Privy client's useEmbeddedWallet hook, like below:
tsx
import {useEmbeddedWallet, isConnected, needsRecovery} from '@privy-io/expo';

const Component = () => {
  const wallet = useEmbeddedWallet();
  const [password, setPassword] = useState('');

  if (isConnected(wallet)) {
    /* The user's embedded wallet exists and is ready to be used! */
    return <View>Wallet Exists</View>;
  }

  if (needsRecovery(wallet)) {
    /*
      The user's embedded wallet exists but has never been loaded on this device.
      They will need to go through the password recovery flow to use it.
    */
    return (
      <View>
        The user's embedded wallet exists but has never been loaded on this device. They will need
        to go through the password recovery flow to use it.
      </View>
    );
  }

  return null;
};
Why is wallet.create undefined or throwing a type error?
  • wallet.create will be undefined if the wallet has already been created
  • If your application uses Typescript, isNotCreated refines the type of wallet. So wallet.create will cause a type error outside a check that either isNotCreated is true or wallet.status === 'not-created'