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

# signTypedData

> Signs EIP-712 typed data using the specified EVM wallet

## Function Signature

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

## Description

Signs [EIP-712](https://eips.ethereum.org/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.

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

## Parameters

### Required Parameters

* **`walletMetadata`** ([`WalletMetadata`](/node/reference/types/wallet-metadata)) — 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[]`](/node/reference/types/server-key-share)) — 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`:

```typescript theme={"system"}
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](/node/wallets/server-wallets/viem-wallet-client). The returned wallet client's `signTypedData` forwards to the same client implementation.

```typescript theme={"system"}
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

```typescript theme={"system"}
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);
}
```

## Related

* [signMessage()](/node/reference/evm/sign-message) — Sign a raw message
* [signTransaction()](/node/reference/evm/sign-transaction) — Sign a transaction
* [Get a Viem wallet client](/node/wallets/server-wallets/viem-wallet-client) — Use signTypedData via viem's WalletClient
