Multi-Wallet (code based)

Enable Multi-wallet

To leverage our no-UI SDK functions (widget coming soon), you'll want to reference the code snippet below.

To get started, you'll want to configure the multiWallet setting to enable the functionality to link additional wallets to a single account:

<DynamicContextProvider
  settings={{
    multiWallet: true,
    ...
  }}
>
  {...}
</DynamicContextProvider>

Multi-wallet SDK functions

Once the multi-wallet is enabled, you'll be able to leverage the functions to manage multiple wallets per user. This code snippet outlines getting a bare bones version setup with these main functions available to you, and you'll want to note the following functions:

  1. primaryWallet - this is the signing wallet
  2. secondaryWallets - these are all the linked wallets that you can reference. You can access the web3provider to read from these wallets.
  3. setPrimaryWallet - if you want to toggle between linked accounts, then call this method to switch the primary wallet.
  4. handleUnlink wallet - if a user wants to unlink a linked wallet, then call this method and we'll remove the wallet association from the user account.
  5. multiWalletWidgetState- the current state of the widget (even if you're not using the widget) is defined here:
    1. idle - the widget’s default state
    2. awaiting_account_switch - the widget should prompt the user to switch accounts in their wallet
    3. awaiting_connection - the widget should prompt the user to connect their wallet to the site
    4. awaiting_signature - the widget should prompt the user to sign a message to prove ownership of their wallet
    5. detected_known_secondary_wallet - the widget should inform the user that their primary wallet has been switched automatically
    6. detected_new_wallet - the widget should prompt the user to link the new wallet

Recently added features (9/8/22)

  • We now support multiple walletconnect sessions
  • We support both Metamask & Phantom having multiple accounts.
  • We reflect the connected status of the linked wallets..
  • When someone tries to link a wallet that is associated with a different account, then we ask the user to confirm ownership of the wallet so they transfer the wallet between accounts.
  • To make a wallet the active wallet, we require proof of ownership (signing the wallet) only the first time it is linked. After that, we only require that the active wallet be connected.
  • (Scheduled to be released 9/9) When someone tries to link a wallet that is associated with a different account, then we offer ask the user to confirm ownership of the wallet so they transfer the wallet between accounts.
  • (Scheduled to be released 9/9) We now identify when a user changes their wallet in their Metamask, Phantom, and WalletConnect based wallets, ensuring the SDK is update to date with the active wallet

Upcoming features

  • We are adding an additional method to connect a secondary wallet so you can connect any wallet without needing to make it the active wallet.
  • We are working on providing a new repo that provides a full implementation of our multi-wallet code.
  • We are resolving some UX issues.
  • We are finalizing our Widget so you can instead embed a widget into your site that supports all these functions out of the box.
import {
  useDynamicContext,
  DynamicAuthFlow,
  DynamicContextProvider,
} from '@dynamic-labs/sdk-react';

const Home = () => {
  const {
    user,
    handleLogOut,
    handleUnlinkWallet,
    setShowAuthFlow,
    primaryWallet,
    secondaryWallets,
    setPrimaryWallet,
  } = useDynamicContext();

  const handleSignMessage = async () => {
    try {
      const signedMessage = await primaryWallet?.connector.signMessage(
        'example',
      );
      alert(signedMessage);
    } catch (e: any) {
      alert(e.message);
    }
  };

  if (user && primaryWallet) {
    return (
      <>
        <div>
          <span>Primary Wallet</span>
          <div>
            {primaryWallet.address} ({primaryWallet.connector.name})
          </div>
          <hr />
          <div>
            <span>Secondary wallets</span>
            {secondaryWallets.map((wallet) => (
              <div key={wallet.address}>
                <span>
                  {wallet.address} ({wallet.connector.name})
                </span>
                <button onClick={() => setPrimaryWallet(wallet.id)}>
                  Set Primary
                </button>
                <button onClick={() => handleUnlinkWallet(wallet.id)}>
                  Unlink
                </button>
              </div>
            ))}
          </div>
          <hr />
          <div>
            <button onClick={handleSignMessage}>Sign Message</button>
          </div>
          <div>
            <button type='button' onClick={() => setShowAuthFlow(true)}>
              Link Wallet
            </button>
          </div>
          <button type='button' onClick={handleLogOut}>
            Log Out
          </button>
        </div>
        <DynamicAuthFlow onAuthSuccess={() => window.location.assign('/')} />
      </>
    );
  }

  return (
    <div>
      <button type='button' onClick={() => setShowAuthFlow(true)}>
        Connect With My Wallet
      </button>
      <DynamicAuthFlow onAuthSuccess={() => window.location.assign('/')} />
    </div>
  );
};

const App = () => (
  <DynamicContextProvider
    settings={{
      appLogoUrl:
        'https://upload.wikimedia.org/wikipedia/commons/3/34/Examplelogo.svg',
      appName: 'Example App',
      environmentId: 'ENV_ID',
        multiWallet: true
    }}
  >
    <Home />
  </DynamicContextProvider>
);

export default App;

What’s Next
Did this page help you?