Skip to main content
MoonKey enables your users to export the private key for their embedded wallet. This allows them to use their embedded wallet address with another wallet client, such as MetaMask or Phantom, or to back up their wallet for recovery purposes.
Exporting private keys is a sensitive operation. Once exported, the private key gives complete control over the wallet and all its assets. Users should be educated about proper key storage and security practices.

Overview

When users export their wallet, they receive:
  • Full private key for their embedded wallet
  • Complete control over their wallet, even outside your application
  • Ability to import into other wallet clients (MetaMask, Phantom, etc.)
  • Self-custody of their assets
When your user exports their embedded wallet, their private key is assembled in a secure environment separate from your app. This means neither you nor MoonKey can ever access your user’s full private key. Your user is the only party that can ever access it.

React SDK

MoonKey provides a simple hook-based API for wallet export in React applications.
  • Ethereum
  • Solana
To enable wallet export for Ethereum wallets, use the useExportKey hook from @moon-key/react-auth/ethereum:

Basic Usage

import { useMoonKey } from '@moon-key/react-auth';
import { useExportKey } from '@moon-key/react-auth/ethereum';

function ExportWalletButton() {
  const { user, isAuthenticated, ready } = useMoonKey();
  const { exportKey } = useExportKey();

  const handleExport = async () => {
    if (!user?.wallet) {
      alert('No wallet found');
      return;
    }

    try {
      await exportKey({
        wallet: user.wallet
      });
      console.log('Export initiated');
    } catch (error) {
      console.error('Export failed:', error);
    }
  };

  // Check if user has a wallet
  const hasWallet = user?.wallet !== undefined;

  return (
    <button 
      onClick={handleExport} 
      disabled={!ready || !isAuthenticated || !hasWallet}
    >
      Export Wallet
    </button>
  );
}

With Custom UI Configuration

You can customize the export modal’s appearance by passing a uiConfig object:
import { useMoonKey } from '@moon-key/react-auth';
import { useExportKey } from '@moon-key/react-auth/ethereum';

function ExportWalletButton() {
  const { user } = useMoonKey();
  const { exportKey } = useExportKey();

  const handleExport = async () => {
    if (!user?.wallet) return;

    try {
      await exportKey({
        wallet: user.wallet,
        uiConfig: {
          title: 'Backup Your Wallet',
          privateKeyDescription: 'Your private key provides complete control over this wallet. Store it securely.',
          neverShareDescription: 'Never share your private key with anyone, including MoonKey support.',
          loadingExportOptionsText: 'Preparing secure export...'
        }
      });
    } catch (error) {
      console.error('Export cancelled or failed:', error);
    }
  };

  return (
    <button onClick={handleExport}>
      Export Private Key
    </button>
  );
}

Complete Example

Here’s a complete example with proper validation and error handling:
'use client';
import { useMoonKey } from '@moon-key/react-auth';
import { useExportKey } from '@moon-key/react-auth/ethereum';
import { useState } from 'react';

export default function WalletExportSection() {
  const { user, isAuthenticated, ready } = useMoonKey();
  const { exportKey } = useExportKey();
  const [isExporting, setIsExporting] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const handleExport = async () => {
    // Clear previous errors
    setError(null);

    // Validate user has a wallet
    if (!user?.wallet) {
      setError('No wallet found. Please create a wallet first.');
      return;
    }

    // Confirm user intent
    const confirmed = window.confirm(
      'WARNING: Your private key gives complete control of your wallet. ' +
      'Make sure you store it in a secure location. Continue?'
    );

    if (!confirmed) return;

    setIsExporting(true);

    try {
      await exportKey({
        wallet: user.wallet,
        uiConfig: {
          title: 'Export Private Key',
          privateKeyDescription: 'This key provides full access to your wallet and funds. Keep it safe and offline.',
          neverShareDescription: 'Never share this key. MoonKey will never ask for it.',
          loadingExportOptionsText: 'Loading secure export options...'
        }
      });

      alert('Private key export initiated. Follow the instructions on screen.');
    } catch (err: any) {
      console.error('Export error:', err);
      setError(err.message || 'Failed to export wallet. Please try again.');
    } finally {
      setIsExporting(false);
    }
  };

  // Loading state
  if (!ready) {
    return <div>Loading...</div>;
  }

  // Not authenticated
  if (!isAuthenticated || !user) {
    return (
      <div className="export-section">
        <p>Please sign in to export your wallet</p>
      </div>
    );
  }

  // No wallet
  if (!user.wallet) {
    return (
      <div className="export-section">
        <p>No wallet found. Create a wallet to enable export.</p>
      </div>
    );
  }

  return (
    <div className="export-section">
      <h3>Export Wallet</h3>
      <p className="warning-text">
        ⚠️ Exporting your private key gives you complete control of your wallet, 
        but also complete responsibility for its security.
      </p>

      <button
        onClick={handleExport}
        disabled={isExporting}
        className="export-button"
      >
        {isExporting ? 'Exporting...' : 'Export Private Key'}
      </button>

      {error && (
        <div className="error-message">
          {error}
        </div>
      )}

      <div className="info-box">
        <h4>What you'll receive:</h4>
        <ul>
          <li>Your wallet's private key</li>
          <li>Instructions for importing into MetaMask</li>
          <li>Security best practices</li>
        </ul>
      </div>
    </div>
  );
}

UI Configuration Options

