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.
Overview
This guide shows you how to work with imported EVM wallets for common operations. Once you’ve imported a private key, you’ll need to retrieve key shares and perform various wallet operations.
Prerequisites
After importing a wallet, you’ll need to get the external server key shares for signing operations:
import { authenticatedEvmClient } from './client';
const evmClient = await authenticatedEvmClient();
// Get external server key shares for your imported wallet
const keyShares = await evmClient.getExternalServerKeyShares({
accountAddress: '0xYourImportedWalletAddress'
});
console.log('Key shares retrieved:', keyShares.length);
Step 2: Check Wallet Balance
Check the balance of your imported wallet:
import { http } from 'viem';
import { base } from 'viem/chains';
const publicClient = evmClient.createViemPublicClient({
chain: base,
rpcUrl: 'https://mainnet.base.org',
});
const balance = await publicClient.getBalance({
address: '0xYourImportedWalletAddress' as `0x${string}`,
});
console.log('Balance:', balance.toString(), 'wei');
console.log('Balance in ETH:', Number(balance) / 1e18);
Step 3: Sign Transactions with Imported Wallet
Use your imported wallet to sign transactions:
import { parseEther } from 'viem/utils';
// Prepare transaction
const transactionRequest = {
to: '0xRecipientAddress' as `0x${string}`,
value: parseEther('0.1'),
};
const preparedTx = await publicClient.prepareTransactionRequest({
...transactionRequest,
chain: base,
account: '0xYourImportedWalletAddress' as `0x${string}`,
});
// Sign with imported wallet
const signedTx = await evmClient.signTransaction({
senderAddress: '0xYourImportedWalletAddress' as `0x${string}`,
externalServerKeyShares: keyShares,
transaction: preparedTx,
password: 'your-wallet-password', // Only if wallet was created with password
});
console.log('Transaction signed with imported wallet');
Step 4: Sign Messages with Imported Wallet
Sign messages for authentication or data integrity:
const message = 'Hello from my imported wallet!';
const signature = await evmClient.signMessage({
message,
accountAddress: '0xYourImportedWalletAddress',
externalServerKeyShares: keyShares,
password: 'your-wallet-password', // Only if wallet was created with password
});
console.log('Message signed:', signature);
Step 5: Verify Wallet Operations
Verify that your imported wallet can perform operations:
// Check if wallet requires password for operations
const requiresPassword = await evmClient.requiresPasswordForOperation({
accountAddress: '0xYourImportedWalletAddress',
walletOperation: 'SIGN_MESSAGE',
});
console.log('Requires password for signing:', requiresPassword);
// Verify password if needed
if (requiresPassword) {
await evmClient.verifyPassword({
accountAddress: '0xYourImportedWalletAddress',
password: 'your-wallet-password',
walletOperation: 'SIGN_MESSAGE'
});
console.log('Password verified successfully');
}
Complete Example: Send ETH from Imported Wallet
export const sendEthFromImportedWallet = async ({
walletAddress,
toAddress,
amount,
password,
}: {
walletAddress: string;
toAddress: string;
amount: string; // Amount in ETH
password?: string;
}) => {
const evmClient = await authenticatedEvmClient();
// Get key shares for imported wallet
const keyShares = await evmClient.getExternalServerKeyShares({
accountAddress: walletAddress
});
// Create public client
const publicClient = evmClient.createViemPublicClient({
chain: base,
rpcUrl: 'https://mainnet.base.org',
});
// Check balance first
const balance = await publicClient.getBalance({
address: walletAddress as `0x${string}`,
});
const amountWei = parseEther(amount);
if (balance < amountWei) {
throw new Error('Insufficient balance');
}
// Prepare and sign transaction
const preparedTx = await publicClient.prepareTransactionRequest({
to: toAddress as `0x${string}`,
value: amountWei,
chain: base,
account: walletAddress as `0x${string}`,
});
const signedTx = await evmClient.signTransaction({
senderAddress: walletAddress as `0x${string}`,
externalServerKeyShares: keyShares,
transaction: preparedTx,
password, // Only if wallet was created with password
});
// Send transaction
const walletClient = createWalletClient({
chain: base,
transport: http('https://mainnet.base.org'),
account: walletAddress as `0x${string}`,
});
const txHash = await walletClient.sendRawTransaction({
serializedTransaction: signedTx,
});
return txHash;
};
// Usage
const txHash = await sendEthFromImportedWallet({
walletAddress: '0xYourImportedWalletAddress',
toAddress: '0xRecipientAddress',
amount: '0.1',
password: 'your-wallet-password',
});
console.log('Transaction sent:', txHash);
Best Practices
- Key Share Management: Always retrieve fresh key shares before operations
- Balance Checking: Verify sufficient balance before sending transactions
- Password Handling: Check if password is required and handle accordingly
- Error Handling: Implement proper error handling for all wallet operations
- Security: Never expose key shares in client-side code
Password Handling:
- If your imported wallet was created without a password, omit the
password parameter
- If your imported wallet was created with a password, you must provide it for all operations
- The password parameter is always optional in the API, but required if the wallet is password-protected
Next Steps