Skip to main content

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.

Only available from v4.37.0 onwards.

Summary

The useWalletDelegation hook provides methods to trigger and manage the wallet delegation flow for Dynamic embedded wallets. For more information on how wallet delegation works, see the delegated access documentation. The hook needs to be initialized within a child of DynamicContextProvider.

Return Value

The hook returns an object with the following properties:
{
  initDelegationProcess: (options?: { wallets?: Wallet[] }) => Promise<void>;
  shouldPromptWalletDelegation: () => boolean;
  getWalletsDelegatedStatus: () => { address: string; chain: string; status: WalletDelegationStatus }[];
  delegateKeyShares: (wallets?: { chainName: ChainEnum; accountAddress: string }[]) => Promise<void>;
  revokeDelegation: (wallets: { chainName: ChainEnum; accountAddress: string; status: WalletDelegationStatus }[]) => Promise<void>;
  denyWalletDelegation: () => void;
  dismissDelegationPrompt: () => void;
  clearDelegationSessionState: () => void;
  delegatedAccessEnabled: boolean | undefined;
  requiresDelegation: boolean | undefined;
}

Functions

initDelegationProcess

Initiates the wallet delegation flow by opening the Dynamic modal and displaying the delegation prompt to the user. Parameters:
  • options (optional): Configuration object
    • wallets (optional): Array of specific wallets to delegate. If not provided, delegates all eligible MPC wallets.
Returns: Promise<void> - Resolves when delegation completes successfully, rejects on failure. Errors:
  • Throws "No primary wallet" if the user doesn’t have a primary wallet connected
  • Throws "user_not_logged_in" if the user is not authenticated
Example:
const { initDelegationProcess } = useWalletDelegation();

try {
  await initDelegationProcess();
  console.log('Delegation completed successfully');
} catch (error) {
  console.error('Delegation failed:', error);
}

shouldPromptWalletDelegation

Determines whether the user should be prompted for wallet delegation based on:
  • Delegated access settings in project configuration
  • User’s previous delegation decisions (denied or completed)
  • Existence of undelegated MPC wallets
Returns: boolean - true if the user should see the delegation prompt, false otherwise. Example:
const { shouldPromptWalletDelegation } = useWalletDelegation();

if (shouldPromptWalletDelegation()) {
  // Show custom UI or automatically trigger delegation
}

getWalletsDelegatedStatus

Returns the delegation status of all MPC wallets for the current user. Returns: An array of objects containing:
  • address: string - The wallet address
  • chain: string - The chain the wallet is on
  • status: WalletDelegationStatus - The delegation status (‘delegated’, ‘pending’, or ‘not_delegated’)
Example:
const { getWalletsDelegatedStatus } = useWalletDelegation();

const walletStatuses = getWalletsDelegatedStatus();

walletStatuses.forEach((wallet) => {
  console.log(`${wallet.address} on ${wallet.chain}: ${wallet.status}`);
});

// Filter for delegated wallets
const delegatedWallets = walletStatuses.filter(
  (wallet) => wallet.status === 'delegated'
);

delegateKeyShares

Delegates key shares for one or more wallets. This allows your application to act on behalf of the user’s wallet (see Delegated Access). Parameters:
  • wallets (optional): Array of wallet objects to delegate. Each wallet object should have:
    • chainName: ChainEnum - The chain the wallet is associated with
    • accountAddress: string - The address of the wallet to delegate
If wallets is not provided or is empty, the function will delegate all pending wallets eligible for delegation. Returns: Promise resolving to void on success. The function automatically refreshes user data after delegation completes. Errors: Throws DelegationError when one or more per-wallet delegations fail. The hook still attempts every wallet and still calls refresh — the error is thrown after the loop with the full set of successful and failed wallets attached, so callers can decide what to retry. Example:
import { ChainEnum } from '@dynamic-labs/sdk-api-core';
import { DelegationError } from '@dynamic-labs/sdk-react-core';

const { delegateKeyShares } = useWalletDelegation();

