> ## Documentation Index
> Fetch the complete documentation index at: https://www.dynamic.xyz/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Exporting WaaS Private Key

You can securely export the private key for a WaaS wallet account. On web you specify an HTML element to host an iframe containing the private key; on React Native you mount the `<ExportPrivateKey />` component, which hosts the key inside a screenshot-protected native WebView. In every case the key is rendered inside a sandboxed document and never crosses into your application's JavaScript.

### Usage

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={"system"}
    import { exportWaasPrivateKey, isWaasWalletAccount } from '@dynamic-labs-sdk/client/waas';
    import { client } from './client';

    const exportPrivateKey = async () => {
      const walletAccounts = client.wallets.getWalletAccounts();
      const walletAccount = walletAccounts[0];

      if (!isWaasWalletAccount({ walletAccount })) return;

      await exportWaasPrivateKey({
        walletAccount,
        displayContainer: document.getElementById('display-container'),
      });
    };

    // Add a container in your UI to inject the iframe
    // E.g: <div id="display-container"></div>
    ```
  </Tab>

  <Tab title="React">
    Use a `ref` to pass the DOM element to `exportWaasPrivateKey`:

    ```tsx theme={"system"}
    import { exportWaasPrivateKey, isWaasWalletAccount } from '@dynamic-labs-sdk/client/waas';
    import { getWalletAccounts } from '@dynamic-labs-sdk/client';
    import { useRef } from 'react';

    function ExportPrivateKey() {
      const containerRef = useRef<HTMLDivElement>(null);

      const handleExport = async () => {
        const walletAccounts = getWalletAccounts();
        const walletAccount = walletAccounts[0];

        if (!walletAccount || !isWaasWalletAccount({ walletAccount }) || !containerRef.current) return;

        await exportWaasPrivateKey({
          walletAccount,
          displayContainer: containerRef.current,
        });
      };

      return (
        <div>
          <button onClick={handleExport}>Export private key</button>
          <div ref={containerRef} />
        </div>
      );
    }
    ```
  </Tab>

  <Tab title="React Native">
    On React Native the key is displayed by the `<ExportPrivateKey />` component from a dedicated package. It renders the key inside a [`react-native-webview`](https://github.com/react-native-webview/react-native-webview) with screenshot/recording protection enabled, and the key never crosses the JS bridge — your app code cannot read, log, or screenshot it.

    <Note>
      Configure the client for React Native first. See [React Native Setup](/docs/javascript/react-native/setup).
    </Note>

    Install the package and its `react-native-webview` peer dependency:

    <Tabs>
      <Tab title="Expo">
        ```shell theme={"system"}
        npx expo install @dynamic-labs-sdk/react-native-embedded-wallet-export react-native-webview
        ```
      </Tab>

      <Tab title="Bare React Native">
        ```shell theme={"system"}
        npm install @dynamic-labs-sdk/react-native-embedded-wallet-export react-native-webview
        cd ios && bundle exec pod install && cd ..
        ```
      </Tab>
    </Tabs>

    Mount `<ExportPrivateKey />` to show the key and unmount it to dismiss — the component owns the display's lifecycle. Place it inside your own modal or card with a close button.

    ```tsx theme={"system"}
    import { ExportPrivateKey } from '@dynamic-labs-sdk/react-native-embedded-wallet-export';
    import { getWalletAccounts } from '@dynamic-labs-sdk/client';
    import { isWaasWalletAccount } from '@dynamic-labs-sdk/client/waas';
    import { useState } from 'react';
    import { Button, Modal, View } from 'react-native';

    function ExportPrivateKeyScreen() {
      const [revealing, setRevealing] = useState(false);
      const walletAccount = getWalletAccounts()[0];

      if (!walletAccount || !isWaasWalletAccount({ walletAccount })) return null;

      return (
        <View>
          <Button title="Reveal private key" onPress={() => setRevealing(true)} />
          <Modal visible={revealing} onRequestClose={() => setRevealing(false)}>
            {revealing && (
              <ExportPrivateKey
                walletAccount={walletAccount}
                onError={(error) => {
                  // Log a non-sensitive representation only — the raw error
                  // may carry key material.
                  const errorType =
                    error instanceof Error ? error.name : typeof error;
                  console.warn('Private key export failed', { errorType });
                  setRevealing(false);
                }}
              />
            )}
            <Button title="Done" onPress={() => setRevealing(false)} />
          </Modal>
        </View>
      );
    }
    ```

    <Note>
      Exporting a private key is a sensitive action guarded by the `wallet:export` scope, so the SDK requires an elevated session for the export ceremony. If your environment enforces MFA, the user is prompted to step up before the key is shown. See [Step-up authentication](/docs/javascript/authentication-methods/step-up-auth/overview).
    </Note>

    **Props**

    | Prop            | Type                       | Description                                                      |
    | --------------- | -------------------------- | ---------------------------------------------------------------- |
    | `walletAccount` | `WalletAccount`            | The WaaS wallet account to export. Required.                     |
    | `password`      | `string`                   | Optional password to decrypt the private key.                    |
    | `onComplete`    | `() => void`               | Fires once the key is displayed. Receives no key material.       |
    | `onError`       | `(error: unknown) => void` | Fires on failure. The error never contains key material.         |
    | `style`         | `StyleProp<ViewStyle>`     | Styles the box that hosts the key display; the WebView fills it. |

    To show a spinner while the key resolves, render your own indicator behind the component (the display is transparent while it loads) and hide it on `onComplete`. Keep the spinner `pointerEvents="none"` so it doesn't intercept taps meant for the key display.
  </Tab>
</Tabs>

## Error Handling

* If the specified wallet account is not a WaaS WalletAccount, it will throw an `NotWaasWalletAccountError` error.

## Related functions

* [Checking WaaS Wallet Account Type](/docs/javascript/reference/waas/checking-waas-wallet-account-type)
* [Checking if WaaS is enabled](/docs/javascript/reference/waas/checking-if-waas-is-enabled)
* [Importing WaaS Private Key](/docs/javascript/reference/waas/importing-waas-private-key)
* [Adding EVM Extensions](/docs/javascript/reference/evm/adding-evm-extensions)
* [Adding Solana Extensions](/docs/javascript/reference/solana/adding-solana-extensions)
