Skip to main content
There are two ways to give an AI agent access to a Dynamic wallet:
  1. Direct — load credentials from environment variables at startup. Best for CLI tools and local development.
  2. Delegated access — each user approves via the Dynamic SDK. Credentials arrive via webhook and are stored per-user. Best for backend APIs and mobile apps.
DirectDelegated access
UsersSingle (you)Any number
CredentialsEnv varsDatabase, per user
Best forCLI tools, local devBackend APIs, mobile apps

Pathway 1: Direct (CLI / single-user)

Step 1: Get credentials from Dynamic dashboard

Find the wallet you want the agent to use and copy:
  • Wallet ID
  • Wallet address
  • API key
  • Key share (JSON)

Step 2: Set environment variables

Option A — paste credentials directly:
DELEGATED_WALLET_ID=<wallet-uuid>
DELEGATED_WALLET_ADDRESS=0x...
DELEGATED_WALLET_API_KEY=<api-key>
DELEGATED_KEY_SHARE={"key":"..."}
Option B — paste the encrypted webhook payload: If you already received the delegation webhook, you can paste the encrypted payload directly. Set your RSA private key and the raw encrypted values — the SDK decrypts them at startup.
DELEGATION_KEY=<RSA private key PEM>
DELEGATED_WALLET_ID=<wallet-uuid>
DELEGATED_WALLET_ADDRESS=0x...
ENCRYPTED_WALLET_API_KEY={"iv":"...","ct":"...","ek":"...","tag":"..."}
ENCRYPTED_KEY_SHARE={"iv":"...","ct":"...","ek":"...","tag":"..."}

Step 3: Load and use

const creds = loadDelegationCredentials();
if (!creds) throw new Error("No delegation credentials found");

// Sign a message
const signature = await signMessageDelegated(creds, "Hello");

// Send a transaction
const txHash = await sendTransactionDelegated(creds, chainId, to, data, value);

Pathway 2: Delegated access (multi-user)

Step 1: User connects wallet via Dynamic

The user authenticates in your app. You get a JWT with their Dynamic user ID (user.sub).

Step 2: User approves delegation

Call the Dynamic SDK to start the delegation flow:
const shouldPrompt = await dynamicClient.wallets.waas.delegation
  .shouldPromptWalletDelegation();

if (shouldPrompt) {
  await dynamicClient.wallets.waas.delegation.initDelegationProcess({});
}
When the user approves, Dynamic sends a wallet.delegation.created webhook to your server. See Set up delegated access via webhook for how to handle it.

Step 3: Fetch credentials per request

On each API request, look up the credentials for the authenticated user:
const record = await getDelegation(user.sub);
if (!record) {
  return c.json({ error: "No delegation found. Please grant wallet access first." }, 403);
}

const creds = {
  walletId: record.walletId,
  walletAddress: record.address,
  walletApiKey: record.walletApiKey,
  keyShare: record.keyShare,
};

Step 4: User can revoke at any time

const walletsStatus = await dynamicClient.wallets.waas.delegation
  .getWalletsDelegatedStatus();

const delegatedWallets = walletsStatus
  .filter((w) => w.isDelegated)
  .map((w) => ({ chainName: w.chainName, accountAddress: w.accountAddress }));

await dynamicClient.wallets.waas.delegation.revokeDelegation({
  wallets: delegatedWallets
});
Dynamic fires wallet.delegation.revoked → delete the record → return 403 until re-delegated.

Signing operations

Both pathways use the same signing functions via the @dynamic-labs-wallet/node-evm SDK:
// Sign a message
await signMessageDelegated(creds, message);

// Sign typed data (e.g. for Polymarket orders)
await signTypedDataDelegated(creds, typedData);

// Sign and broadcast a transaction (handles nonce + gas automatically)
await sendTransactionDelegated(creds, chainId, to, data, value);

Supported chains

Chain IDNetwork
1Ethereum
137Polygon
8453Base
10Optimism
42161Arbitrum
56BSC
43114Avalanche