try {
  await delegateKeyShares([
    {
      chainName: ChainEnum.Evm,
      accountAddress: '0x123...',
    },
  ]);
} catch (err) {
  if (err instanceof DelegationError) {
    console.log(
      `${err.failureCount} of ${err.successCount + err.failureCount} wallets failed`,
    );
    // err.successfulWallets / err.failedWallets are structured for retry logic
  }
}

// Delegate all pending wallets
await delegateKeyShares();
Behavior:
  • Delegates wallets sequentially (one at a time)
  • Continues iterating even if individual wallets fail
  • Always refreshes user data after the loop (even on partial failure) so wallet state stays in sync
  • Throws a single DelegationError at the end if any per-wallet delegation failed

revokeDelegation

Revokes delegation for one or more wallets. This removes your application’s ability to act on behalf of the user’s wallet (see Revoking Delegation). Parameters:
  • wallets: Array of wallet objects to revoke. Each wallet object should have:
    • chainName: ChainEnum - The chain the wallet is associated with
    • accountAddress: string - The address of the wallet to revoke
    • status: WalletDelegationStatus - The delegation status of the wallet (must be ‘delegated’ for revocation to proceed)
Returns: Promise resolving to void on success. The function automatically refreshes user data after revocation completes. Errors: Throws DelegationError when one or more per-wallet revocations fail. The hook still attempts every wallet and still calls refresh — the error is thrown after the loop. Example:
import { ChainEnum } from '@dynamic-labs/sdk-api-core';
import { DelegationError } from '@dynamic-labs/sdk-react-core';

const { revokeDelegation, getWalletsDelegatedStatus } = useWalletDelegation();

// Get delegated wallets and revoke them
const delegatedWallets = getWalletsDelegatedStatus().filter(
  (wallet) => wallet.status === 'delegated'
);

try {
  await revokeDelegation(
    delegatedWallets.map((wallet) => ({
      chainName: wallet.chain as ChainEnum,
      accountAddress: wallet.address,
      status: wallet.status,
    }))
  );
} catch (err) {
  if (err instanceof DelegationError) {
    // err.operation === 'revoke' here
    // Inspect err.failedWallets to decide what to retry
  }
}
Behavior:
  • Revokes wallets sequentially (one at a time)
  • Only attempts to revoke wallets with status ‘delegated’ (logs a warning and skips others)
  • Continues iterating even if individual revocations fail
  • Always refreshes user data after the loop (even on partial failure) so wallet state stays in sync
  • Throws a single DelegationError at the end if any per-wallet revocation failed

denyWalletDelegation

Permanently denies wallet delegation for the current user. This sets a flag that prevents the delegation prompt from appearing again, even if the user has undelegated wallets. Returns: void Example:
const { denyWalletDelegation, shouldPromptWalletDelegation } = useWalletDelegation();

// User clicks "Don't ask again" button
const handleDenyDelegation = () => {
  denyWalletDelegation();
  // shouldPromptWalletDelegation() will now return false
};

dismissDelegationPrompt

Temporarily dismisses the delegation prompt for the current session. Unlike denyWalletDelegation, this does not permanently prevent the prompt from appearing - it will show again in future sessions. Returns: void Example:
const { dismissDelegationPrompt } = useWalletDelegation();

// User clicks "Maybe later" button
const handleDismiss = () => {
  dismissDelegationPrompt();
  // Prompt won't appear again this session
};

clearDelegationSessionState

Clears all delegation-related session state, including any “denied” or “dismissed” flags. This resets the delegation prompt behavior, allowing it to appear again based on the user’s wallet status. Returns: void Example:
const { clearDelegationSessionState, shouldPromptWalletDelegation } = useWalletDelegation();

// Reset delegation state (e.g., when user wants to reconsider)
const handleResetDelegationState = () => {
  clearDelegationSessionState();
  // Delegation prompt can now appear again if conditions are met
  if (shouldPromptWalletDelegation()) {
    // Show delegation prompt
  }
};

DelegationError

