Skip to main content

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.

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.
PackageV1 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.
// 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.

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.

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.
// V0
await client.recoverEncryptedBackupByWallet({
  accountAddress,
  storeRecoveredShares: true, // removed in V1
});

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

backUpToClientShareServicebackUpToDynamic

The boolean flag that controls Dynamic-managed backup has been renamed. This affects createWalletAccount, importPrivateKey, refreshWalletAccountShares, reshare, updatePassword, and the backup endpoints.
- 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 / senderAddresswalletMetadata

Every sign / export / backup operation now identifies the wallet through walletMetadata.accountAddress rather than a standalone accountAddress or senderAddress parameter.
- 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:
MethodNew 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.
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.
  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.