Skip to content
Snippets Groups Projects
use-polkadot-extension.ts 2.86 KiB
Newer Older
Niklas P's avatar
Niklas P committed
import {
  InjectedAccountWithMeta,
  InjectedExtension,
} from "@polkadot/extension-inject/types";
import { useEffect, useState } from "react";
import { documentReadyPromise } from "./utils";
Niklas P's avatar
Niklas P committed

Niklas P's avatar
Niklas P committed
export interface UsePolkadotExtensionReturnType {
  isReady: boolean;
  accounts: InjectedAccountWithMeta[] | null;
  error: Error | null;
  injector: InjectedExtension | null;
  actingAccount: InjectedAccountWithMeta | null;
  setActingAccountIdx: (idx: number) => void;
}

export const usePolkadotExtension = (): UsePolkadotExtensionReturnType => {
  const [isReady, setIsReady] = useState(false);
  const [accounts, setAccounts] = useState<InjectedAccountWithMeta[] | null>(
    null
  );
  const [extensions, setExtensions] = useState<InjectedExtension[] | null>(
    null
  );
  const [actingAccountIdx, setActingAccountIdx] = useState<number>(0);
  const [error, setError] = useState<Error | null>(null);
  const [injector, setInjector] = useState<InjectedExtension | null>(null);

  const actingAccount = accounts && accounts[actingAccountIdx];

  useEffect(() => {
Niklas P's avatar
Niklas P committed
    // This effect is used to setup the browser extension
    const extensionSetup = async () => {
Niklas P's avatar
Niklas P committed
      const extensionDapp = await import("@polkadot/extension-dapp");
Niklas P's avatar
Niklas P committed
      const { web3AccountsSubscribe, web3Enable } = extensionDapp;
Niklas P's avatar
Niklas P committed

      const injectedPromise = documentReadyPromise(() =>
Niklas P's avatar
Niklas P committed
        web3Enable("Polkadot Tokengated Website Demo")
Niklas P's avatar
Niklas P committed
      );
      const extensions = await injectedPromise;

      setExtensions(extensions);

      if (extensions.length === 0) {
        console.log("no extension");
        return;
Niklas P's avatar
Niklas P committed
      }
Niklas P's avatar
Niklas P committed

      if (accounts) {
        setIsReady(true);
      } else {
        let unsubscribe: () => void;

        // we subscribe to any account change
        // note that `web3AccountsSubscribe` returns the function to unsubscribe
        unsubscribe = await web3AccountsSubscribe((injectedAccounts) => {
          setAccounts(injectedAccounts);
        });

        return () => unsubscribe && unsubscribe();
      }
    };

    if (!isReady) {
Niklas P's avatar
Niklas P committed
      extensionSetup();
Niklas P's avatar
Niklas P committed
    }
Niklas P's avatar
Niklas P committed
  }, [extensions]);
Niklas P's avatar
Niklas P committed

  useEffect(() => {
Niklas P's avatar
Niklas P committed
    // This effect is used to get the injector from the selected account
    // and is triggered when the accounts or the actingAccountIdx change
Niklas P's avatar
Niklas P committed
    const getInjector = async () => {
      const { web3FromSource } = await import("@polkadot/extension-dapp");
      const actingAccount =
        accounts && actingAccountIdx !== undefined
          ? accounts[actingAccountIdx]
          : undefined;
      if (actingAccount?.meta.source) {
        try {
          const injector = await web3FromSource(actingAccount?.meta.source);
          setInjector(injector);
        } catch (e: any) {
          setError(e);
Niklas P's avatar
Niklas P committed
        }
Niklas P's avatar
Niklas P committed
      }
    };

    getInjector();
  }, [actingAccountIdx, accounts]);

  return {
    accounts,
    actingAccount,
    setActingAccountIdx,
    isReady,
    error,
    injector,
  };
};