Wagmi + Dynamic Setup

Optional: Check out the official Wagmi + Dynamic installation docs here.

Install the Dependencies

npm install --save @story-protocol/react-sdk viem wagmi @dynamic-labs/sdk-react-core @dynamic-labs/wagmi-connector @dynamic-labs/ethereum @tanstack/react-query
pnpm install @story-protocol/core-sdk viem
yarn add @story-protocol/core-sdk viem

Setup

Before diving into the example, make sure you have two things setup:

  1. Make sure to have NEXT_PUBLIC_RPC_PROVIDER_URL for your desired chain set up in your .env file. You can use a public default one (NEXT_PUBLIC_RPC_PROVIDER_URL=https://ethereum-sepolia-rpc.publicnode.com) or, for a potentially faster experience, sign up for a free Alchemy account and create an Ethereum Sepolia test application to get your own private RPC URL. Once your application is created, you can click the "API Key" button and then copy the link in the HTTP box.
  2. Make sure to have NEXT_PUBLIC_DYNAMIC_ENV_ID set up in your .env file. Do this by logging into Dynamic and creating a project.

You can then configure your DApp with help from the following example:

"use client";
import { http, createConfig, WagmiProvider } from "wagmi";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { sepolia } from "wagmi/chains";
import { DynamicContextProvider } from "@dynamic-labs/sdk-react-core";
import { DynamicWagmiConnector } from "@dynamic-labs/wagmi-connector";
import { EthereumWalletConnectors } from "@dynamic-labs/ethereum";
import { PropsWithChildren } from "react";
import { StoryProvider } from "@story-protocol/react-sdk";

// setup wagmi
const config = createConfig({
  chains: [sepolia],
  multiInjectedProviderDiscovery: false,
  transports: {
    [sepolia.id]: http(),
  },
});
const queryClient = new QueryClient();

// add any extra networks here
const evmNetworks = [
  {
    blockExplorerUrls: ["https://sepolia.etherscan.io"],
    chainId: 11155111,
    iconUrls: ["https://app.dynamic.xyz/assets/networks/sepolia.svg"],
    name: "Sepolia",
    nativeCurrency: {
      decimals: 18,
      name: "Sepolia Ether",
      symbol: "ETH",
    },
    networkId: 11155111,
    rpcUrls: [process.env.NEXT_PUBLIC_RPC_PROVIDER_URL as string],
    vanityName: "Sepolia",
  },
];

export default function Web3Providers({ children }: PropsWithChildren) {
  return (
    // setup dynamic
    <DynamicContextProvider
      settings={{
        appName: "Story Documentation",
        // Find your environment id at https://app.dynamic.xyz/dashboard/developer
        environmentId: process.env.NEXT_PUBLIC_DYNAMIC_ENV_ID as string,
        walletConnectors: [EthereumWalletConnectors],
        overrides: { evmNetworks },
        networkValidationMode: "always",
      }}
    >
      <WagmiProvider config={config}>
        <QueryClientProvider client={queryClient}>
          <DynamicWagmiConnector>
            <StoryProviderWrapper>
              {children}
            </StoryProviderWrapper>
          </DynamicWagmiConnector>
        </QueryClientProvider>
      </WagmiProvider>
    </DynamicContextProvider>
  );
}

// we use this component to pass in our 
// wallet from wagmi
function StoryProviderWrapper({ children}: PropsWithChildren) {
  const { data: wallet } = useWalletClient();
  
  // react sdk will throw an error if wallet is
  // undefined, meaning user has not logged in yet
  // using the DynamicWidget login
  if (!wallet) {
   return <>{children}</> 
  }
  
  return (
    <StoryProvider
      config={{
        chainId: "sepolia",
        transport: http(process.env.NEXT_PUBLIC_RPC_PROVIDER_URL),
        wallet: wallet,
      }}
    >
      {children}
    </StoryProvider>
  )
}
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import { PropsWithChildren } from "react";
import Web3Providers from "./Web3Providers";

const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
  title: "Example",
  description: "This is an Example DApp",
};

export default function RootLayout({
  children
}: PropsWithChildren) {
  return (
    <html lang="en">
      <body>
        <Web3Providers>{children}</Web3Providers>
      </body>
    </html>
  );
}
import { custom, toHex } from 'viem';
import { useIpAsset } from "@story-protocol/react-sdk";

// example of how you would now use the fully setup react sdk

export default function TestComponent() {
  const { register } = useIpAsset();
  
  const response = await register({
    nftContract: '0x01...',
    tokenId: '1',
    metadata: {
      metadataURI: "test-metadata-uri",
      metadataHash: toHex("test-metadata-hash", { size: 32 }),
      nftMetadataHash: toHex("test-nft-metadata-hash", { size: 32 }),
    },
    txOptions: { waitForTransaction: true },
  });
  console.log(
    `Root IPA created at tx hash ${response.txHash}, IPA ID: ${response.ipId}`
  );
  
  return (
    {/* */} 
  )
}