Skip to main content

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.

Spin up millions of secure, server-controlled wallets with battle-tested MPC infrastructure. Built for onchain automation, Dynamic Server Wallets let you trigger transactions, interact with contracts, and run complex flows—all without user involvement, and fully owned by your backend.
Find pricing for server wallets here.

Setup

Reference example: GitHub example
1

Enable multiple embedded wallets per chain

Navigate to the Dynamic Dashboard and enable multiple embedded wallets per chain.
2

Retrieve your auth token

Navigate to the Dynamic Dashboard and create a new API token.
3

Install desired Node SDKs

npm i @dynamic-labs-wallet/node-evm
npm i @dynamic-labs-wallet/node-svm
4

Create client with authenticateApiToken

Separate clients are needed for each chain.
import { DynamicEvmWalletClient } from "@dynamic-labs-wallet/node-evm";

export const authenticatedEvmClient = async ({
  authToken,
  environmentId,
}: {
  authToken: string;
  environmentId: string;
}) => {
  const client = new DynamicEvmWalletClient({
    environmentId,
  });

  await client.authenticateApiToken(authToken);
  return client;
};
5

Access MPC functionality by creating a new wallet account

import { ThresholdSignatureScheme } from '@dynamic-labs-wallet/node';
import { authenticatedEvmClient } from '<path-to-dynamic-authenticated-client>';

const AUTH_TOKEN = "your-auth-token";
const ENVIRONMENT_ID = "your-environment-id";

const evmClient = await authenticatedEvmClient({
  authToken: AUTH_TOKEN,
  environmentId: ENVIRONMENT_ID,
});

const thresholdSignatureScheme = ThresholdSignatureScheme.TWO_OF_TWO; // or TWO_OF_THREE
const password = "your-password"; // Required when backUpToDynamic is true
const onError = (error: Error) => {
  // handle error
  console.error(error);
};

const {
  walletMetadata,
  rawPublicKey,
  publicKeyHex,
  externalServerKeyShares,
} = await evmClient.createWalletAccount({
  thresholdSignatureScheme,
  password,
  onError,
  backUpToDynamic: true, // Optional: backs up key shares to Dynamic's service (important-comment)
});
The Node SDK is stateless. createWalletAccount() returns two pieces of state that you must persist on the customer side:
  • walletMetadata — non-sensitive identity + backup-pointer info. Cache it in Redis, Postgres, or similar. You’ll pass it to every subsequent sign / export / backup operation.
  • externalServerKeyShares — sensitive MPC key material. Store in a secrets vault (HSM, KMS-wrapped column, Secret Manager).
See Storage Best Practices for the cache + vault split. The wallet’s address is at walletMetadata.accountAddress — pass walletMetadata to subsequent calls rather than reconstructing args from individual fields.
Removed in V1. The Node SDK no longer holds wallet state internally. If you are migrating from a pre-V1 SDK, the following have been removed: the in-memory walletMap, client.getWallet(address), initializeWalletMapEntry, and ensureCeremonyCompletionBeforeBackup. recoverEncryptedBackupByWallet no longer accepts storeRecoveredShares — the caller now decides what to do with the returned shares. Every sign / export / backup operation now takes explicit walletMetadata (and externalServerKeyShares when supplying shares yourself), so the caller owns persistence.
backUpToDynamic is false by default, which means Dynamic will not store the key shares for you. You are responsible for securely storing the externalServerKeyShares returned by createWalletAccount. Losing these shares means losing access to the wallet. See Storage Best Practices for guidance on secure storage.Alternatively, set backUpToDynamic: true to leverage Dynamic’s key share service, in which case you do not need to manage storage yourself.
6

Example: Sign a message with the MPC wallet account

import { authenticatedEvmClient } from '<path-to-dynamic-authenticated-client>';

const AUTH_TOKEN = 'your-auth-token';
const ENVIRONMENT_ID = 'your-environment-id';

const evmClient = await authenticatedEvmClient({
  authToken: AUTH_TOKEN,
  environmentId: ENVIRONMENT_ID,
});

const message = 'Hello, world!';
const password = 'your-password'; // Required if the wallet was created with backUpToDynamic: true

// Load walletMetadata + externalServerKeyShares from where you persisted them.
const walletMetadata = JSON.parse(await redis.get(`wallet:${accountAddress}`));
const externalServerKeyShares = await vault.read(`wallet:${accountAddress}/shares`);

const serializedSignature = await evmClient.signMessage({
  message,
  walletMetadata,
  externalServerKeyShares,
  password,
});

Next Steps

You can find the full SDK reference for server wallets for each chain below:

EVM

EVM Guides

SVM

SVM Guides