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

# Upgrade Node SDK to V1

V1 is the first stable major release of the Node SDK. It is a breaking change relative to the pre-1.0 versions and requires code changes on every sign / export / backup / refresh / reshare / password call site.

### Affected packages

V1 spans the entire `@dynamic-labs-wallet` Node family. Upgrade all of them together — they share types and a base client and will not interoperate across major versions.

| Package                         | V1 version range |
| ------------------------------- | ---------------- |
| `@dynamic-labs-wallet/node`     | `^1.0.0`         |
| `@dynamic-labs-wallet/node-evm` | `^1.0.0`         |
| `@dynamic-labs-wallet/node-svm` | `^1.0.0`         |
| `@dynamic-labs-wallet/node-btc` | `^1.0.0`         |
| `@dynamic-labs-wallet/node-ton` | `^1.0.0`         |

If a `^0.x` package is still in your `package.json` after the upgrade, that's pre-V1.

### Breaking changes

#### The SDK is now stateless

The SDK no longer holds wallet state between calls. The internal `walletMap` is gone; every operation takes explicit `walletMetadata` (returned at creation) and, when you manage shares yourself, `externalServerKeyShares`.

```typescript theme={"system"}
// V0 — SDK held wallet state internally
await client.initializeWalletMapEntry({ accountAddress });
const signature = await client
  .getWallet(accountAddress)
  .signMessage({ message: 'hello' });

// V1 — caller passes metadata + shares explicitly
const walletMetadata = JSON.parse(await redis.get(`wallet:${accountAddress}`));
const externalServerKeyShares = await vault.read(`wallet:${accountAddress}/shares`);
const signature = await client.signMessage({
  message: 'hello',
  walletMetadata,
  externalServerKeyShares,
  password,
});
```

The implication is that **you own persistence now.** Cache `walletMetadata` (non-sensitive identity + backup-pointer info) and vault `externalServerKeyShares` (sensitive MPC material) on creation, then thread them through. See [Storage Best Practices](/node/wallets/server-wallets/storage-best-practices).

#### Removed APIs

The following symbols no longer exist:

* `walletMap` (and all access patterns that used it)
* `client.getWallet(address)`
* `initializeWalletMapEntry`
* `ensureCeremonyCompletionBeforeBackup`

Each one has been folded into the explicit-metadata flow.

#### `getWallets()` / `getSvmWallets()` are deprecated

`getWallets()` (and the SVM `getSvmWallets()`) are deprecated for wallet listing and lookup. They still function and log a runtime deprecation warning. For identity-only lookups, use `fetchWalletMetadata(accountAddress)` — it returns identity-only `WalletMetadata` in the shape every SDK operation takes as input, including the share-set fields (`shareSetId`, `shareSetType`, `otherShareSets`) that lifecycle operations like `refreshWalletAccountShares` and `reshare` need. It does not include `externalServerKeySharesBackupInfo` or `addressType`, so it is not a substitute for the full `walletMetadata` persisted at creation.

