Let’s look at an example to get used to working with our SDK! Imagine we want to get the address and signer of the user’s primary wallet, and also sign a transaction.

This tutorial assumes you have already completed a quickstart. If you haven’t, please do so here.

Accessing hooks

Once you wrap your application in the DynamicContextProvider component and have your environmentId set, any child component will be able to use the provided hooks and components. We will employ a commonly used hook: useDynamicContext.

This hook gives you access to all kinds of things, which you can learn about here. Specifically though, it gives you access to wallets that the user has associated with them.

You can access wallets in multiple ways through the hook, from the list of currently connected wallets, to the secondary wallets connected. Again, all these attributes can be found in the spec for the hook.

Getting primary wallet address One of the most commonly accessed attributes is primaryWallet, which is an instance of a Wallet that represents the most recently connected wallet, or the last wallet that was selected as primary wallet - this is the one we want!

const { primaryWallet } = useDynamicContext();

Since primaryWallet is an instance of Wallet, we can look at the Object Reference to see what this gives us access to. Immediately we can see “address” which is the first thing we wanted:

const primaryWalletAddress = primaryWallet?.address;

Remember that there will be times when a wallet is not connected, so make sure and handle these states.

Getting the signer and signing

Now the last part, the signer. We can also see in the reference for Wallet that there is a field called connector. This is a really important concept!

Each web3 wallet has different methods associated with it. For example a Metamask might have different method names than Phantom. We provide you with an interface so the methods are standardized between all wallets - that’s the wallet connector interface!

Each and every Wallet has a connector object on it, accessed like this:

const connector = primaryWallet?.connector;

Once we have our connector, we can very quickly sign a message using the following:

const signature = await signer.signMessage(‘example’)

If you are using Ethers rather than viem which is our default, this looks a little different. Please refer to this guide.

We’re done!


We explained how the SDK works by demonstrating an example.

By using the useDynamicContext hook within the DynamicContextProvider component, we accessed the Wallet interface.

Through this interface, we obtained the address of the user’s primary wallet using primaryWallet.address.

We also learned about the connector attribute, which led us to the wallet connector interface. From there, we accessed the getSigner() method to retrieve the signer for the wallet and use that signer to sign an example message.

Full Code

import "./App.css";
import Main from "./components/Main";

import { DynamicContextProvider } from "@dynamic-labs/sdk-react-core";

function App() {
  return (
    <div className="App">
          environmentId: "dca95954-81d8-4ef8-b20f-b1c3b6781cb6",
        <Main />

export default App;
import { useDynamicContext, DynamicWidget } from "@dynamic-labs/sdk-react-core";

const Main = () => {
  const { primaryWallet } = useDynamicContext();

  const signMessage = async (primaryWallet) => {
    if (!primaryWallet) return null;
    else {

    const signer = await primaryWallet.connector.getSigner();

    return signer ? await signer.signMessage("example") : null;

  return (
      <DynamicWidget />
      <button onClick={() => signMessage(primaryWallet)}>Sign Message</button>

export default Main;

You can find more examples here