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.

Function Signature

signTypedData(params: {
  walletMetadata: WalletMetadata;
  typedData: TypedData;
  password?: string;
  externalServerKeyShares?: ServerKeyShare[];
  onError?: (error: Error) => void;
}): Promise<string>

Description

Signs EIP-712 typed data using the EVM wallet identified by the supplied walletMetadata. The client formats the typed data, recovers key shares if needed, signs with the wallet’s key, and returns the serialized ECDSA signature as a hex string. Use this for permit flows, order signing, and other structured data that requires typed-data signing.
When you pass externalServerKeyShares (the caller-supplied path), walletMetadata.externalServerKeySharesBackupInfo must also be present — signTypedData throws if shares are supplied but backup metadata is missing. The full walletMetadata returned from createWalletAccount / importPrivateKey already includes it; identity-only metadata from fetchWalletMetadata will be rejected.

Parameters

Required Parameters

  • walletMetadata (WalletMetadata) — Non-sensitive wallet metadata persisted from createWalletAccount() / importPrivateKey(). The signer address comes from walletMetadata.accountAddress.
  • typedData (TypedData) — The EIP-712 typed data to sign (viem’s TypedData type)

Optional Parameters

  • password (string) — Required if the wallet was created with backUpToDynamic: true. Used for backup decryption when externalServerKeyShares is not provided.
  • externalServerKeyShares (ServerKeyShare[]) — Caller-supplied plaintext shares. If omitted, the SDK recovers from backup using password.
  • onError ((error: Error) => void) — Callback invoked if an error occurs during signing

Returns

  • Promise<string> — The serialized ECDSA signature as a hex string

Usage

Direct (DynamicEvmWalletClient)

Call signTypedData on your authenticated DynamicEvmWalletClient:
import { DynamicEvmWalletClient } from '@dynamic-labs-wallet/node-evm';
import type { TypedData } from 'viem';

const evmClient = new DynamicEvmWalletClient({
  environmentId: 'your-environment-id',
});
await evmClient.authenticateApiToken('your-api-token');

const typedData = {
  domain: {
    name: 'My App',
    version: '1',
    chainId: 8453,
  },
  types: {
    Permit: [
      { name: 'owner', type: 'address' },
      { name: 'spender', type: 'address' },
      { name: 'value', type: 'uint256' },
      { name: 'nonce', type: 'uint256' },
      { name: 'deadline', type: 'uint256' },
    ],
  },
  primaryType: 'Permit',
  message: {
    owner: '0xYourWalletAddress',
    spender: '0xContractAddress',
    value: 1000000n,
    nonce: 0n,
    deadline: 1735689600n,
  },
} as TypedData;

// Load the metadata + shares you persisted at creation time.
const walletMetadata = JSON.parse(await redis.get(`wallet:${accountAddress}`));
const externalServerKeyShares = await vault.read(`wallet:${accountAddress}/shares`);

const signature = await evmClient.signTypedData({
  walletMetadata,
  typedData,
  externalServerKeyShares,
  password: 'user-password', // required when wallet was created with backUpToDynamic: true
});

console.log('Signature:', signature);

Viem-style (getWalletClient)

For a viem-style API (e.g. with signTypedData(typedData) where the account is implicit), use getWalletClient. The returned wallet client’s signTypedData forwards to the same client implementation.
const walletClient = await evmClient.getWalletClient({
  accountAddress: '0xYourWalletAddress',
  chainId: 8453,
  rpcUrl: 'https://mainnet.base.org',
});

const signature = await walletClient.signTypedData({
  domain: { name: 'My App', version: '1', chainId: 8453 },
  types: { Permit: [/* ... */] },
  primaryType: 'Permit',
  message: { /* ... */ },
});

Key shares and password

  • If the wallet was created with automatic backup (backUpToDynamic: true), you typically do not need externalServerKeyShares.
  • If the wallet was created with manual backup (backUpToDynamic: false), pass externalServerKeyShares when calling signTypedData.
  • If the wallet is password-protected, pass password; otherwise omit it.

Error handling

try {
  const signature = await evmClient.signTypedData({
    walletMetadata,
    typedData,
    externalServerKeyShares,
    password: 'user-password',
    onError: (err) => console.error('Signing error:', err),
  });
  console.log('Signed:', signature);
} catch (error) {
  console.error('Failed to sign typed data:', error);
}