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

# WalletMetadata

> Non-sensitive wallet identity + backup-pointer metadata passed to every sign / export / backup operation in the stateless Node SDK

`WalletMetadata` describes a wallet's non-sensitive identity and backup-pointer state. It is returned alongside `externalServerKeyShares` from wallet-creation methods and **must be passed as an explicit argument** to every subsequent sign, export, backup, refresh, reshare, and password operation.

The Node SDK is stateless — it does not hold wallet state between calls. Persist `walletMetadata` in a cache (Redis, Postgres, etc.) and `externalServerKeyShares` in a secrets vault (HSM, KMS-wrapped DB column, Secret Manager). See [Storage Best Practices](/node/wallets/server-wallets/storage-best-practices) for the recommended split.

## Interface Definition

```typescript theme={"system"}
interface WalletMetadata {
  walletId: string;
  accountAddress: string;
  chainName: string;
  thresholdSignatureScheme: ThresholdSignatureScheme;
  derivationPath?: string;
  addressType?: string; // BTC only
  externalServerKeySharesBackupInfo?: KeyShareBackupInfo;
}
```

## Properties

### Required Properties

* **`walletId`** (`string`) — Unique identifier for the wallet
* **`accountAddress`** (`string`) — The wallet's account address
* **`chainName`** (`string`) — SDK-internal chain name (`EVM`, `SVM`, `BTC`, `TON`)
* **`thresholdSignatureScheme`** ([`ThresholdSignatureScheme`](/node/reference/types/threshold-signature-scheme)) — The threshold signature scheme used for this wallet

### Optional Properties

* **`derivationPath`** (`string`) — Derivation path for the wallet (e.g. EVM uses a BIP-44 path; encoded as a JSON object)
* **`addressType`** (`string`) — Bitcoin address type (`taproot` or `native_segwit`). Required for BTC operations; absent for other chains.
* **`externalServerKeySharesBackupInfo`** ([`KeyShareBackupInfo`](/node/reference/types/key-share-backup-info)) — Per-share pointer metadata describing where each share is backed up. **Required for `signMessage`, `signTransaction`, `signTypedData`, `exportKey`, `exportPrivateKey`, password verification, share recovery, `refreshWalletAccountShares`, `reshare`, and `updatePassword` whenever you pass caller-held `externalServerKeyShares`.** Operations that need it throw a descriptive error when it's missing. Caching the full `walletMetadata` returned from `createWalletAccount()` / `importPrivateKey()` ensures you have it.

## How to obtain `WalletMetadata`

There are two paths to obtain a `walletMetadata` value, with different completeness guarantees:

| Source                                                      | Includes `backupInfo`? | Includes `addressType`? | Use when                                                                                 |
| ----------------------------------------------------------- | ---------------------- | ----------------------- | ---------------------------------------------------------------------------------------- |
| `createWalletAccount()` / `importPrivateKey()` return value | ✅ Yes                  | ✅ Yes                   | Wallet creation. **Persist the full object** in your cache.                              |
| `client.fetchWalletMetadata(accountAddress)`                | ❌ No                   | ❌ No                    | Recovery path: you have the address but lost the cached metadata. Returns identity only. |

The recommended flow is to **persist the full `walletMetadata` from creation**. The backup-pointer metadata (`externalServerKeySharesBackupInfo`) is not recoverable via SDK-scoped endpoints — there is no server-side fallback if you lose it.

<Warning>
  `fetchWalletMetadata(accountAddress)` is **not** a recovery path for signing or exporting. It returns identity only (no `externalServerKeySharesBackupInfo`, no `addressType`). `signMessage`, `signTransaction`, `signTypedData`, `exportKey`, and `exportPrivateKey` all throw when called with caller-supplied `externalServerKeyShares` and a `walletMetadata` that lacks `externalServerKeySharesBackupInfo`. If you lose the cached object, you cannot sign — only re-identify.
</Warning>

## Example

```typescript theme={"system"}
import { DynamicEvmWalletClient } from '@dynamic-labs-wallet/node-evm';
import { ThresholdSignatureScheme } from '@dynamic-labs-wallet/node';

const client = new DynamicEvmWalletClient({ environmentId, baseApiUrl });
await client.authenticateApiToken(apiKey);

// 1. Create the wallet — returns walletMetadata + externalServerKeyShares.
const { walletMetadata, externalServerKeyShares } = await client.createWalletAccount({
  thresholdSignatureScheme: ThresholdSignatureScheme.TWO_OF_TWO,
  backUpToDynamic: true,
  password: 'user-password',
});

// 2. Persist both — to your cache and your vault respectively.
await redis.set(
  `wallet:${walletMetadata.accountAddress}`,
  JSON.stringify(walletMetadata)
);
await vault.write(
  `wallet:${walletMetadata.accountAddress}/shares`,
  externalServerKeyShares
);

// 3. Later, in any process / pod, pass walletMetadata back in.
const cached = JSON.parse(await redis.get(`wallet:${accountAddress}`));
const shares = await vault.read(`wallet:${accountAddress}/shares`);

const signature = await client.signMessage({
  walletMetadata: cached,
  externalServerKeyShares: shares,
  message: 'Hello',
  password: 'user-password',
});
```

## Updating cached `walletMetadata` after mutating operations

`updatePassword`, `refreshWalletAccountShares`, and `reshare` all return a new `backupInfo` reflecting the **new** backup state. You **must** merge it into your cached `walletMetadata` — otherwise the next operation reads stale metadata and either silently misbehaves or surfaces a "stale walletMetadata" error.

```typescript theme={"system"}
const { backupInfo } = await client.updatePassword({
  walletMetadata,
  externalServerKeyShares,
  existingPassword: 'old-password',
  newPassword: 'new-password',
  backUpToDynamic: true,
});

const updated = {
  ...walletMetadata,
  externalServerKeySharesBackupInfo: backupInfo,
};
await redis.set(
  `wallet:${updated.accountAddress}`,
  JSON.stringify(updated)
);
```

## Related

* [`ServerKeyShare`](/node/reference/types/server-key-share) — The sensitive key-share type stored in your vault
* [`KeyShareBackupInfo`](/node/reference/types/key-share-backup-info) — The shape of `externalServerKeySharesBackupInfo`
* [`ThresholdSignatureScheme`](/node/reference/types/threshold-signature-scheme) — Threshold signature scheme enum
* [Storage Best Practices](/node/wallets/server-wallets/storage-best-practices) — Where to cache metadata vs. where to vault shares
