Skip to content

Importing an embedded wallet

Privy enables your users to import a private key into their embedded wallet.

This allows users to bring an existing wallet into your application, enabling them to manage their assets directly within your app. For example, a user can import their MetaMask wallet private key to access and manage their assets within your app seamlessly. This method can also be used by developers to migrate users from a different embedded wallet provider to Privy.

INFO

Privy's React SDK currently only supports importing wallets on EVM networks.

Importing a wallet by private key

To have your user import a private key into their embedded wallet, use the importWallet method from the useImportWallet hook. As a parameter to this method, pass an object containing the user's privateKey as a string.

tsx
import {usePrivy, useImportWallet} from '@privy-io/react-auth';

function ImportWalletButton() {
  const {ready, authenticated} = usePrivy();
  const {importWallet} = useImportWallet();
  const [privateKey, setPrivateKey] = useState('');

  const handleImport = async () => {
    try {
      const wallet = await importWallet({privateKey: privateKey});
      console.log('Wallet imported successfully:', wallet);
    } catch (error) {
      console.error('Failed to import wallet:', error);
    }
  };

  // Check that your user is authenticated
  const isAuthenticated = ready && authenticated;

  return (
    <div>
      <input
        type="text"
        value={privateKey}
        onChange={(e) => setPrivateKey(e.target.value)}
        placeholder="Enter your private key"
      />
      <button onClick={handleImport} disabled={!isAuthenticated}>
        Import my wallet
      </button>
    </div>
  );
}

If importWallet succeeds, the imported wallet will be added to the user's linkedAccounts and the wallets array returned by the useWallets hook, with an imported field that is marked true. As an example, you can find the imported wallet like so:

tsx
import {useWallets} from '@privy-io/react-auth';

function ImportedWalletInfo() {
  const wallets = useWallets();
  const importedWallet = wallets.find((wallet) => wallet.imported);
  return (
    <div>
      <h3>Imported Wallet</h3>
      {importedWallet ? <p>Address: {importedWallet.address}</p> : <p>No imported wallet found</p>}
    </div>
  );
}

This method will error if the provided private key is not valid or if the user has previously imported a wallet by private key.

Using imported embedded wallets

You can request signatures and transactions from imported wallets using Privy's native methods, the wallet's EIP1193 provider, or a third-party library like viem or ethers.

Using Privy's native signature and transaction methods

To use Privy's native signMessage, signTypedData, and sendTransaction methods with an imported wallet, simply pass the address for the imported wallet as the final optional parameter to these methods:

tsx
const {signMessage} = usePrivy();
const signature = await signMessage(
  'insert-message-to-sign',
  insertOptionalUIConfigOrUndefined,
  'insert-imported-wallet-address', // Replace with the imported wallet address in EIP55 format
);

Using the EIP1193 provider, viem, and ethers

You can also request signatures and transactions from an imported wallet using the wallet's EIP1193 provider or a library like viem or ethers.

To get the EIP1193 provider for the imported wallet, first find the corresponding ConnectedWallet object from the useWallets array:

tsx
const {wallets} = useWallets();
// `ConnectedWallet.imported` is set to `true` for imported wallets
const importedWallet = wallets.find(
  (wallet) => wallet.walletClientType === 'privy' && wallet.imported,
);

Then, call the object's getEthereumProvider method to get an EIP1193 provider for that wallet:

tsx
const provider = await importedWallet.getEthereumProvider();

You can then easily pass that EIP1193 provider to a library like viem or ethers to use those libraries' interfaces to send requests to the wallet.

Exporting imported embedded wallets

Privy enables your users to export the full private key for their embedded wallet, even if it was imported. This allows them to use their embedded wallet address with another wallet client, such as MetaMask in any application.

To have your user export their embedded wallet's private key, use the exportWallet method from the usePrivy hook. As a parameter to this method, you must pass an object containing an address field with the user's imported wallet address as a string.

As an example, you might have an export wallet button in your app like so:

tsx
import {usePrivy, useWallets} from '@privy-io/react-auth';

function ExportWalletButton() {
  const {ready, authenticated, exportWallet} = usePrivy();
  const {wallets} = useWallets();
  // Check that your user is authenticated
  const isAuthenticated = ready && authenticated;
  // Find your user's imported wallet
  const importedWallet = wallets.find(
    (wallet) => wallet.walletClientType === 'privy' && wallet.imported,
  );

  const exportImportedWallet = async () => {
    if (!importedWallet) return;
    await exportWallet({address: importedWallet.address});
  };

  return (
    <button onClick={exportImportedWallet} disabled={!isAuthenticated || !importedWallet}>
      Export my wallet
    </button>
  );
}

INFO

Exporting the seed phrase for an imported embedded wallet is not supported, as it is impossible to recover the full seed phrase for the wallet from the imported private key.