Skip to main content Link Menu Expand (external link) Document Search Copy Copied

Canto Identity Protocol SDK Guide

The purpose of this guide is to get you up and running with the CIP-SDK in your application in just a few minutes, perfect for retrieving user canto identity protocol data. For the sake of simplicity, we will assume that you are building a web application with React. The SDK will also work in node as well.

Prerequisite

We will be using ethers.js wagmi and Rainbowkit in Next.js to interact with the CIP SDK and Canto.

Install

npm install wagmi viem @rainbow-me/rainbowkit ethers

Example

To configure wagmi, create a file called providers.ts:

import { getDefaultWallets } from '@rainbow-me/rainbowkit';
import { configureChains, createConfig, WagmiConfig } from 'wagmi';

export const { chains, publicClient, webSocketPublicClient } = configureChains(
  [canto],
  [publicProvider()]
);

const { connectors } = getDefaultWallets({
  appName: 'RainbowKit App',
  projectId: '54869hvf6h34a0fe6e04561318b5ec99', <-- your projectId
  chains,
});

export const wagmiConfig = createConfig({
  autoConnect: true,
  connectors,
  publicClient,
  webSocketPublicClient,
});

Then in your main _app.tsx file, wrap your app in the wagmi and Rainbowkit providers:

import { RainbowKitProvider } from '@rainbow-me/rainbowkit'
import '@rainbow-me/rainbowkit/styles.css'
import type { AppProps } from 'next/app'
import { useEffect, useState } from 'react'
import { WagmiConfig } from 'wagmi'

import { chains, wagmiConfig } from './providers'

export default function App({ Component, pageProps }: AppProps) {
  const [isMounted, setIsMounted] = useState(false)
  useEffect(() => setIsMounted(true), [])

  return (
    <WagmiConfig config={wagmiConfig}>
      <RainbowKitProvider chains={chains}>
        {isMounted && <Component {...pageProps} />}
      </RainbowKitProvider>
    </WagmiConfig>
  )
}

Now we have an app that is ready to interact with the CIP sdk.

Retrieving Namespace, Bio and PFP.

Easiest way to retrieve a user namepsace, bio and pfp data is to use the getNamespaceByAddress(), getBioByAddress(), getPfpByAddress() methods.

import React, { useState } from 'react';
import { ethers } from 'ethers';
import { CIP } from 'cip-sdk';
import { chains } from './_app';

// pfp data shape
type ProfilePictureInfo = {
  src: string;
  alt: string;
};

//namespace data shape
type NameSpace = {
  displayName: string;
  baseName: string;
};

// select the right chain from wagmi
const cantoChain = chains[0];
const rpcUrl = cantoChain.rpcUrls.default.http[0];

// initialize provider and CIP instance
const provider = new ethers.providers.JsonRpcProvider(rpcUrl);
const cipInstance = new CIP(provider);

//helper function to handle nft picture data. 
const transformUri = (uri: string) => {
  if (!uri) return '';
  else if (uri.includes('ipfs://')) {
    return uri.replace('ipfs://', 'https://dweb.link/ipfs/');
  } else if (uri.includes('arweave://')) {
    return uri.replace('arweave://', 'https://arweave.net/');
  }
  return uri;
};

function Temp() {
  const [isLoading, setIsLoading] = useState(false);
  const [namespace, setNamespace] = useState<NameSpace>({
    displayName: '',
    baseName: '',
  });
  const [bio, setBio] = useState('');
  const [pfp, setPfp] = useState<ProfilePictureInfo>({
    src: '',
    alt: '',
  });

  const handleCall = async () => {
    try {
      setIsLoading(true);
      const addr = '0x7a52439b167eab8382677fdba54c2e2b616bd169'; // <------CIP user address
      
      const namespace = await cipInstance.getNamespaceByAddress(addr); // <---- CIP sdk methods
      const bio = await cipInstance.getBioByAddress(addr); // <---- CIP sdk methods
      const pfp = await cipInstance.getPfpByAddress(addr); // <---- CIP sdk methods
  
      setNamespace({
        displayName: namespace.displayName,
        baseName: namespace.baseName,
      });
  
      setBio(bio);
  
      setPfp({
        src: transformUri(pfp.src),
        alt: pfp.alt,
      });
  
    } catch (error) {
      console.log(error);
    } finally {
      setIsLoading(false);
    }
  };
  

  return (
    <div className='mt-20 flex justify-center align-middle'>
      <div className=''>
        {/* ID CARD */}
        <div
          id='shared-id'
          className='m-auto flex max-w-xl flex-col bg-idCard py-3 px-3'
        >
          <div className='mr-4 flex-shrink-0'></div>
          <div className='flex h-[345px] w-[345px] flex-col items-center justify-between bg-white p-3'>
            <img
              src={pfp.src}
              height={90}
              width={135}
              alt={pfp.alt}
              className='rounded-full'
            />
            <h1 className='mb-1 mt-4 break-words text-2xl'>{namespace.displayName}</h1>
            <h2 className='text-md mb-2 text-gray-400'>{namespace.baseName}</h2>
            <p className='flex-grow text-sm'>{bio}</p>
          </div>
          <div className='mt-1.5 flex justify-between'>
            <div className='mt-1 text-xl font-light text-white'>#14</div>
            <div className='text-md font-light text-white'>
            </div>
            <div
              onClick={handleCall}
              className='items-center bg-slate-600 text-white'
            >
              <button className='rounded bg-slate-500 py-2 px-4 font-bold text-white hover:bg-slate-700'>
                {isLoading ? 'loading' : 'fetch data'}
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

export default Temp;

NPM information

For additional information on the cip-sdk, visit the package website.