For the complete documentation index, see llms.txt. This page is also available as Markdown.

React Context Provider

In React applications, you can wrap the SDK download and initialization flow in a context provider. This keeps the CSPR.click runtime reference and connected account state available to any component through a custom hook.

Use this approach when your application loads CSPR.click from the CDN but still wants React-friendly access to the SDK. If you are not using React, follow the lower-level Downloading and initializing the SDK guide instead.

Create the provider

Create a ClickContext.tsx file and define the SDK options before the runtime script is loaded. The provider listens for the csprclick:loaded event, stores the SDK reference, and keeps the active account state synchronized with CSPR.click events.

import { createContext, useContext, useEffect, useState } from 'react';
import type { ReactNode } from 'react';
import {
  CONTENT_MODE,
  WALLET_KEYS,
} from '@make-software/csprclick-core-types';
import type {
  AccountType,
  CsprClickInitOptions,
  ICSPRClickSDK,
} from '@make-software/csprclick-core-types';
import type { ClickUIOptions } from '@make-software/csprclick-core-types/clickui';

declare global {
  interface Window {
    clickUIOptions: ClickUIOptions;
    clickSDKOptions: CsprClickInitOptions;
    csprclick?: ICSPRClickSDK;
  }
}

window.clickUIOptions = {
  uiContainer: 'csprclick-ui',
  rootAppElement: '#root',
  show1ClickModal: true,
  showTopBar: true,
  accountMenuItems: [
    'AccountCardMenuItem',
    'CopyHashMenuItem',
    'BuyCSPRMenuItem',
  ],
  defaultTheme: 'light',
};

window.clickSDKOptions = {
  appName: 'CSPR.click React template',
  appId: 'csprclick-template',
  providers: [
    WALLET_KEYS.CASPER_WALLET,
    WALLET_KEYS.LEDGER,
    WALLET_KEYS.METAMASK_SNAP,
  ],
  contentMode: CONTENT_MODE.IFRAME,
};

type ClickContextState = {
  publicKey: string | undefined;
  provider: string | undefined;
  clickRef: ICSPRClickSDK | undefined;
};

type AccountChangedEvent = {
  account?: AccountType;
};

const ClickContext = createContext<ClickContextState | undefined>(undefined);

type ClickProviderProps = {
  children: ReactNode;
};

export const ClickProvider = ({ children }: ClickProviderProps) => {
  const [connectedAccount, setConnectedAccount] = useState<AccountType | undefined>();
  const [clickRef, setClickRef] = useState<ICSPRClickSDK | undefined>();

  useEffect(() => {
    const checkActiveAccount = async (ref: ICSPRClickSDK) => {
      try {
        const account = await ref.getActiveAccountAsync({
          withBalance: true,
          withFiatCurrency: 'USD',
        });

        setConnectedAccount(account?.public_key ? account : undefined);
      } catch (error) {
        console.error('Failed to get active account', error);
        setConnectedAccount(undefined);
      }
    };

    const handleAccountChanged = (event: AccountChangedEvent) => {
      const account = event.account;
      setConnectedAccount(account?.public_key ? account : undefined);
    };

    const handleSdkLoaded = () => {
      const ref = window.csprclick;

      if (!ref) {
        return;
      }

      setClickRef(ref);
      ref.on('csprclick:signed_in', handleAccountChanged);
      ref.on('csprclick:switched_account', handleAccountChanged);
      ref.on('csprclick:unsolicited_account_change', handleAccountChanged);
      ref.on('csprclick:signed_out', () => setConnectedAccount(undefined));
      checkActiveAccount(ref);
    };

    window.addEventListener('csprclick:loaded', handleSdkLoaded);

    if (window.csprclick) {
      handleSdkLoaded();
    }

    if (!document.querySelector('script#csprclick-client')) {
      const script = document.createElement('script');
      script.src = 'https://cdn.cspr.click/ui/v2.1.0/csprclick-client-2.1.0.js';
      script.id = 'csprclick-client';
      script.async = true;
      document.head.appendChild(script);
    }

    return () => {
      window.removeEventListener('csprclick:loaded', handleSdkLoaded);
    };
  }, []);

  return (
    <ClickContext.Provider
      value={{
        publicKey: connectedAccount?.public_key,
        provider: connectedAccount?.provider,
        clickRef,
      }}
    >
      {children}
    </ClickContext.Provider>
  );
};

export const useClickRef = (): ClickContextState => {
  const context = useContext(ClickContext);

  if (!context) {
    throw new Error('useClickRef must be used within a ClickProvider');
  }

  return context;
};

Add the UI container

The CDN runtime still needs a DOM element where it can mount the CSPR.click top bar and modal UI. Add this container to your index.html, before the React root element.

The container id must match the uiContainer value configured in window.clickUIOptions.

Wrap your application

Wrap your application with ClickProvider so components can access the SDK reference and account state.

Use the SDK from a component

Call useClickRef() from any component rendered inside the provider. The clickRef value is available after the CDN runtime has loaded.

What's next

After the provider is in place, continue with the shared integration steps:

Last updated