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);
}