Do **not** treat lookup calls as a recovery path for signing or exporting. Neither `fetchWalletMetadata(accountAddress)` nor `getWalletByAddress(accountAddress)` returns `externalServerKeySharesBackupInfo` on current backends, so operations that need backup info (sign with auto-recovery, password verification, refresh, reshare, updatePassword) throw `MissingBackupInfoError` on their result — the same limitation described [below](#signmessage-%2F-signtransaction-%2F-signtypeddata-%2F-exportkey-%2F-exportprivatekey-require-backupinfo). Note that `getWallets()` never returns raw key shares either; its `externalServerKeyShares` field is always an empty array. The canonical pattern is to persist the full `walletMetadata` returned from `createWalletAccount` at creation time, not to re-fetch it.

#### `recoverEncryptedBackupByWallet` no longer accepts `storeRecoveredShares`

Recovery returns the shares; the caller decides what to do with them. There is no SDK-side "auto-restore" path anymore.

```typescript theme={"system"}
// V0
await client.recoverEncryptedBackupByWallet({
  accountAddress,
  storeRecoveredShares: true, // removed in V1
});

// V1
const { externalServerKeyShares } = await client.recoverEncryptedBackupByWallet({
  walletMetadata,
});
await vault.write(`wallet:${accountAddress}/shares`, externalServerKeyShares);
```

#### `backUpToClientShareService` → `backUpToDynamic`

The boolean flag that controls Dynamic-managed backup has been renamed. This affects `createWalletAccount`, `importPrivateKey`, `refreshWalletAccountShares`, `reshare`, `updatePassword`, and the backup endpoints.

```diff theme={"system"}
- backUpToClientShareService: true
+ backUpToDynamic: true
```

#### `password` is required when `backUpToDynamic` is `true`

Any operation that backs key shares up to Dynamic's key share service now requires a `password`. The SDK validates this upfront and throws before the MPC ceremony runs (previously, V0 silently produced an unprotected backup in some paths).

This applies to `createWalletAccount`, `importPrivateKey`, `refreshWalletAccountShares`, `reshare`, and `updatePassword`.

#### `accountAddress` / `senderAddress` → `walletMetadata`

Every sign / export / backup operation now identifies the wallet through `walletMetadata.accountAddress` rather than a standalone `accountAddress` or `senderAddress` parameter.

```diff theme={"system"}
- await client.signTransaction({
-   senderAddress: '0x...',
-   transaction,
- });
+ await client.signTransaction({
+   walletMetadata,
+   externalServerKeyShares,
+   transaction,
+ });
```

EVM `signTransaction` previously accepted both `senderAddress` and `accountAddress`; in V1 both are removed in favor of `walletMetadata`.

#### New return shapes

The methods below now return additional data the caller is expected to persist:

| Method                                    | New return shape                                                          |
| ----------------------------------------- | ------------------------------------------------------------------------- |
| `createWalletAccount`, `importPrivateKey` | `{ walletMetadata, externalServerKeyShares, rawPublicKey, publicKeyHex }` |
| `refreshWalletAccountShares`, `reshare`   | `{ externalServerKeyShares, backupInfo }`                                 |
| `updatePassword`                          | `{ backupInfo }`                                                          |

#### Cache-merge rule for `backupInfo`

`refreshWalletAccountShares`, `reshare`, and `updatePassword` all return a fresh `backupInfo` that reflects the **new** backup state. Merge it into your cached `walletMetadata.externalServerKeySharesBackupInfo` and re-cache — otherwise the next operation reads stale metadata and fails password verification.

```typescript theme={"system"}
const { backupInfo } = await client.updatePassword({ walletMetadata, /* … */ });
const updated = { ...walletMetadata, externalServerKeySharesBackupInfo: backupInfo };
await redis.set(`wallet:${updated.accountAddress}`, JSON.stringify(updated));
```

For `refreshWalletAccountShares` and `reshare`, also re-vault the newly returned `externalServerKeyShares` — the old shares no longer sign with the wallet.

### Behavior changes that surface as thrown errors post-upgrade

These are not API renames — they are pre-existing logical paths that now reject input the SDK previously accepted. They are easy to miss in a code-review pass because the call shape looks the same.

#### `signMessage` / `signTransaction` / `signTypedData` / `exportKey` / `exportPrivateKey` require `backupInfo`

When you pass caller-supplied `externalServerKeyShares`, the SDK now requires `walletMetadata.externalServerKeySharesBackupInfo` to be present. It throws `MissingBackupInfoError` if shares are supplied but backup metadata is missing. The full `walletMetadata` returned from creation already includes it; identity-only metadata from `fetchWalletMetadata` does not.

The practical consequence: **`fetchWalletMetadata` is not a lost-cache recovery path for signing or exporting.** Treat the full `walletMetadata` object as recovery-critical and persist it from creation.

#### `updatePassword` validates `newPassword` upfront

When `backUpToDynamic: true`, `updatePassword` now rejects missing / empty `newPassword` before running the MPC ceremony, instead of silently producing an unprotected backup. Pre-V1 callers that relied on the silent downgrade will see a thrown error post-upgrade.

#### BTC: `addressType` must live on cached `walletMetadata`

`storeEncryptedBackupByWallet` for BTC reads `addressType` (`taproot` or `native_segwit`) directly from `walletMetadata`. There is no server-side fallback, and `fetchWalletMetadata` does not return it. If your V0 cache stored fields à la carte and omitted `addressType`, BTC backups will fail post-upgrade.

### Recommended migration steps

1. Bump every `@dynamic-labs-wallet/*` package to `^1.0.0` in one PR — they cannot mix majors.
2. At each `createWalletAccount` / `importPrivateKey` call site: change the return-handling to persist the full `walletMetadata` object (including `externalServerKeySharesBackupInfo`) in your cache, and `externalServerKeyShares` in your vault.
3. At every sign / export / backup / refresh / reshare / password call site: thread `walletMetadata` + `externalServerKeyShares` through instead of bare `accountAddress` / `senderAddress`.
4. After every `refreshWalletAccountShares`, `reshare`, or `updatePassword` call: merge the returned `backupInfo` into cached `walletMetadata` and re-cache.
5. Replace `backUpToClientShareService` with `backUpToDynamic` throughout. Add a `password` arg anywhere `backUpToDynamic: true` is passed.
6. Drop `storeRecoveredShares` from `recoverEncryptedBackupByWallet` calls; persist the returned shares to your vault explicitly.
7. (BTC only) Audit your cached wallet records to ensure `addressType` is present on every BTC wallet's `walletMetadata`.

### Related

* [`WalletMetadata`](/node/reference/types/wallet-metadata) — the metadata object passed to every operation
* [Storage Best Practices](/node/wallets/server-wallets/storage-best-practices) — what to cache vs. vault, and recovery limits
* [Server Wallets Setup](/node/wallets/server-wallets/overview) — the V1 stateless model end-to-end