Thrown by delegateKeyShares and revokeDelegation when one or more per-wallet operations fail. Extends AggregateError, so callers reading the underlying causes via .errors keep working; structured fields make it easy to drive partial-failure UI without parsing the message. Fields:
  • operation: 'delegate' | 'revoke' — which method threw.
  • successfulWallets: { chainName: ChainEnum; accountAddress: string }[] — wallets that completed before the error was thrown.
  • failedWallets: { wallet: { chainName: ChainEnum; accountAddress: string }; cause: unknown }[] — wallets that failed and their underlying causes.
  • successCount: number — convenience getter.
  • failureCount: number — convenience getter.
  • message: string"Delegation failed for X of Y wallet(s): <first underlying cause>" (or "Revoke delegation failed for ..." for revocations).
Example — partial-failure retry:
import { DelegationError } from '@dynamic-labs/sdk-react-core';

try {
  await delegateKeyShares(wallets);
} catch (err) {
  if (err instanceof DelegationError) {
    // Re-attempt only the wallets that failed
    const retryTargets = err.failedWallets.map((f) => f.wallet);
    await delegateKeyShares(retryTargets);
  } else {
    throw err;
  }
}

Properties

delegatedAccessEnabled

A boolean value from your project settings that indicates whether delegated access is enabled for your application. Type: boolean | undefined Example:
const { delegatedAccessEnabled } = useWalletDelegation();

if (delegatedAccessEnabled) {
  // Delegated access feature is enabled
  // You can show delegation-related UI
}

requiresDelegation

A boolean value from your project settings that indicates whether wallet delegation is required for your application. Type: boolean | undefined Example:
const { requiresDelegation } = useWalletDelegation();

if (requiresDelegation) {
  // Delegation is mandatory for this application
  // You might want to block certain actions until delegation is complete
}

Usage

import { useWalletDelegation } from '@dynamic-labs/sdk-react-core';

const MyComponent = () => {
  const { 
    initDelegationProcess, 
    shouldPromptWalletDelegation,
    getWalletsDelegatedStatus,
    denyWalletDelegation,
    dismissDelegationPrompt,
    delegatedAccessEnabled,
    requiresDelegation 
  } = useWalletDelegation();

  const handleDelegateWallet = async () => {
    try {
      await initDelegationProcess();
      console.log('Wallet delegation successful!');
    } catch (error) {
      console.error('Failed to delegate wallet:', error);
    }
  };

  // Automatically prompt on mount if needed
  useEffect(() => {
    if (shouldPromptWalletDelegation()) {
      initDelegationProcess();
    }
  }, []);

  // Check delegation status of wallets
  const walletStatuses = getWalletsDelegatedStatus();
  const hasDelegatedWallets = walletStatuses.some(w => w.status === 'delegated');

  return (
    <div>
      {delegatedAccessEnabled && !hasDelegatedWallets && (
        <div>
          <p>Enable delegated access for a better experience</p>
          <button onClick={handleDelegateWallet}>Delegate Wallet</button>
          <button onClick={dismissDelegationPrompt}>Maybe Later</button>
          <button onClick={denyWalletDelegation}>Don't Ask Again</button>
        </div>
      )}
      {requiresDelegation && !hasDelegatedWallets && (
        <p>This app requires wallet delegation to function</p>
      )}
    </div>
  );
};

Advanced Usage

Delegate specific wallets:
import { useWalletDelegation } from '@dynamic-labs/sdk-react-core';
import { useUserWallets } from '@dynamic-labs/sdk-react-core';

const MyComponent = () => {
  const { initDelegationProcess } = useWalletDelegation();
  const { userWallets } = useUserWallets();

  const delegateSpecificWallet = async (walletId: string) => {
    const wallet = userWallets.find(w => w.id === walletId);
    
    if (wallet) {
      try {
        await initDelegationProcess({ wallets: [wallet] });
        console.log('Specific wallet delegated successfully');
      } catch (error) {
        console.error('Delegation failed:', error);
      }
    }
  };

  return (
    <div>
      {userWallets.map(wallet => (
        <button 
          key={wallet.id}
          onClick={() => delegateSpecificWallet(wallet.id)}
        >
          Delegate {wallet.address}
        </button>
      ))}
    </div>
  );
};

Important Notes

  • The user must be authenticated and have a primary wallet for delegation to work
  • The delegation modal is part of the Dynamic UI and handles all user interactions
  • User delegation preferences are persisted across sessions using local storage

Learn More