The exportKey method accepts an optional uiConfig object to customize the export modal:
title
string
Custom title displayed at the top of the export modal.Example:
uiConfig: {
  title: 'Backup Your Wallet'
}
privateKeyDescription
string
Description explaining what the private key is and its importance.Example:
uiConfig: {
  privateKeyDescription: 'Your private key gives full control of your wallet. Store it securely offline.'
}
neverShareDescription
string
Warning message emphasizing that the key should never be shared.Example:
uiConfig: {
  neverShareDescription: 'Never share your private key with anyone, including MoonKey support.'
}
loadingExportOptionsText
string
Loading text displayed while the export modal is initializing.Example:
uiConfig: {
  loadingExportOptionsText: 'Preparing secure export...'
}
hdDescription
string
Description for HD (Hierarchical Deterministic) wallet exports.Example:
uiConfig: {
  hdDescription: 'Your seed phrase can restore all wallets derived from this account.'
}
logoUrl
string
URL to your application’s logo to display in the export modal.Example:
uiConfig: {
  logoUrl: 'https://myapp.com/logo.png'
}

Common Use Cases

Wallet Backup

Allow users to back up their wallet for recovery:
import { useMoonKey } from '@moon-key/react-auth';
import { useExportKey } from '@moon-key/react-auth/ethereum';

function BackupWalletButton() {
  const { user } = useMoonKey();
  const { exportKey } = useExportKey();

  const handleBackup = async () => {
    if (!user?.wallet) return;

    await exportKey({
      wallet: user.wallet,
      uiConfig: {
        title: 'Backup Your Wallet',
        privateKeyDescription: 'Save your private key in a secure location for wallet recovery.',
        neverShareDescription: 'Store this key offline. Never share it with anyone.'
      }
    });
  };

  return (
    <button onClick={handleBackup} className="backup-btn">
      Backup Wallet
    </button>
  );
}

Best Practices

Use confirmation dialogs before exporting to ensure users understand the implications:
const confirmed = window.confirm(
  'WARNING: Your private key gives complete control of your wallet. ' +
  'Make sure you store it securely. Continue?'
);

if (!confirmed) return;
Provide clear warnings and best practices:
<div className="security-notice">
  <h4>Security Best Practices:</h4>
  <ul>
    <li>Store your private key in a password manager or offline</li>
    <li>Never share your key with anyone</li>
    <li>Be cautious of phishing attempts</li>
    <li>Consider using a hardware wallet for large amounts</li>
  </ul>
</div>
Always check that a wallet exists before attempting export:
if (!user?.wallet) {
  setError('No wallet found. Create a wallet first.');
  return;
}
Provide clear error messages and recovery options:
try {
  await exportKey({ wallet: user.wallet });
} catch (error: any) {
  if (error.code === 'USER_CANCELLED') {
    console.log('User cancelled export');
  } else {
    setError('Export failed. Please try again or contact support.');
  }
}
Your application should never log, store, or transmit exported private keys:
// ❌ NEVER DO THIS
const key = await exportKey({ wallet: user.wallet });
console.log('Private key:', key); // NEVER LOG KEYS
localStorage.setItem('key', key); // NEVER STORE KEYS
await fetch('/api/save-key', { body: key }); // NEVER SEND KEYS

// ✅ CORRECT - Just trigger the export UI
await exportKey({ wallet: user.wallet });
// MoonKey handles key display securely
Use uiConfig to match your application’s branding:
uiConfig: {
  title: 'Backup Your Wallet',
  logoUrl: 'https://myapp.com/logo.png',
  privateKeyDescription: 'Custom message for your users...'
}

Security Considerations

Private key export is a high-risk operation. Ensure your users understand:
  • Anyone with the private key has complete control of the wallet
  • Lost private keys cannot be recovered
  • Stolen private keys can result in permanent loss of funds
  • Private keys should never be shared with anyone

What happens during export

  1. User initiates export through your application
  2. MoonKey opens secure modal in an isolated environment
  3. Private key is assembled client-side in a separate origin
  4. User copies key directly from the secure modal
  5. No logging or storage occurs in your application or MoonKey’s servers

Security features

  • Isolated origin: Keys are displayed in a separate security context
  • No server access: Neither your app nor MoonKey can access the full key
  • User-only access: Only the user can view their exported key
  • No automatic storage: Keys are never automatically saved anywhere
  • Ephemeral display: Keys are only shown during the export flow

Troubleshooting

Check these conditions:
  • SDK is ready (ready === true)
  • User is authenticated (isAuthenticated === true)
  • User has a wallet (user?.wallet !== undefined)
console.log('SDK ready:', ready);
console.log('Is authenticated:', isAuthenticated);
console.log('Has wallet:', !!user?.wallet);
Common causes and solutions:
  • User cancelled: User closed the modal - this is expected behavior
  • No wallet found: Ensure wallet creation is complete before export
  • Network error: Check internet connection and try again
  • SDK not ready: Wait for ready state before calling export
Ensure:
  • Copying the complete private key (including 0x prefix for Ethereum)
  • Using correct import method in MetaMask (Import Account → Private Key)
  • Private key format matches wallet type (hex for Ethereum, base58 for Solana)

Importing Exported Wallets

After exporting, users can import their wallet into various wallet clients:

MetaMask (Ethereum)

  1. Open MetaMask
  2. Click account icon → “Import Account”
  3. Select “Private Key” option
  4. Paste the exported private key (with 0x prefix)
  5. Click “Import”

Phantom (Solana)

  1. Open Phantom
  2. Settings → Add / Connect Wallet
  3. Select “Import Private Key”
  4. Paste the exported private key
  5. Click “Import”

Other Wallet Clients

Most wallet clients support private key import through similar flows. Consult the specific wallet’s documentation for detailed instructions.

Next Steps

After implementing wallet export:
  1. Test the flow with test wallets on testnet
  2. Educate your users about private key security
  3. Provide support documentation for common issues
  4. Consider adding recovery mechanisms for users who lose keys
  5. Monitor usage to understand how users interact with export
For more details on customizing the export UI, see the Export Key UI Component documentation.