React SDK Setup

Prerequisite

For running the tutorial for developers, we require node version 20 or later version and npm version 8 to be installed in your environment. To install node and npm, we recommend you go to the Node.js official website and download the latest LTS (Long Term Support) version.

If you want to upgrade node to 20 or higher version, we recommend you to use nvm (Node Version Manager). If you want to upgrade npm to the latest version, you can run the command npm install -g nvm.

Create a Next.js Project

Create a folder called story-react-example.

Then follow the short Next.js "Getting Started: Installation" guide to set up a boilerplate Next.js project.

Install the Dependencies

In the current folder story-react-example, install the Story Protocol SDK node package, as well as viem (https://www.npmjs.com/package/viem) to access the DeFi wallet accounts.

npm install --save @story-protocol/react-sdk viem
pnpm install @story-protocol/core-sdk viem
yarn add @story-protocol/core-sdk viem

Initiate SDK Provider

We recommend first setting up wagmi in your application as a Web3 provider. Next, we recommend using Dynamic so that users can log in to their preferred wallet. Ultimately you will end up with something that looks like this:

ℹ️ 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 much 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.

ℹ️ 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.

"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();
// setup dynamic
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 (
    <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 Web3Providers from "./Web3Providers";

export default function RootLayout({
  children
}) {
  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 (
    {/* */} 
  )
}