Skip to main content

Function Signature

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

Description

Signs EIP-712 typed data using the specified EVM wallet address. 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.

Parameters

Required Parameters

  • accountAddress (string) — The wallet address to sign with (must include 0x prefix)
  • typedData (TypedData) — The EIP-712 typed data to sign (viem’s TypedData type)

Optional Parameters

  • password (string) — Wallet password (if the wallet is password-protected)
  • externalServerKeyShares (ServerKeyShare[]) — Array of external server key shares (for advanced key management)
  • 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;

const signature = await evmClient.signTypedData({
  accountAddress: '0xYourWalletAddress',
  typedData,
  password: 'optional-password', // omit if wallet has no password
});

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 (backUpToClientShareService: true), you typically do not need externalServerKeyShares.
  • If the wallet was created with manual backup (backUpToClientShareService: 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({
    accountAddress: '0xYourWalletAddress',
    typedData,
    onError: (err) => console.error('Signing error:', err),
  });
  console.log('Signed:', signature);
} catch (error) {
  console.error('Failed to sign typed data:', error);
}