> ## 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.

# Import a Private Key

> Bring an externally-managed private key into the Dynamic MPC system from Java

## Overview

`importPrivateKey` brings an externally-managed private key into the Dynamic MPC system. The imported wallet is stored as a standard MPC wallet with the canonical share layout (client + Dynamic + optional backup) — there is no insecure "key copy", and the raw private key is never persisted in plaintext after the import ceremony.

Use this for:

* Migrating wallets from another custody system
* Bringing a wallet you previously exported back into MPC
* Onboarding existing on-chain accounts to Dynamic

The Java SDK exposes three flavors:

* `DynamicEvmWalletClient::importPrivateKey` — EVM, takes raw 32 bytes
* `DynamicSvmWalletClient::importPrivateKey` — SVM, takes the 32-byte Ed25519 seed (the seed half of a 64-byte keypair)
* `DynamicWalletClient::importRawPrivateKey` — chain-agnostic, takes a `ChainName` enum and lets you tune the threshold scheme

## Prerequisites

* [Set up your Dynamic project](/java/quickstart)
* An authenticated client (`DynamicEvmWalletClient`, `DynamicSvmWalletClient`, or the base `DynamicWalletClient`)
* The raw private key bytes (handle them as `byte[]` and zero the array after import)

## EVM Import

```java theme={"system"}
import xyz.dynamic.waas.KeygenResult;
import xyz.dynamic.waas.evm.opts.ImportPrivateKeyOpts;

byte[] privateKey = /* 32 raw bytes — e.g. Numeric.hexStringToByteArray("0x...") */;

KeygenResult wallet = evmClient.importPrivateKey(ImportPrivateKeyOpts.builder()
    .privateKey(privateKey)
    .build()
).join();

String address = wallet.walletProperties().accountAddress();   // EIP-55 hex
System.out.println("Imported EVM wallet: " + address);

// Zero the source bytes immediately.
java.util.Arrays.fill(privateKey, (byte) 0);
```

## SVM Import

```java theme={"system"}
import xyz.dynamic.waas.KeygenResult;
import xyz.dynamic.waas.svm.opts.ImportPrivateKeyOpts;

byte[] solanaSeed = /* 32 raw bytes — the seed half of a 64-byte Solana keypair */;

KeygenResult wallet = svmClient.importPrivateKey(ImportPrivateKeyOpts.builder()
    .privateKey(solanaSeed)
    .build()
).join();

String address = wallet.walletProperties().accountAddress();   // base58
System.out.println("Imported Solana wallet: " + address);

java.util.Arrays.fill(solanaSeed, (byte) 0);
```

<Note>
  Solana's native `Keypair` is 64 bytes (`seed || pubkey`). Pass only the first 32 bytes — `importPrivateKey` derives the public key itself and would reject a 64-byte input.
</Note>

## Chain-Agnostic Import

When you want a single code path that handles both EVM and Solana, use `DynamicWalletClient::importRawPrivateKey`:

```java theme={"system"}
import xyz.dynamic.waas.DynamicWalletClient;
import xyz.dynamic.waas.KeygenResult;
import xyz.dynamic.waas.core.types.ChainName;
import xyz.dynamic.waas.core.types.ThresholdSignatureScheme;
import xyz.dynamic.waas.opts.ImportRawPrivateKeyOpts;

KeygenResult wallet = baseClient.importRawPrivateKey(
    ChainName.EVM,                                       // or ChainName.SVM
    ImportRawPrivateKeyOpts.builder()
        .privateKey(privateKey)
        .thresholdSignatureScheme(ThresholdSignatureScheme.TWO_OF_TWO)
        .build()
).join();
```

## Backup After Import

`importPrivateKey` does **not** back up to Dynamic automatically. After a successful import:

1. Persist the returned `wallet.externalServerKeyShares()` to your secrets vault.
2. If you also want Dynamic-backed storage, call `backupKeyShares(...)` on the base client with the password you want to use.

```java theme={"system"}
// 1) Vault the local shares.
vault.write(
    "wallet:" + wallet.walletProperties().accountAddress() + "/shares",
    ServerKeyShare.toJsonList(wallet.externalServerKeyShares())
);

// 2) Optional: also back up to Dynamic.
baseClient.backupKeyShares(BackupKeySharesOpts.builder()
    .walletProperties(wallet.walletProperties())
    .externalServerKeyShares(wallet.externalServerKeyShares())
    .password("user-password")
    .build()
).join();
```

## Best Practices

* **Treat the source private key as compromised after import.** Anyone who held the key before import still has signing power — rotate any on-chain authority that depends on it.
* **Zero the source bytes immediately** after the import ceremony returns (`Arrays.fill(privateKey, (byte) 0)`).
* **Never log the raw key** — redact it from all logs, error messages, and exception payloads.
* **Run the import inside try-with-resources** so the wallet client and its native handles are released even if vault writes fail.

## Next Steps

* [Storage Best Practices](/java/storage-best-practices) — persist what the import returned
* [Sign EVM messages](/java/evm/sign-messages) / [Sign SVM messages](/java/svm/sign-messages)
* [Password & state queries](/java/password-and-state) — manage the backup password lifecycle
