@headlessui/react#Disclosure TypeScript Examples

The following examples show how to use @headlessui/react#Disclosure. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Accordion.tsx    From yet-another-generic-startpage with MIT License 6 votes vote down vote up
Accordion = ({
  header,
  buttonLabel,
  defaultOpen,
  children,
}: PropsWithChildren<AccordionProps>) => (
  <Disclosure defaultOpen={defaultOpen}>
    {({ open }) => (
      <>
        <HeaderButton open={open} label={buttonLabel}>
          {header}
        </HeaderButton>
        <Panel>{children}</Panel>
      </>
    )}
  </Disclosure>
)
Example #2
Source File: HeaderButton.tsx    From yet-another-generic-startpage with MIT License 6 votes vote down vote up
DivButton = ({
  label,
  ...delegated
}: PropsWithChildren<DivButtonProps>) => (
  <Disclosure.Button
    as="div"
    role="button"
    aria-label={`Expand ${label || "accordion"}`}
    tabIndex={0}
    {...delegated}
  />
)
Example #3
Source File: MessageDocs.tsx    From contracts-ui with GNU General Public License v3.0 6 votes vote down vote up
MessageDocs = ({ message, message: { docs } }: Props) => {
  return (
    <Disclosure defaultOpen>
      {({ open }) => (
        <div className="collapsible-panel">
          <Disclosure.Button className="panel-title text-xs leading-normal text-left p-3 dark:bg-elevation-1 text-mono flex w-full">
            <ChevronUpIcon
              className={`${open ? 'transform rotate-180' : ''} w-5 h-5 mr-1 border-gray-500`}
            />
            <MessageSignature message={message} />
          </Disclosure.Button>
          <Disclosure.Panel className="panel-body p-4 markdown border-t dark:border-gray-700 border-gray-200">
            {/* eslint-disable-next-line react/no-children-prop */}
            {docs.length ? (
              <ReactMarkdown remarkPlugins={[remarkGfm]}>{docs.join('\r\n')}</ReactMarkdown>
            ) : (
              <i>No documentation provided</i>
            )}
          </Disclosure.Panel>
        </div>
      )}
    </Disclosure>
  );
}
Example #4
Source File: Panel.ts    From yet-another-generic-startpage with MIT License 5 votes vote down vote up
Panel = styled(Disclosure.Panel)`
  ${({ theme: { space } }) => css`
    padding: ${space.medium} 0 ${space.medium} ${space.largest};
  `}
`
Example #5
Source File: DropdownFilter.tsx    From po8klasie with GNU General Public License v3.0 5 votes vote down vote up
MobileDropdownFilter: FC<DropdownFilterProps> = ({
  onChange,
  value,
  options: { title, choices, isMultipleChoice },
}) => {
  const { selected, selectItem } = useSelected(value as [], !!isMultipleChoice);

  useEffect(() => {
    onChange(selected);
  }, [selected])

  return (
    <div className="border-b border-light">
    <Disclosure>
      {({ open }) => (
        <>
          <Disclosure.Button className="flex w-full justify-between px-2 py-2">
            <span>{title}</span>
            <MdExpandMore className={`text-2xl text-primary transition transform ${open ? 'rotate-180' : ''}`} />
          </Disclosure.Button>
          <Disclosure.Panel className="px-2">
            <ul className="">
              {choices.map((choice: DropdownChoice) => (
                <li
                  className={
                  `rounded-lg bg-opacity-50 my-2 px-2 py-2 flex items-center border-2 border-light transition
                  ${ selected.includes(choice.value) ? 'bg-light' : ''}`
                  }
                  onClick={() => selectItem(choice.value)}
                  key={choice.value}
                >
                  <MdCheck className={
                    `mr-2 transition text-primary ${selected.includes(choice.value) ? 'opacity-100' : 'opacity-0'}`
                  } /> {choice.label}
                </li>
              ))}
            </ul>
          </Disclosure.Panel>
        </>
      )}
    </Disclosure>
    </div>
  )
}
Example #6
Source File: Accordion.tsx    From ui with MIT License 5 votes vote down vote up
export function Item({ children, className, label, id }: ItemProps) {
  const { defaultActiveId, icon, iconPosition, onChange } =
    useContext(AccordionContext)

  let panelClasses = [AccordionStyles['sbui-accordion-item__panel']]

  let buttonClasses = [AccordionStyles['sbui-accordion-item__button']]
  if (className) {
    buttonClasses.push(className)
  }

  const isDefaultActive = id ? defaultActiveId?.includes(id) : false

  const handleOnChange = useCallback(
    (open: boolean) => () => {
      if (onChange) {
        onChange({ id, label, open })
      }
    },
    [onChange, id, label]
  )

  return (
    <Disclosure defaultOpen={isDefaultActive}>
      {({ open }) => (
        <>
          <Disclosure.Button
            className={
              open
                ? `${buttonClasses.join(' ')} sbui-accordion-item__button--open`
                : buttonClasses.join(' ')
            }
          >
            {iconPosition === 'left' && icon}
            <Typography.Text>{label}</Typography.Text>
            {iconPosition === 'right' && icon}
          </Disclosure.Button>
          <Transition
            show={open}
            enter={AccordionStyles[`sbui-accordion-item__panel--enter`]}
            enterFrom={AccordionStyles[`sbui-accordion-item__panel--enterFrom`]}
            enterTo={AccordionStyles[`sbui-accordion-item__panel--enterTo`]}
            leave={AccordionStyles[`sbui-accordion-item__panel--leave`]}
            leaveFrom={AccordionStyles[`sbui-accordion-item__panel--leaveFrom`]}
            leaveTo={AccordionStyles[`sbui-accordion-item__panel--leaveTo`]}
            afterEnter={handleOnChange(open)}
            afterLeave={handleOnChange(open)}
          >
            <Disclosure.Panel className={panelClasses.join(' ')} static>
              {children}
            </Disclosure.Panel>
          </Transition>
        </>
      )}
    </Disclosure>
  )
}
Example #7
Source File: header.tsx    From arkadiko with GNU General Public License v3.0 4 votes vote down vote up
Header: React.FC<HeaderProps> = ({ signOut, setShowSidebar }) => {
  const [state, _] = useContext(AppContext);
  const showWallet = process.env.REACT_APP_SHOW_CONNECT_WALLET === 'true';
  const { doOpenAuth } = useConnect();
  const name = bnsName();
  const contractAddress = process.env.REACT_APP_CONTRACT_ADDRESS || '';
  const [isVotingOpen, setisVotingOpen] = useState(false);

  useEffect(() => {
    let mounted = true;

    const getData = async () => {
      const proposals = await callReadOnlyFunction({
        contractAddress,
        contractName: 'arkadiko-governance-v3-1',
        functionName: 'get-proposals',
        functionArgs: [],
        senderAddress: contractAddress,
        network: network,
      });
      const json = cvToJSON(proposals);
      const data = json.value.value;

      setisVotingOpen(data.some(item => item.value["is-open"].value));
    };


    if (mounted) {
      void getData();
    }

    return () => {
      mounted = false;
    };
  }, []);

  return (
    <Disclosure as="nav" className="relative sticky top-0 z-50 bg-white shadow dark:bg-zinc-900">
      {({ open }) => (
        <>
          <div className="px-4 px-6 mx-auto max-w-7xl lg:px-8">
            <div className="flex justify-between h-16">
              <div className="flex justify-between flex-1">
                <RouterLink className="flex items-center shrink-0" to="/">
                  <svg
                    className="w-auto h-6 lg:block sm:h-8 text-zinc-900 dark:text-white"
                    viewBox="0 0 60 46"
                    xmlns="http://www.w3.org/2000/svg"
                  >
                    <path
                      fillRule="evenodd"
                      clipRule="evenodd"
                      d="M19.03 1.54A2.68 2.68 0 0121.46 0h11.48c.95 0 1.82.49 2.3 1.29L59.62 41.6c.5.82.5 1.84.03 2.66a2.69 2.69 0 01-2.33 1.34h-12a2.7 2.7 0 01-1.9-.77 31.32 31.32 0 00-16.15-8.17c-6.8-1.09-14.81.4-22.7 8.17a2.71 2.71 0 01-3.42.3 2.62 2.62 0 01-.9-3.28L19.02 1.54zm7.1 3.75L46.86 40.3h5.74L31.42 5.3h-5.29zm10.89 28.89L21.75 8.37 9.55 34.55a29.17 29.17 0 0118.58-3.1c3.2.5 6.2 1.5 8.89 2.73z"
                      fill="currentColor"
                    />
                  </svg>

                  <span className="inline-block ml-2 text-lg font-bold align-middle font-headings text-zinc-900 dark:text-zinc-100">
                    Arkadiko
                  </span>
                </RouterLink>
                {state.userData ? (
                  <div className="hidden lg:ml-6 lg:flex lg:space-x-6">
                    <RouterLink
                      to="/swap"
                      className="inline-flex items-center px-1 pt-1 text-sm font-medium text-gray-500 border-b-2 border-transparent dark:text-zinc-100 hover:border-gray-300 hover:text-gray-700"
                      activeClassName="border-indigo-500 text-gray-900"
                    >
                      Swap
                    </RouterLink>

                    <RouterLink
                      to="/vaults"
                      className="inline-flex items-center px-1 pt-1 text-sm font-medium text-gray-500 border-b-2 border-transparent dark:text-zinc-100 hover:border-gray-300 hover:text-gray-700"
                      activeClassName="border-indigo-500 text-gray-900"
                    >
                      Borrow
                    </RouterLink>

                    <RouterLink
                      to="/stake"
                      className="inline-flex items-center px-1 pt-1 text-sm font-medium text-gray-500 border-b-2 border-transparent dark:text-zinc-100 hover:border-gray-300 hover:text-gray-700"
                      activeClassName="border-indigo-500 text-gray-900"
                    >
                      Stake
                    </RouterLink>

                    <RouterLink
                      to="/liquidations"
                      exact
                      className="inline-flex items-center px-1 pt-1 text-sm font-medium text-gray-500 border-b-2 border-transparent dark:text-zinc-100 hover:border-gray-300 hover:text-gray-700"
                      activeClassName="border-indigo-500 text-gray-900"
                    >
                      Liquidations
                    </RouterLink>

                    <RouterLink
                      to="/governance"
                      className="inline-flex items-center px-1 pt-1 text-sm font-medium text-gray-500 border-b-2 border-transparent dark:text-zinc-100 hover:border-gray-300 hover:text-gray-700"
                      activeClassName="border-indigo-500 text-gray-900"
                    >
                      {isVotingOpen ? (
                        <Tooltip
                          label="A vote is in progress. Check it out and have a say in the future of the protocol!"
                          shouldWrapChildren={true}
                          className="z-50"
                        >
                          <span className="relative flex w-2 h-2 mr-2">
                            <span className="absolute inline-flex w-full h-full bg-indigo-400 rounded-full opacity-75 animate-ping dark:bg-indigo-300"></span>
                            <span className="relative inline-flex w-2 h-2 bg-indigo-500 rounded-full dark:bg-indigo-300"></span>
                          </span>
                        </Tooltip>
                      ) : null}
                      Governance
                    </RouterLink>

                    <button
                      type="button"
                      className="block px-1 text-sm font-medium text-gray-500 dark:text-white hover:text-gray-700 "
                      onClick={() => {
                        setShowSidebar(true);
                      }}
                    >
                      <span className="inline-block w-3 h-3 pt-2 mr-2 bg-green-400 border-2 border-white rounded-full"></span>
                      {shortAddress(name)}
                    </button>

                    <button
                      type="button"
                      className="block px-1 text-sm font-medium text-indigo-500 hover:text-indigo-800 dark:text-indigo-300 dark:hover:text-indigo-200"
                      onClick={() => {
                        signOut();
                      }}
                    >
                      Sign out
                    </button>

                    <ColorThemeToggle />
                  </div>
                ) : (
                  <div className="hidden lg:ml-6 lg:flex lg:space-x-6 lg:items-center">
                    {showWallet ? (
                      <div>
                        <button
                          type="button"
                          className="relative inline-flex items-center px-4 py-2 text-sm font-medium text-white bg-indigo-600 border border-transparent rounded-md shadow-sm hover:bg-indigo-700 "
                          onClick={() => doOpenAuth()}
                        >
                          <span>Connect Wallet</span>
                        </button>
                      </div>
                    ) : null}

                    <ColorThemeToggle />
                  </div>
                )}
              </div>
              <div className="flex items-center -mr-2 lg:hidden">
                <Disclosure.Button className="inline-flex items-center justify-center p-2 text-gray-400 rounded-md hover:text-gray-500 dark:text-white hover:bg-zinc-100 dark:hover:bg-zinc-700">
                  <span className="sr-only">Open main menu</span>
                  {open ? (
                    <StyledIcon as="XIcon" size={6} solid={false} className="block" />
                  ) : (
                    <StyledIcon as="MenuIcon" size={6} solid={false} className="block" />
                  )}
                </Disclosure.Button>
              </div>
            </div>
          </div>

          <Disclosure.Panel className="lg:hidden">
            {state.userData ? (
              <div>
                <div className="pt-2 pb-3 space-y-1">
                  <Disclosure.Button
                    as={RouterLink}
                    to="/swap"
                    className="block py-2 pl-3 pr-4 text-base font-medium text-gray-500 border-l-4 border-transparent dark:text-zinc-100 hover:bg-gray-50 hover:border-gray-300 hover:text-gray-700 dark:hover:bg-zinc-700"
                    activeClassName="border-indigo-500 text-gray-900"
                  >
                    Swap
                  </Disclosure.Button>

                  <Disclosure.Button
                    as={RouterLink}
                    to="/vaults"
                    className="block py-2 pl-3 pr-4 text-base font-medium text-gray-500 border-l-4 border-transparent dark:text-zinc-100 hover:bg-gray-50 hover:border-gray-300 hover:text-gray-700 dark:hover:bg-zinc-700"
                    activeClassName="border-indigo-500 text-gray-900"
                  >
                    Borrow
                  </Disclosure.Button>

                  <Disclosure.Button
                    as={RouterLink}
                    to="/stake"
                    className="block py-2 pl-3 pr-4 text-base font-medium text-gray-500 border-l-4 border-transparent dark:text-zinc-100 hover:bg-gray-50 hover:border-gray-300 hover:text-gray-700 dark:hover:bg-zinc-700"
                    activeClassName="border-indigo-500 text-gray-900"
                  >
                    Stake
                  </Disclosure.Button>

                  <Disclosure.Button
                    as={RouterLink}
                    to="/liquidations"
                    className="block py-2 pl-3 pr-4 text-base font-medium text-gray-500 border-l-4 border-transparent dark:text-zinc-100 hover:bg-gray-50 hover:border-gray-300 hover:text-gray-700 dark:hover:bg-zinc-700"
                    activeClassName="border-indigo-500 text-gray-900"
                  >
                    Liquidations
                  </Disclosure.Button>

                  <Disclosure.Button
                    as={RouterLink}
                    to="/governance"
                    className="flex items-center flex-1 py-2 pl-3 pr-4 text-base font-medium text-gray-500 border-l-4 border-transparent dark:text-zinc-100 hover:bg-gray-50 hover:border-gray-300 hover:text-gray-700 dark:hover:bg-zinc-700"
                    activeClassName="border-indigo-500 text-gray-900"
                  >
                    {isVotingOpen ? (
                      <Tooltip
                        label="A vote is in progress. Check it out and have a say in the future of the protocol!"
                        shouldWrapChildren={true}
                        className="z-50"
                      >
                        <span className="relative flex w-2 h-2 mr-2">
                          <span className="absolute inline-flex w-full h-full bg-indigo-400 rounded-full opacity-75 animate-ping dark:bg-indigo-300"></span>
                          <span className="relative inline-flex w-2 h-2 bg-indigo-500 rounded-full dark:bg-indigo-300"></span>
                        </span>
                      </Tooltip>
                    ) : null}
                    Governance
                  </Disclosure.Button>
                </div>
                <div className="pt-4 pb-3 border-t border-gray-300 dark:border-zinc-600">
                  <div className="space-y-1">
                    <button
                      type="button"
                      className="block w-full px-4 py-2 text-base font-medium text-left text-gray-500 dark:text-white hover:text-gray-800 hover:bg-gray-100 sm:px-6 dark:hover:bg-zinc-700"
                      onClick={() => {
                        setShowSidebar(true);
                      }}
                    >
                      <span className="inline-block w-3 h-3 pt-2 mr-2 bg-green-400 border-2 border-white rounded-full"></span>
                      {shortAddress(name)}
                    </button>

                    <button
                      type="button"
                      className="block w-full px-4 py-2 text-base font-medium text-left text-indigo-500 hover:text-indigo-800 hover:bg-indigo-100 sm:px-6"
                      onClick={() => {
                        signOut();
                      }}
                    >
                      Sign out
                    </button>

                    <ColorThemeToggle classes="block w-full px-4 py-2 sm:px-6" />
                  </div>
                </div>
              </div>
            ) : (
              <div>
                <div className="p-3 border-t border-gray-200">
                  {showWallet ? (
                    <button
                      type="button"
                      className="relative inline-flex items-center justify-center w-full px-4 py-2 text-sm font-medium text-white bg-indigo-600 border border-transparent rounded-md shadow-sm hover:bg-indigo-700 focus:focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
                      onClick={() => doOpenAuth()}
                    >
                      <span>Connect Wallet</span>
                    </button>
                  ) : null}
                </div>

                <ColorThemeToggle classes="block w-full px-4 py-2 sm:px-6" />
              </div>
            )}
          </Disclosure.Panel>
        </>
      )}
    </Disclosure>
  );
}
Example #8
Source File: pool-position.tsx    From arkadiko with GNU General Public License v3.0 4 votes vote down vote up
PoolPosition: React.FC = ({ indexTokenX, indexTokenY, canAdd }) => {
  const tokenX = tokenList[indexTokenX];
  const tokenY = tokenList[indexTokenY];
  const tokenXTrait = tokenTraits[tokenX['name'].toLowerCase()]['swap'];
  const tokenXAddress = tokenTraits[tokenX['name'].toLowerCase()]['address'];
  const tokenYTrait = tokenTraits[tokenY['name'].toLowerCase()]['swap'];
  const tokenYAddress = tokenTraits[tokenY['name'].toLowerCase()]['address'];
  const contractAddress = process.env.REACT_APP_CONTRACT_ADDRESS || '';
  const stxAddress = useSTXAddress();

  const [state] = useContext(AppContext);
  const [tokenPair, setTokenPair] = useState('');
  const [pooledX, setPooledX] = useState(0.0);
  const [pooledY, setPooledY] = useState(0.0);
  const [totalShare, setTotalShare] = useState(0);
  const [stakedLpTokens, setStakedLpTokens] = useState(0);
  const [isLoading, setIsLoading] = useState(true);
  const [isOpen, setIsOpen] = useState(false);

  const fetchPair = async (
    tokenXAddress: string,
    tokenXContract: string,
    tokenYAddress: string,
    tokenYContract: string
  ) => {
    const details = await callReadOnlyFunction({
      contractAddress,
      contractName: 'arkadiko-swap-v2-1',
      functionName: 'get-pair-details',
      functionArgs: [
        contractPrincipalCV(tokenXAddress, tokenXContract),
        contractPrincipalCV(tokenYAddress, tokenYContract),
      ],
      senderAddress: stxAddress || '',
      network: network,
    });
    return cvToJSON(details);
  };

  const fetchStakedTokens = async (poolName: string) => {
    let poolContract = '';
    if (poolName == 'wSTX-DIKO') {
      poolContract = 'arkadiko-stake-pool-wstx-diko-v1-1';
    } else if (poolName == 'wSTX-USDA') {
      poolContract = 'arkadiko-stake-pool-wstx-usda-v1-1';
    } else if (poolName == 'DIKO-USDA') {
      poolContract = 'arkadiko-stake-pool-diko-usda-v1-1';
    } else if (poolName == 'wSTX-xBTC') {
      poolContract = 'arkadiko-stake-pool-wstx-xbtc-v1-1';
    } else if (poolName === 'xBTC-USDA') {
      poolContract = 'arkadiko-stake-pool-xbtc-usda-v1-1';
    }
    if (poolContract == '') {
      return 0;
    }

    const userLpDikoUsdaStakedCall = await callReadOnlyFunction({
      contractAddress,
      contractName: poolContract,
      functionName: 'get-stake-amount-of',
      functionArgs: [standardPrincipalCV(stxAddress || '')],
      senderAddress: stxAddress || '',
      network: network,
    });
    return cvToJSON(userLpDikoUsdaStakedCall).value;
  };

  const resolvePair = async () => {
    const json3 = await fetchPair(tokenXAddress, tokenXTrait, tokenYAddress, tokenYTrait);
    if (json3['success']) {
      const pairDetails = json3['value']['value']['value'];
      const stakedTokens = await fetchStakedTokens(pairDetails['name'].value);
      setStakedLpTokens(stakedTokens);

      const balanceX = pairDetails['balance-x'].value;
      const balanceY = pairDetails['balance-y'].value;

      const tokenPair = `${tokenX.nameInPair.toLowerCase()}${tokenY.nameInPair.toLowerCase()}`;
      const totalTokens = pairDetails['shares-total'].value;
      const tokenXYBalance = Number(state.balance[tokenPair]) + Number(stakedTokens);

      // to make sure data is loaded properly
      if (state.balance[tokenPair] == undefined) {
        return;
      }

      setTokenPair(tokenPair);

      let totalShare = tokenXYBalance / totalTokens;
      if (totalShare > 100) {
        totalShare = 100;
      }
      const totalBalanceX = balanceX * totalShare;
      const totalBalanceY = balanceY * totalShare;

      setPooledX(totalBalanceX / Math.pow(10, tokenX['decimals']));
      setPooledY(totalBalanceY / Math.pow(10, tokenY['decimals']));
      console.log(totalBalanceX, totalBalanceY);

      setTotalShare(Number((totalShare * 100).toFixed(5)));
      setIsLoading(false);
    }
  };

  const loadData = async () => {
    const open = !isOpen;
    setIsOpen(open);
    if (open && isLoading) {
      resolvePair();
    }
  };

  return (
    <Disclosure as="div" key={''} className="" onClick={() => loadData()}>
      {({ open }) => (
        <>
          <dt className="text-lg">
            <Disclosure.Button className="flex items-start justify-between w-full text-left text-gray-400">
              <div className="flex items-center">
                <div className="flex -space-x-2 shrink-0">
                  <img
                    className="inline-block w-8 h-8 rounded-full ring-2 ring-white dark:ring-zinc-800 shrink-0"
                    src={tokenX.logo}
                    alt=""
                  />
                  <img
                    className="inline-block w-8 h-8 rounded-full ring-2 ring-white dark:ring-zinc-800 shrink-0"
                    src={tokenY.logo}
                    alt=""
                  />
                </div>
                <p className="ml-3 text-base text-gray-800 dark:text-zinc-100">
                  {tokenX.name}/{tokenY.name}
                </p>
              </div>
              <span className="flex items-center ml-6 h-7">
                <StyledIcon
                  as="ChevronDownIcon"
                  size={6}
                  className={classNames(open ? '-rotate-180' : 'rotate-0', 'transform')}
                />
              </span>
            </Disclosure.Button>
          </dt>
          <Disclosure.Panel as="dd" className="mt-2">
            <div className="w-full p-4 mt-4 border border-indigo-200 rounded-lg shadow-sm bg-indigo-50 dark:bg-indigo-200">
              <h4 className="text-xs text-indigo-700 uppercase font-headings">Pool share</h4>

              <dl className="mt-2 space-y-1">
                <div className="sm:grid sm:grid-cols-2 sm:gap-4">
                  <dt className="inline-flex items-center text-sm font-medium text-indigo-500 dark:text-indigo-700">
                    Available pool tokens
                    <div className="ml-2">
                      <Tooltip
                        className="z-10"
                        shouldWrapChildren={true}
                        label={`Indicates the total amount of LP tokens you have in your wallet`}
                      >
                        <StyledIcon
                          as="InformationCircleIcon"
                          size={4}
                          className="block text-indigo-400 dark:text-indigo-500"
                        />
                      </Tooltip>
                    </div>
                  </dt>
                  <dt className="mt-1 text-sm font-semibold text-indigo-900 sm:mt-0 sm:text-right">
                    {isLoading ? (
                      <Placeholder className="justify-end" width={Placeholder.width.HALF} />
                    ) : (
                      <>
                        {state.balance[tokenPair] > 0 ? `${state.balance[tokenPair] / 1000000}` : 0}
                      </>
                    )}
                  </dt>
                </div>

                <div className="sm:grid sm:grid-cols-2 sm:gap-4">
                  <dt className="inline-flex items-center text-sm font-medium text-indigo-500 dark:text-indigo-700">
                    Staked pool tokens
                    <div className="ml-2">
                      <Tooltip
                        className="z-10"
                        shouldWrapChildren={true}
                        label={`Indicates the total amount of LP tokens you have staked`}
                      >
                        <StyledIcon
                          as="InformationCircleIcon"
                          size={4}
                          className="block text-indigo-400 dark:text-indigo-500"
                        />
                      </Tooltip>
                    </div>
                  </dt>
                  <dt className="mt-1 text-sm font-semibold text-indigo-900 sm:mt-0 sm:text-right">
                    {isLoading ? (
                      <Placeholder className="justify-end" width={Placeholder.width.THIRD} />
                    ) : (
                      <>{stakedLpTokens > 0 ? `${stakedLpTokens / 1000000}` : 0}</>
                    )}
                  </dt>
                </div>
              </dl>

              <dl className="mt-4 space-y-1">
                <div className="sm:grid sm:grid-cols-2 sm:gap-4">
                  <dt className="inline-flex items-center text-sm font-medium text-indigo-500 dark:text-indigo-700">
                    Your pool share
                    <div className="ml-2">
                      <Tooltip
                        className="z-10"
                        shouldWrapChildren={true}
                        label={`The percentual share of LP tokens you own against the whole pool supply`}
                      >
                        <StyledIcon
                          as="InformationCircleIcon"
                          size={4}
                          className="block text-indigo-400 dark:text-indigo-500"
                        />
                      </Tooltip>
                    </div>
                  </dt>
                  <dd className="mt-1 text-sm font-semibold text-indigo-900 sm:mt-0 sm:text-right">
                    {isLoading ? (
                      <Placeholder className="justify-end" width={Placeholder.width.HALF} />
                    ) : (
                      <>{totalShare}%</>
                    )}
                  </dd>
                </div>

                <div className="sm:grid sm:grid-cols-2 sm:gap-4">
                  <dt className="inline-flex items-center text-sm font-medium text-indigo-500 dark:text-indigo-700">
                    Pooled {tokenX.name}
                  </dt>
                  <dd className="mt-1 text-sm font-semibold text-indigo-900 sm:mt-0 sm:text-right">
                    {isLoading ? (
                      <Placeholder className="justify-end" width={Placeholder.width.THIRD} />
                    ) : (
                      <>
                        {pooledX.toLocaleString(undefined, {
                          minimumFractionDigits: 2,
                          maximumFractionDigits: 6,
                        })}
                      </>
                    )}
                  </dd>
                </div>

                <div className="sm:grid sm:grid-cols-2 sm:gap-4">
                  <dt className="inline-flex items-center text-sm font-medium text-indigo-500 dark:text-indigo-700">
                    Pooled {tokenY.name}
                  </dt>
                  <dd className="mt-1 text-sm font-semibold text-indigo-900 sm:mt-0 sm:text-right">
                    {isLoading ? (
                      <Placeholder className="justify-end" width={Placeholder.width.HALF} />
                    ) : (
                      <>
                        {pooledY.toLocaleString(undefined, {
                          minimumFractionDigits: 2,
                          maximumFractionDigits: 6,
                        })}
                      </>
                    )}
                  </dd>
                </div>
              </dl>
            </div>

            <div className="my-4">
              <Alert>
                <p>
                  In order to remove liquidity and make the LP tokens available again, keep in mind
                  that you must first{' '}
                  <RouterLink
                    className="font-semibold text-blue-700 underline whitespace-nowrap hover:text-blue-600"
                    to={'/stake'}
                  >
                    unstake them
                  </RouterLink>
                  .
                </p>
              </Alert>
            </div>

            <div className="grid grid-flow-row-dense grid-cols-2 gap-2 mt-4">
              <RouterLink
                className="inline-flex justify-center px-4 py-2 text-sm font-medium bg-white border border-gray-300 rounded-md shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
                to={`swap/remove/${tokenX.name}/${tokenY.name}`}
              >
                Remove
              </RouterLink>
              {canAdd ? (
                <RouterLink
                  className="inline-flex justify-center px-4 py-2 text-sm font-medium text-white bg-indigo-600 border border-transparent rounded-md shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
                  to={`swap/add/${tokenX.name}/${tokenY.name}`}
                >
                  Add
                </RouterLink>
              ) : null}
            </div>
          </Disclosure.Panel>
        </>
      )}
    </Disclosure>
  );
}
Example #9
Source File: stake-lp-row.tsx    From arkadiko with GNU General Public License v3.0 4 votes vote down vote up
StakeLpRow: React.FC<StakeLpRowProps> = ({
  loadingApy,
  loadingData,
  canStake,
  tokenListItemX,
  tokenListItemY,
  balance,
  pendingRewards,
  stakedAmount,
  apy,
  poolInfo,
  setShowStakeLpModal,
  setShowUnstakeLpModal,
  claimLpPendingRewards,
  stakeLpPendingRewards,
  getLpRoute,
}) => {
  return (
    <Disclosure as="tbody" className="bg-white dark:bg-zinc-800">
      {({ open }) => (
        <>
          <tr className="bg-white dark:bg-zinc-800">
            <td className="px-6 py-4 text-sm whitespace-nowrap">
              <div className="flex flex-wrap items-center flex-1 sm:flex-nowrap">
                <div className="flex -space-x-2 shrink-0">
                  <img
                    className="inline-block w-8 h-8 rounded-full shrink-0 ring-2 ring-white dark:ring-zinc-800"
                    src={tokenList[tokenListItemX].logo}
                    alt=""
                  />
                  <img
                    className="inline-block w-8 h-8 rounded-full shrink-0 ring-2 ring-white dark:ring-zinc-800"
                    src={tokenList[tokenListItemY].logo}
                    alt=""
                  />
                </div>
                <p className="mt-2 sm:mt-0 sm:ml-4">
                  <span className="block text-gray-500 dark:text-zinc-400">
                    <Tooltip
                      shouldWrapChildren={true}
                      label={`ARKV1${tokenList[tokenListItemX].name}${tokenList[tokenListItemY].name}`}
                    >
                      Arkadiko V1
                      <br />
                      {tokenList[tokenListItemX].name}/{tokenList[tokenListItemY].name}
                    </Tooltip>
                  </span>
                </p>
              </div>
            </td>
            <td className="px-6 py-4 text-sm text-indigo-600 dark:text-indigo-400 whitespace-nowrap">
              {loadingApy ? (
                <Placeholder className="py-2" width={Placeholder.width.HALF} />
              ) : (
                `${apy}%`
              )}
            </td>

            <td className="px-6 py-4 whitespace-nowrap dark:text-white">
              {loadingData ? (
                <Placeholder className="py-2" width={Placeholder.width.HALF} />
              ) : (
                <>
                  <Tooltip
                    shouldWrapChildren={true}
                    label={`
                    ${microToReadable(poolInfo.walletTokenXAmount).toLocaleString(undefined, {
                      minimumFractionDigits: 2,
                      maximumFractionDigits: 6,
                    })} ${poolInfo.tokenX}
                    /
                    ${microToReadable(poolInfo.walletTokenYAmount).toLocaleString(undefined, {
                      minimumFractionDigits: 2,
                      maximumFractionDigits: 6,
                    })} ${poolInfo.tokenY}
                  `}
                  >
                    <div className="flex items-center">
                      <p className="font-semibold">
                        {microToReadable(balance).toLocaleString(undefined, {
                          minimumFractionDigits: 2,
                          maximumFractionDigits: 6,
                        })}{' '}
                        <span className="text-sm font-normal">LP</span>
                      </p>
                      <StyledIcon
                        as="InformationCircleIcon"
                        size={5}
                        className="inline ml-2 text-gray-400"
                      />
                    </div>
                  </Tooltip>
                  <p className="mt-1 text-sm">
                    ≈$
                    {microToReadable(poolInfo.walletValue).toLocaleString(undefined, {
                      minimumFractionDigits: 2,
                      maximumFractionDigits: 6,
                    })}
                  </p>
                </>
              )}
            </td>

            <td className="px-6 py-4 whitespace-nowrap dark:text-white">
              {loadingData ? (
                <Placeholder className="py-2" width={Placeholder.width.HALF} />
              ) : (
                <>
                  <Tooltip
                    shouldWrapChildren={true}
                    label={`
                    ${microToReadable(poolInfo.stakedTokenXAmount).toLocaleString(undefined, {
                      minimumFractionDigits: 2,
                      maximumFractionDigits: 6,
                    })} ${poolInfo.tokenX}
                    /
                    ${microToReadable(poolInfo.stakedTokenYAmount).toLocaleString(undefined, {
                      minimumFractionDigits: 2,
                      maximumFractionDigits: 6,
                    })} ${poolInfo.tokenY}
                  `}
                  >
                    <div className="flex items-center">
                      <p className="font-semibold">
                        {microToReadable(stakedAmount).toLocaleString(undefined, {
                          minimumFractionDigits: 2,
                          maximumFractionDigits: 6,
                        })}{' '}
                        <span className="text-sm font-normal">LP</span>
                      </p>
                      <StyledIcon
                        as="InformationCircleIcon"
                        size={5}
                        className="inline ml-2 text-gray-400"
                      />
                    </div>
                  </Tooltip>
                  <p className="mt-1 text-sm">
                    ≈$
                    {microToReadable(poolInfo.stakedValue).toLocaleString(undefined, {
                      minimumFractionDigits: 2,
                      maximumFractionDigits: 6,
                    })}
                  </p>
                </>
              )}
            </td>
            <td className="px-6 py-4 font-semibold whitespace-nowrap dark:text-white">
              {loadingData ? (
                <Placeholder className="py-2" width={Placeholder.width.HALF} />
              ) : (
                <>
                  {microToReadable(pendingRewards).toLocaleString(undefined, {
                    minimumFractionDigits: 2,
                    maximumFractionDigits: 6,
                  })}{' '}
                  <span className="text-sm font-normal">DIKO</span>
                </>
              )}
            </td>
            <td className="px-6 py-4 text-sm text-right whitespace-nowrap">
              <Disclosure.Button className="inline-flex items-center justify-center px-2 py-1 text-sm text-indigo-500 bg-white rounded-lg focus:outline-none focus-visible:ring focus-visible:ring-indigo-500 focus-visible:ring-opacity-75 dark:bg-zinc-800 dark:text-indigo-400">
                <span>Actions</span>
                <StyledIcon
                  as="ChevronUpIcon"
                  size={5}
                  className={`${
                    open ? '' : 'transform rotate-180 transition ease-in-out duration-300'
                  } ml-2`}
                />
              </Disclosure.Button>
            </td>
          </tr>
          <Disclosure.Panel as="tr" className="bg-gray-50 dark:bg-zinc-700">
            <td className="px-6 py-4 text-sm whitespace-nowrap">
              <RouterLink
                to={getLpRoute}
                className={`inline-flex items-center px-4 py-2 text-sm leading-4 border border-transparent rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 ${
                  balance > 0
                    ? 'text-indigo-700 bg-indigo-100 hover:bg-indigo-200'
                    : 'text-white bg-indigo-600 hover:bg-indigo-700'
                }`}
              >
                {balance > 0 ? `Add LP` : `Get LP`}
              </RouterLink>
            </td>
            <td className="px-6 py-4 text-sm whitespace-nowrap" />
            <td className="px-6 py-4 text-sm whitespace-nowrap">
              {loadingData ? (
                <Placeholder className="py-2" width={Placeholder.width.HALF} />
              ) : (
                <button
                  type="button"
                  className="inline-flex items-center px-4 py-2 text-sm leading-4 text-white bg-indigo-600 border border-transparent rounded-md shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 disabled:bg-gray-200 disabled:text-gray-500 disabled:cursor-not-allowed"
                  disabled={!canStake || balance == 0}
                  onClick={() => setShowStakeLpModal(true)}
                >
                  Stake LP
                </button>
              )}
            </td>
            <td className="px-6 py-4 text-sm whitespace-nowrap">
              {loadingData ? (
                <Placeholder className="py-2" width={Placeholder.width.HALF} />
              ) : (
                <button
                  type="button"
                  className="inline-flex items-center px-4 py-2 text-sm leading-4 text-indigo-700 bg-indigo-100 border border-transparent rounded-md hover:bg-indigo-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 disabled:bg-gray-100 disabled:text-gray-500 disabled:cursor-not-allowed"
                  disabled={stakedAmount == 0}
                  onClick={() => setShowUnstakeLpModal(true)}
                >
                  Unstake LP
                </button>
              )}
            </td>
            <td className="px-6 py-4 text-sm whitespace-nowrap">
              <div className="flex space-x-2">
                {loadingData ? (
                  <Placeholder className="py-2" width={Placeholder.width.HALF} />
                ) : (
                  <>
                    <button
                      type="button"
                      className="inline-flex items-center px-3 py-2 text-sm leading-4 text-indigo-700 bg-indigo-100 border border-transparent rounded-md hover:bg-indigo-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 disabled:bg-gray-100 disabled:text-gray-500 disabled:cursor-not-allowed"
                      disabled={pendingRewards == 0}
                      onClick={() => claimLpPendingRewards()}
                    >
                      Claim
                    </button>
                    <button
                      type="button"
                      className="inline-flex items-center px-3 py-2 text-sm leading-4 text-white bg-indigo-600 border border-transparent rounded-md shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 disabled:bg-gray-100 disabled:text-gray-500 disabled:cursor-not-allowed"
                      disabled={pendingRewards == 0}
                      onClick={() => stakeLpPendingRewards()}
                    >
                      Stake
                    </button>
                  </>
                )}
              </div>
            </td>
            <td className="px-6 py-4 text-sm whitespace-nowrap" />
          </Disclosure.Panel>
        </>
      )}
    </Disclosure>
  );
}
Example #10
Source File: tx-sidebar.tsx    From arkadiko with GNU General Public License v3.0 4 votes vote down vote up
TxSidebar = ({ showSidebar, setShowSidebar }) => {
  const address = useSTXAddress();
  const [isLoading, setIsLoading] = useState(true);
  const [transactions, setTransactions] = useState<JSX.Element[]>();
  const [pendingTransactions, setPendingTransactions] = useState<JSX.Element[]>();

  const [networks, setNetworks] = useState([]);
  const [selectedNetworkKey, setSelectedNetworkKey] = useState(
    JSON.parse(localStorage.getItem('arkadiko-stacks-node') || JSON.stringify(DEFAULT_NETWORKS[0]))
      .key
  );
  const selectedNetwork = networks.find(network => network.key === selectedNetworkKey);

  const [networkName, setNetworkName] = useState('');
  const [networkAddress, setNetworkAddress] = useState('');
  const [networkKey, setNetworkKey] = useState('');

  const onInputChange = (event: { target: { name: any; value: any } }) => {
    const value = event.target.value;
    if (event.target.name === 'networkName') {
      setNetworkName(value);
    } else if (event.target.name === 'networkAddress') {
      setNetworkAddress(value);
    } else if (event.target.name === 'networkKey') {
      setNetworkKey(value);
    }
  };

  const addNewNetwork = () => {
    const networks = JSON.parse(localStorage.getItem('arkadiko-stacks-nodes') || '[]');
    const network = {
      name: networkName,
      url: networkAddress,
      key: networkKey,
    };
    networks.push(network);
    localStorage.setItem('arkadiko-stacks-nodes', JSON.stringify(networks));
    setSelectedNetworkKey(network);
  };

  useEffect(() => {
    const network = JSON.parse(localStorage.getItem('arkadiko-stacks-node')) || networks[0];
    if (showSidebar && selectedNetwork['url'] != network['url']) {
      localStorage.setItem('arkadiko-stacks-node', JSON.stringify(selectedNetwork));
      window.location.reload();
    }
  }, [selectedNetwork]);

  useEffect(() => {
    let mounted = true;

    const fetchTransactions = async () => {
      if (mounted && address) {
        setIsLoading(true);
        const txs = await getAccountTransactions(address || '', CONTRACT_ADDRESS || '');
        let index = 0;
        const txMap = txs.map((tx: ContractCallTransaction) => {
          let status = 'error';
          if (tx.tx_status === 'success') {
            status = 'success';
          } else if (tx.tx_status === 'pending') {
            status = 'pending';
          }
          index += 1;
          return <ContractTransaction key={index} transaction={tx} status={status} />;
        });

        setTransactions(txMap);
        const pending = await getPendingTransactions(address || '', CONTRACT_ADDRESS || '');
        const pendingMap = pending.map((tx: MempoolContractCallTransaction) => {
          index += 1;
          return <ContractTransaction key={index} transaction={tx} status="pending" />;
        });
        setPendingTransactions(pendingMap);
        setIsLoading(false);
      }
    };

    const setAllNetworks = () => {
      const addedNetworks = JSON.parse(localStorage.getItem('arkadiko-stacks-nodes') || '[]');
      setNetworks(DEFAULT_NETWORKS.concat(addedNetworks));
    };

    setAllNetworks();
    if (showSidebar) {
      fetchTransactions();
    }
    return () => {
      mounted = false;
    };
  }, [showSidebar]);

  return (
    <Transition show={showSidebar} as={Fragment}>
      <Dialog
        as="div"
        className="fixed inset-0 z-50 overflow-hidden"
        onClose={() => {
          setShowSidebar(false);
        }}
      >
        <div className="absolute inset-0 overflow-hidden">
          <Transition.Child
            as={Fragment}
            enter="ease-in-out duration-500"
            enterFrom="opacity-0"
            enterTo="opacity-100"
            leave="ease-in-out duration-500"
            leaveFrom="opacity-100"
            leaveTo="opacity-0"
          >
            <Dialog.Overlay className="absolute inset-0 transition-opacity bg-gray-700 bg-opacity-50" />
          </Transition.Child>

          <div className="fixed inset-y-0 right-0 flex max-w-full pl-10">
            <Transition.Child
              as={Fragment}
              enter="transform transition ease-in-out duration-500 sm:duration-700"
              enterFrom="translate-x-full"
              enterTo="translate-x-0"
              leave="transform transition ease-in-out duration-500 sm:duration-700"
              leaveFrom="translate-x-0"
              leaveTo="translate-x-full"
            >
              <div className="w-screen max-w-md">
                <div className="flex flex-col h-full overflow-y-scroll bg-white shadow-xl dark:bg-zinc-800">
                  <div className="px-4 py-6 bg-indigo-700 sm:px-6">
                    <div className="flex items-start justify-between">
                      <Dialog.Title className="text-lg text-white font-headings">
                        Network Settings
                      </Dialog.Title>
                      <div className="flex items-center ml-3 h-7">
                        <button
                          type="button"
                          className="text-indigo-200 bg-indigo-700 rounded-md hover:text-white focus:outline-none focus:ring-2 focus:ring-white"
                          onClick={() => {
                            setShowSidebar(false);
                          }}
                        >
                          <span className="sr-only">Close panel</span>
                          <StyledIcon as="XIcon" size={6} solid={false} />
                        </button>
                      </div>
                    </div>
                    <div className="mt-1">
                      <p className="text-sm text-indigo-300">Switch between networks easily</p>
                    </div>
                  </div>
                  <div className="relative px-4 my-6 sm:px-6">
                    <div className="relative w-72">
                      <Listbox value={selectedNetworkKey} onChange={setSelectedNetworkKey}>
                        <Listbox.Button className="relative w-full py-2 pl-3 pr-10 text-left bg-white border border-gray-300 rounded-md shadow-sm cursor-default focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-zinc-900 dark:border-zinc-800">
                          <span className="block truncate dark:text-zinc-50">
                            {selectedNetwork?.name}
                          </span>
                          <span className="absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none">
                            <StyledIcon as="SelectorIcon" size={5} className="text-gray-400" />
                          </span>
                        </Listbox.Button>
                        <Transition
                          as={Fragment}
                          leave="transition ease-in duration-100"
                          leaveFrom="opacity-100"
                          leaveTo="opacity-0"
                        >
                          <Listbox.Options className="absolute right-0 w-full py-1 mt-1 overflow-auto text-base bg-white rounded-md shadow-lg dark:text-zinc-50 dark:bg-zinc-900 max-h-56 ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
                            {networks.map(network => (
                              <Listbox.Option
                                key={network.key}
                                value={network.key}
                                className={({ active }) =>
                                  `${active ? 'text-white bg-indigo-600' : 'text-gray-900'}
                              cursor-default select-none relative py-2 pl-10 pr-4`
                                }
                              >
                                {({ selected, active }) => (
                                  <div>
                                    <span
                                      className={`${
                                        selected ? 'font-semibold' : 'font-normal'
                                      } block truncate dark:text-zinc-50`}
                                    >
                                      {network.name} ({network.url})
                                    </span>
                                    {selected ? (
                                      <span
                                        className={`${active ? 'text-white' : 'text-indigo-600'}
                                      absolute inset-y-0 left-0 flex items-center pl-3`}
                                      >
                                        <StyledIcon as="CheckIcon" size={5} />
                                      </span>
                                    ) : null}
                                  </div>
                                )}
                              </Listbox.Option>
                            ))}
                          </Listbox.Options>
                        </Transition>
                      </Listbox>
                    </div>
                    <Disclosure>
                      {() => (
                        <>
                          <Disclosure.Button className="flex items-center px-3 py-2 mt-4 text-sm font-medium leading-4 text-white bg-indigo-600 border border-transparent rounded-md shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
                            <span>Add a network</span>
                          </Disclosure.Button>
                          <Disclosure.Panel className="p-4 mt-4 text-sm text-gray-700 bg-gray-100 rounded-md dark:bg-zinc-700 dark:text-zinc-100">
                            Use this form to add a new instance of the Stacks Blockchain API. Make
                            sure you review and trust the host before you add it.
                            <form className="mt-4">
                              <div className="flex flex-col">
                                <label
                                  htmlFor="name"
                                  className="block text-sm font-medium text-gray-500 dark:text-gray-300"
                                >
                                  Name
                                </label>
                                <div className="flex mt-1 rounded-md shadow-sm">
                                  <input
                                    value={networkName}
                                    onChange={onInputChange}
                                    type="text"
                                    name="networkName"
                                    id="networkName"
                                    className="flex-1 block w-full min-w-0 text-black border-gray-300 rounded-md focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
                                  />
                                </div>
                              </div>

                              <div className="flex flex-col mt-3">
                                <label
                                  htmlFor="address"
                                  className="block text-sm font-medium text-gray-500 dark:text-gray-300"
                                >
                                  Address (include https://)
                                </label>
                                <div className="flex mt-1 rounded-md shadow-sm">
                                  <input
                                    value={networkAddress}
                                    onChange={onInputChange}
                                    type="text"
                                    name="networkAddress"
                                    id="networkAddress"
                                    className="flex-1 block w-full min-w-0 text-black border-gray-300 rounded-md focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
                                  />
                                </div>
                              </div>

                              <div className="flex flex-col mt-3">
                                <label
                                  htmlFor="key"
                                  className="block text-sm font-medium text-gray-500 dark:text-gray-300"
                                >
                                  Key
                                </label>
                                <div className="flex mt-1 rounded-md shadow-sm">
                                  <input
                                    value={networkKey}
                                    onChange={onInputChange}
                                    type="text"
                                    name="networkKey"
                                    id="networkKey"
                                    className="flex-1 block w-full min-w-0 text-black border-gray-300 rounded-md focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
                                  />
                                </div>
                              </div>

                              <button
                                onClick={() => addNewNetwork()}
                                className="flex items-center px-3 py-2 mt-5 text-sm font-medium leading-4 text-white bg-indigo-600 border border-transparent rounded-md shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
                              >
                                Add network
                              </button>
                            </form>
                          </Disclosure.Panel>
                        </>
                      )}
                    </Disclosure>
                  </div>

                  <div className="px-4 py-6 mt-6 bg-indigo-700 sm:px-6">
                    <div className="flex items-start justify-between">
                      <Dialog.Title className="text-lg text-white font-headings">
                        Transaction History
                      </Dialog.Title>
                    </div>
                    <div className="mt-1">
                      <p className="text-sm text-indigo-300">
                        Your pending and confirmed transactions.
                      </p>
                    </div>
                  </div>
                  {isLoading ? (
                    <div className="relative flex-1 px-4 mt-6 sm:px-6">
                      <ul className="divide-y divide-gray-200 dark:divide-zinc-700">
                        <li className="py-4">
                          <div className="flex flex-col space-y-3">
                            <Placeholder width={Placeholder.width.FULL} />
                            <Placeholder width={Placeholder.width.THIRD} />
                            <Placeholder width={Placeholder.width.HALF} />
                          </div>
                        </li>
                        <li className="py-4">
                          <div className="flex flex-col space-y-3">
                            <Placeholder width={Placeholder.width.FULL} />
                            <Placeholder width={Placeholder.width.THIRD} />
                            <Placeholder width={Placeholder.width.HALF} />
                          </div>
                        </li>
                      </ul>
                    </div>
                  ) : (
                    <div className="relative flex-1 px-4 mt-6 sm:px-6">
                      <ul className="divide-y divide-gray-200 dark:divide-zinc-700">
                        {pendingTransactions}
                        {transactions}
                      </ul>
                    </div>
                  )}
                </div>
              </div>
            </Transition.Child>
          </div>
        </div>
      </Dialog>
    </Transition>
  );
}
Example #11
Source File: Navbar.tsx    From ultimate-saas-ts with MIT License 4 votes vote down vote up
Component = () => {
  const { data: session, status } = useSession();
  const router = useRouter();

  return (
    <Disclosure as="nav" className="bg-white">
      {({ open }) => (
        <>
          <div className="px-2 mx-auto max-w-7xl sm:px-6 lg:px-8">
            <div className="relative flex justify-between h-16">
              <div className="absolute inset-y-0 left-0 flex items-center sm:hidden">
                <Disclosure.Button className="inline-flex items-center justify-center p-2 text-gray-400 rounded-md hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500">
                  <span className="sr-only">Open main menu</span>
                  {open ? (
                    <XIcon className="block w-6 h-6" aria-hidden="true" />
                  ) : (
                    <MenuIcon className="block w-6 h-6" aria-hidden="true" />
                  )}
                </Disclosure.Button>
              </div>
              <div className="flex items-center justify-center flex-1 sm:items-stretch sm:justify-start">
                <div className="flex items-center flex-shrink-0">
                  <img
                    className="block w-auto h-8 lg:hidden"
                    src="https://tailwindui.com/img/logos/workflow-mark-indigo-600.svg"
                    alt="Workflow"
                  />
                  <img
                    className="hidden w-auto h-8 lg:block"
                    src="https://tailwindui.com/img/logos/workflow-logo-indigo-600-mark-gray-800-text.svg"
                    alt="Workflow"
                  />
                </div>
                <div className="hidden sm:ml-6 sm:flex sm:space-x-8">
                  <Link href="/">
                    <a
                      className={classNames(
                        'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium',
                        {
                          'border-indigo-500 text-gray-900':
                            router.pathname === '/',
                          '': router.pathname !== '/',
                        }
                      )}
                    >
                      Pricings
                    </a>
                  </Link>

                  <Link href="/account">
                    <a
                      className={classNames(
                        'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium',
                        {
                          'border-indigo-500 text-gray-900':
                            router.pathname === '/account',
                          '': router.pathname !== '/account',
                        }
                      )}
                    >
                      Account
                    </a>
                  </Link>
                </div>
              </div>
              <div className="absolute inset-y-0 right-0 flex items-center pr-2 sm:static sm:inset-auto sm:ml-6 sm:pr-0">
                {/* Profile dropdown */}
                {status === 'authenticated' ? (
                  <Menu as="div" className="relative ml-3">
                    <div>
                      <Menu.Button className="flex text-sm bg-white rounded-full focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
                        <span className="sr-only">Open user menu</span>
                        <img
                          className="w-8 h-8 rounded-full"
                          src={
                            session?.user?.image ||
                            'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80'
                          }
                          alt=""
                        />
                      </Menu.Button>
                    </div>
                    <Transition
                      as={Fragment}
                      enter="transition ease-out duration-200"
                      enterFrom="transform opacity-0 scale-95"
                      enterTo="transform opacity-100 scale-100"
                      leave="transition ease-in duration-75"
                      leaveFrom="transform opacity-100 scale-100"
                      leaveTo="transform opacity-0 scale-95"
                    >
                      <Menu.Items className="absolute right-0 w-48 py-1 mt-2 origin-top-right bg-white rounded-md shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
                        <Menu.Item>
                          {({ active }) => (
                            <Link href="/account">
                              <a
                                className={classNames(
                                  active ? 'bg-gray-100' : '',
                                  'block px-4 py-2 text-sm text-gray-700'
                                )}
                              >
                                Account
                              </a>
                            </Link>
                          )}
                        </Menu.Item>
                        <Menu.Item>
                          {({ active }) => (
                            <a
                              onClick={() => signOut()}
                              className={classNames(
                                active ? 'bg-gray-100' : '',
                                'block px-4 py-2 text-sm text-gray-700'
                              )}
                            >
                              Sign out
                            </a>
                          )}
                        </Menu.Item>
                      </Menu.Items>
                    </Transition>
                  </Menu>
                ) : (
                  <Link href="/api/auth/signin">
                    <a>Sign in</a>
                  </Link>
                )}
              </div>
            </div>
          </div>

          <Disclosure.Panel className="sm:hidden">
            <div className="pt-2 pb-4 space-y-1">
              {/* Current: "bg-indigo-50 border-indigo-500 text-indigo-700", Default: "border-transparent text-gray-500 hover:bg-gray-50 hover:border-gray-300 hover:text-gray-700" */}

              <Link href="/">
                <a className="block py-2 pl-3 pr-4 text-base font-medium text-indigo-700 border-l-4 border-indigo-500 bg-indigo-50">
                  Pricings
                </a>
              </Link>
              <Link href="/account">
                <a className="block py-2 pl-3 pr-4 text-base font-medium text-gray-500 border-l-4 border-transparent hover:bg-gray-50 hover:border-gray-300 hover:text-gray-700">
                  Account
                </a>
              </Link>
            </div>
          </Disclosure.Panel>
        </>
      )}
    </Disclosure>
  );
}
Example #12
Source File: AccountHeader.tsx    From pali-wallet with MIT License 4 votes vote down vote up
AccountMenu: React.FC = () => {
  const { navigate } = useUtils();
  const { wallet } = getController();
  const { encryptedMnemonic, accounts, activeAccount } = useStore();

  const verifyAccounts = Object.keys(accounts);

  const setActiveAccount = async (id: number) => {
    await wallet.setAccount(Number(id));
    wallet.account.sys.watchMemPool(accounts[Number(id)]);
  };

  const handleLogout = () => {
    wallet.lock();

    navigate('/');
  };

  return (
    <Menu
      id="account-settings-btn"
      as="div"
      className="absolute right-3 inline-block text-right md:max-w-2xl"
    >
      <Menu.Button className="inline-flex justify-center w-full hover:text-button-primaryhover text-white text-sm font-medium hover:bg-opacity-30 rounded-full focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75">
        {encryptedMnemonic && <Icon name="dots" className="z-0" />}
      </Menu.Button>

      <Transition
        as="div"
        enter="transition ease-out duration-100"
        enterFrom="transform opacity-0 scale-95"
        enterTo="opacity-100 scale-100"
        leave="transition ease-in duration-75"
        leaveFrom="opacity-100 scale-100"
        leaveTo="transform opacity-0 scale-95"
      >
        <div className="fixed z-0 -inset-0 w-full bg-brand-black bg-opacity-50 transition-all duration-300 ease-in-out" />

        <Menu.Items
          as="div"
          className="scrollbar-styled absolute z-10 right-0 pb-6 w-72 text-center text-brand-white font-poppins bg-menu-primary rounded-2xl focus:outline-none shadow-2xl overflow-auto origin-top-right ring-1 ring-black ring-opacity-5"
        >
          <h2
            className="mb-3 pb-6 pt-8 w-full text-center text-brand-white bg-menu-primary border-b border-dashed border-dashed-light"
            id="account-settings-title"
          >
            ACCOUNT SETTINGS
          </h2>

          <Menu.Item>
            <li
              onClick={() => navigate('/settings/account/private-key')}
              className="flex items-center justify-start px-5 py-3 w-full text-base hover:bg-bkg-3 cursor-pointer transition-all duration-200"
            >
              <Icon name="key" className="mb-2 ml-1 mr-2 text-brand-white" />

              <span className="px-3">Your keys</span>
            </li>
          </Menu.Item>

          <Menu.Item>
            <Disclosure>
              {({ open }) => (
                <>
                  <Disclosure.Button className="flex items-center justify-start px-5 py-3 w-full text-base hover:bg-bkg-3 cursor-pointer transition-all duration-200">
                    <Icon
                      name="user"
                      className="mb-2 ml-1 mr-2 text-brand-white"
                      id="accounts-btn"
                    />

                    <span className="px-3 text-base">Accounts</span>

                    <Icon
                      name="select-down"
                      className={`${
                        open ? 'transform rotate-180' : ''
                      } mb-1 text-brand-white`}
                    />
                  </Disclosure.Button>

                  <div
                    className="relative"
                    style={{
                      paddingTop: `${open ? '45px' : '0px'}`,
                    }}
                  >
                    <Disclosure.Panel
                      className={`static overflow-y-scroll scrollbar-styled pb-2 
                    ${
                      verifyAccounts?.length === 1
                        ? 'h-16'
                        : verifyAccounts?.length === 2
                        ? 'h-28'
                        : verifyAccounts?.length >= 3
                        ? 'h-40'
                        : ''
                    }
                    text-sm bg-menu-secondary`}
                    >
                      <li
                        onClick={() => navigate('/settings/account/new')}
                        className="backface-visibility-hidden absolute top-0 flex items-center justify-center mb-4 mx-auto p-2.5 w-full text-brand-white text-sm font-medium hover:bg-bkg-2 bg-menu-secondary active:bg-opacity-40 border-b border-dashed border-gray-500 focus:outline-none cursor-pointer transform transition duration-300"
                        id="create-new-account-btn"
                      >
                        <Icon
                          name="appstoreadd"
                          className="mb-1 mr-3 text-brand-white"
                        />

                        <span>Create new account</span>
                      </li>

                      {Object.values(accounts).map((account, index) => (
                        <li
                          key={account.id}
                          className="backface-visibility-hidden flex flex-col items-center justify-around mt-2 mx-auto p-2.5 max-w-95 text-white text-sm font-medium bg-menu-secondary active:bg-opacity-40 focus:outline-none cursor-pointer transform hover:scale-105 transition duration-300"
                          onClick={() => setActiveAccount(account.id)}
                          id={`account-${index}`}
                        >
                          <span>
                            {account.label} ({ellipsis(account.address, 4, 8)})
                          </span>

                          {activeAccount.id === account.id && (
                            <Icon
                              name="check"
                              className="mb-1 w-4"
                              wrapperClassname="w-6 absolute right-1"
                            />
                          )}
                        </li>
                      ))}
                    </Disclosure.Panel>
                  </div>
                </>
              )}
            </Disclosure>
          </Menu.Item>

          <Menu.Item>
            <li
              onClick={() => navigate('/settings/account/hardware')}
              className="flex items-center justify-start px-5 py-3 w-full text-base hover:bg-bkg-3 cursor-pointer transition-all duration-200"
            >
              <Icon
                name="partition"
                className="mb-2 ml-1 mr-2 text-brand-white"
                id="hardware-wallet-btn"
              />

              <span className="px-3">Hardware wallet</span>
            </li>
          </Menu.Item>

          <Menu.Item>
            <li
              onClick={handleLogout}
              className="flex items-center justify-start px-5 py-3 w-full text-base hover:bg-bkg-3 cursor-pointer transition-all duration-200"
            >
              <Icon name="lock" className="mb-2 ml-1 mr-2 text-brand-white" />

              <span className="px-3">Lock</span>
            </li>
          </Menu.Item>
        </Menu.Items>
      </Transition>
    </Menu>
  );
}
Example #13
Source File: NormalHeader.tsx    From pali-wallet with MIT License 4 votes vote down vote up
NormalHeader: React.FC = () => {
  const { wallet } = getController();

  const { activeNetwork, encryptedMnemonic, networks } = useStore();
  const { handleRefresh, navigate } = useUtils();

  const [currentTabURL, setCurrentTabURL] = useState<string>('');

  const handleChangeNetwork = (chain: string, chainId: number) => {
    wallet.setActiveNetwork(chain, chainId);

    if (chain === 'syscoin') wallet.account.sys.setAddress();
  };

  const updateCurrentTabUrl = async () => {
    const windows = await browser.windows.getAll({ populate: true });

    for (const window of windows) {
      const views = browser.extension.getViews({ windowId: window.id });

      if (views) {
        const tabs = await browser.tabs.query({
          active: true,
          currentWindow: true,
        });
        return String(tabs[0].url);
      }
    }
  };

  useEffect(() => {
    let isMounted = true;

    updateCurrentTabUrl().then((response: any) => {
      if (isMounted) {
        setCurrentTabURL(response);
      }
    });

    return () => {
      isMounted = false;
    };
  }, [wallet.isUnlocked()]);

  const NetworkMenu = () => (
    <Menu as="div" className="absolute left-2 inline-block mr-8 text-left">
      {(menuprops) => (
        <>
          <Menu.Button className="inline-flex gap-x-2 items-center justify-start ml-2 w-full text-white text-sm font-medium hover:bg-opacity-30 rounded-full focus:outline-none cursor-pointer">
            <span>{activeNetwork.label}</span>

            <Icon
              name="select-down"
              className={`${
                menuprops.open ? 'transform rotate-180' : ''
              } text-brand-white`}
              id="network-settings-btn"
            />
          </Menu.Button>

          <Transition
            as="div"
            enter="transition ease-out duration-100"
            enterFrom="transform opacity-0 scale-95"
            enterTo="opacity-100 scale-100"
            leave="transition ease-in duration-75"
            leaveFrom="opacity-100 scale-100"
            leaveTo="transform opacity-0 scale-95"
          >
            <div className="fixed z-50 -inset-0 w-full bg-brand-black bg-opacity-50 transition-all duration-300 ease-in-out" />

            <Menu.Items
              as="div"
              className="absolute z-50 left-0 pb-6 w-72 h-menu text-center text-brand-white font-poppins bg-menu-primary rounded-2xl focus:outline-none shadow-2xl overflow-hidden origin-top-right ring-1 ring-black ring-opacity-5"
            >
              <h2
                className="mb-6 pb-6 pt-8 w-full text-center text-brand-white bg-menu-primary border-b border-dashed border-dashed-light"
                id="network-settings-title"
              >
                NETWORK SETTINGS
              </h2>
              <div className="scrollbar-styled h-80 overflow-auto">
                <Menu.Item>
                  <li
                    onClick={() =>
                      navigate('/settings/networks/connected-sites')
                    }
                    className="flex items-center justify-start mb-2 mx-3 px-2 py-1 text-base bg-warning-success hover:bg-opacity-70 border border-solid border-transparent hover:border-warning-success rounded-full cursor-pointer transition-all duration-200"
                  >
                    <Icon
                      name="globe"
                      className="mb-1 ml-1 mr-4 text-brand-white"
                    />

                    <span className="px-3">Connected sites</span>
                  </li>
                </Menu.Item>

                <Menu.Item>
                  <li
                    onClick={() => navigate('/settings/networks/trusted-sites')}
                    className="flex items-center justify-start mb-4 mx-3 px-2 py-1 text-base bg-brand-royalblue hover:bg-opacity-70 border border-solid border-brand-royalblue rounded-full cursor-pointer transition-all duration-200"
                  >
                    <Icon
                      name="warning"
                      className="mb-1 ml-1 mr-4 text-brand-white"
                    />

                    <span className="px-3">Trusted sites</span>
                  </li>
                </Menu.Item>

                <Menu.Item>
                  <Disclosure>
                    {({ open }) => (
                      <>
                        <Disclosure.Button className="flex items-center justify-start px-5 py-3 w-full text-base hover:bg-bkg-3 cursor-pointer transition-all duration-200">
                          <Icon
                            name="dolar"
                            className="ml-1 mr-4 text-brand-white"
                          />

                          <span className="px-3 text-base">Syscoin core</span>

                          <Icon
                            name="select-down"
                            className={`${
                              open ? 'transform rotate-180' : ''
                            } text-brand-white mb-1`}
                          />
                        </Disclosure.Button>

                        <Disclosure.Panel className="scrollbar-styled pb-2 pt-0.5 h-28 text-sm bg-menu-secondary overflow-auto">
                          {Object.values(networks.syscoin).map(
                            (currentNetwork: any) => (
                              <li
                                key={currentNetwork.chainId}
                                className="backface-visibility-hidden flex flex-col justify-around mt-2 mx-auto p-2.5 max-w-95 text-white text-sm font-medium bg-menu-secondary active:bg-opacity-40 focus:outline-none cursor-pointer transform hover:scale-105 transition duration-300"
                                onClick={() =>
                                  handleChangeNetwork(
                                    'syscoin',
                                    currentNetwork.chainId
                                  )
                                }
                              >
                                <span className="ml-8 text-left">
                                  {currentNetwork.label}
                                </span>

                                {activeNetwork.chainId ===
                                  currentNetwork.chainId && (
                                  <Icon
                                    name="check"
                                    className="mb-1 w-4"
                                    wrapperClassname="w-6 absolute right-20"
                                  />
                                )}
                              </li>
                            )
                          )}
                        </Disclosure.Panel>
                      </>
                    )}
                  </Disclosure>
                </Menu.Item>

                <Menu.Item>
                  <Disclosure>
                    {({ open }) => (
                      <>
                        <Disclosure.Button className="flex items-center justify-start px-5 py-3 w-full text-base hover:bg-bkg-3 cursor-pointer transition-all duration-200">
                          <Icon
                            name="dolar"
                            className="ml-1 mr-4 text-brand-white"
                          />

                          <span className="px-3 text-base">Web3 networks</span>

                          <Icon
                            name="select-down"
                            className={`${
                              open ? 'transform rotate-180' : ''
                            } mb-1 text-brand-white`}
                          />
                        </Disclosure.Button>

                        <Disclosure.Panel className="scrollbar-styled pb-2 pt-0.5 h-28 text-sm bg-menu-secondary overflow-auto">
                          {Object.values(networks.ethereum).map(
                            (currentNetwork: any) => (
                              <li
                                key={currentNetwork.id}
                                className="backface-visibility-hidden flex flex-col justify-around mt-2 mx-auto p-2.5 max-w-95 text-white text-sm font-medium bg-menu-secondary active:bg-opacity-40 focus:outline-none cursor-pointer transform hover:scale-105 transition duration-300"
                                onClick={() =>
                                  handleChangeNetwork(
                                    'ethereum',
                                    currentNetwork.chainId
                                  )
                                }
                              >
                                <span className="ml-8 text-left">
                                  {currentNetwork.label}
                                </span>

                                {activeNetwork.chainId ===
                                  currentNetwork.chainId && (
                                  <Icon
                                    name="check"
                                    className="mb-1 w-4"
                                    wrapperClassname="w-6 absolute right-16"
                                  />
                                )}
                              </li>
                            )
                          )}
                        </Disclosure.Panel>
                      </>
                    )}
                  </Disclosure>
                </Menu.Item>

                <Menu.Item>
                  <li
                    onClick={() => navigate('/settings/networks/custom-rpc')}
                    className="flex items-center justify-start px-5 py-3 w-full text-base hover:bg-bkg-3 cursor-pointer transition-all duration-200"
                  >
                    <Icon
                      name="appstoreadd"
                      className="ml-1 mr-4 text-brand-white"
                    />

                    <span className="px-3">Custom RPC</span>
                  </li>
                </Menu.Item>

                <Menu.Item>
                  <li
                    onClick={() => navigate('/settings/networks/edit')}
                    className="flex items-center justify-start px-5 py-3 w-full text-base hover:bg-bkg-3 cursor-pointer transition-all duration-200"
                  >
                    <Icon name="edit" className="ml-1 mr-4 text-brand-white" />

                    <span className="px-3">Manage networks</span>
                  </li>
                </Menu.Item>
              </div>
            </Menu.Items>
          </Transition>
        </>
      )}
    </Menu>
  );

  const GeneralMenu = () => (
    <Menu
      as="div"
      className="absolute right-2 top-2 flex items-center justify-evenly"
    >
      {() => (
        <>
          <Tooltip content={ellipsis(currentTabURL, 25, 0)}>
            <div
              onClick={() => navigate('/settings/networks/connected-sites')}
              className="relative mx-1.5 text-brand-white cursor-pointer"
            >
              <Icon
                name="globe"
                className="hover:text-brand-royalblue text-white"
              />

              <Badge className="absolute -right-1 top-1 w-3 h-3 text-warning-error bg-warning-error rounded-full" />
            </div>
          </Tooltip>

          <div
            onClick={() => handleRefresh(false)}
            className="mx-1.5 hover:text-brand-royalblue text-brand-white cursor-pointer"
          >
            <Icon name="reload" />
          </div>

          <Menu.Button as="button" className="mx-1.5">
            {Boolean(encryptedMnemonic) && (
              <div id="general-settings-button">
                <Icon
                  name="settings"
                  className="hover:text-brand-royalblue text-brand-white"
                />
              </div>
            )}
          </Menu.Button>

          <Transition
            as="div"
            enter="transition ease-out duration-100"
            enterFrom="transform opacity-0 scale-95"
            enterTo="opacity-100 scale-100"
            leave="transition ease-in duration-75"
            leaveFrom="opacity-100 scale-100"
            leaveTo="transform opacity-0 scale-95"
          >
            <div className="fixed z-50 -inset-0 w-full bg-brand-black bg-opacity-50 transition-all duration-300 ease-in-out" />

            <Menu.Items
              as="div"
              className="scrollbar-styled absolute z-50 right-0 pb-6 w-72 h-96 text-center text-brand-white font-poppins bg-menu-primary rounded-2xl focus:outline-none shadow-2xl overflow-auto origin-top-right ring-1 ring-black ring-opacity-5"
            >
              <h2
                className="mb-6 pb-6 pt-8 w-full text-center text-brand-white bg-menu-primary border-b border-dashed border-dashed-light"
                id="general-settings-title"
              >
                GENERAL SETTINGS
              </h2>

              <Menu.Item>
                <li
                  onClick={() => navigate('/settings/autolock')}
                  className="flex items-center justify-start px-5 py-3 w-full text-base hover:bg-bkg-3 cursor-pointer transition-all duration-200"
                >
                  <Icon name="clock" className="ml-1 mr-4 text-brand-white" />

                  <span className="px-3">Auto lock timer</span>
                </li>
              </Menu.Item>

              <Menu.Item>
                <li
                  onClick={() => navigate('/settings/currency')}
                  className="flex items-center justify-start px-5 py-3 w-full text-base hover:bg-bkg-3 cursor-pointer transition-all duration-200"
                >
                  <Icon name="dolar" className="ml-1 mr-4 text-brand-white" />

                  <span className="px-3">Currency</span>
                </li>
              </Menu.Item>

              <Menu.Item>
                <li
                  onClick={() => navigate('/settings/phrase')}
                  className="flex items-center justify-start px-5 py-3 w-full text-base hover:bg-bkg-3 cursor-pointer transition-all duration-200"
                >
                  <Icon name="wallet" className="ml-1 mr-4 text-brand-white" />

                  <span id="wallet-seed-phrase-btn" className="px-3">
                    Wallet Seed Phrase
                  </span>
                </li>
              </Menu.Item>

              <Menu.Item>
                <li
                  onClick={() => navigate('/settings/about')}
                  className="flex items-center justify-start px-5 py-3 w-full text-base hover:bg-bkg-3 cursor-pointer transition-all duration-200"
                >
                  <Icon
                    name="warning"
                    className="ml-1 mr-4 text-brand-white"
                    id="info-help-btn"
                  />

                  <span className="px-3">Info/Help</span>
                </li>
              </Menu.Item>

              <Menu.Item>
                <li
                  onClick={() => navigate('/settings/forget-wallet')}
                  className="flex items-center justify-start px-5 py-3 w-full text-base hover:bg-bkg-3 cursor-pointer transition-all duration-200"
                >
                  <Icon
                    name="forget"
                    className="ml-1 mr-4 w-5 h-5 text-brand-white"
                    id="forget-wallet-btn"
                  />

                  <span className="px-3">Forget wallet</span>
                </li>
              </Menu.Item>
            </Menu.Items>
          </Transition>
        </>
      )}
    </Menu>
  );

  return (
    <div className="relative flex items-center justify-between p-2 py-6 w-full text-gray-300 bg-bkg-1">
      <NetworkMenu />

      <GeneralMenu />
    </div>
  );
}
Example #14
Source File: TransactionDetails.tsx    From pali-wallet with MIT License 4 votes vote down vote up
TransactionDetails = ({
  transactionType,
  transactionDetails,
  setTransactionHash,
  txAddress,
}: {
  setTransactionHash?: any;
  transactionDetails: any;
  transactionType: any;
  txAddress?: any;
}) => {
  const { activeNetwork, networks } = useStore();
  const isSyscoinChain = Boolean(networks.syscoin[activeNetwork.chainId]);
  const { useCopyClipboard, alert } = useUtils();

  const controller = getController();

  const [newRecipients, setNewRecipients] = useState<any>({});
  const [newSenders, setNewSenders] = useState<any>({});
  const [copied, copyText] = useCopyClipboard();

  const showSuccessAlert = () => {
    if (copied) {
      alert.removeAll();
      alert.success('Address successfully copied');
    }
  };

  const recipients: any = {};
  const senders: any = {};

  useEffect(() => {
    if (transactionDetails) {
      const { vin, vout } = transactionDetails;

      if (vin && vout) {
        for (const item of vout) {
          if (item.addresses) {
            recipients[item.addresses[0]] = {
              address: item.addresses[0],
              value: item.value,
            };
          }
        }

        if (vin.length === 1) {
          for (const item of vin) {
            if (!item.vout) {
              return;
            }

            controller.utils
              .getRawTransaction(activeNetwork.url, item.txid)
              .then((response: any) => {
                for (const responseVout of response.vout) {
                  if (responseVout.n === item.vout) {
                    senders[item.addresses[0]] = {
                      address: item.addresses[0],
                      value: item.value,
                    };
                  }
                }
              });
          }
        }

        if (vin.length > 1) {
          for (const item of vin) {
            if (item.addresses) {
              senders[item.addresses[0]] = {
                address: item.addresses[0],
                value: item.value,
              };
            }
          }
        }

        setNewRecipients(recipients);
        setNewSenders(senders);
      }
    }
  }, [transactionDetails]);

  const renderAddresses = (list: any) =>
    Object.values(list).map(({ address, value: addressValue }: any) => (
      <li
        onClick={() => copyText(address)}
        key={address}
        className="flex gap-x-1 items-center justify-between mt-2 p-1 text-xs rounded-lg cursor-pointer transition-all duration-200"
      >
        <p>{ellipsis(address) || '...'}</p>

        <div>
          <small>
            {formatUrl(String(Number(addressValue) / 10 ** 8), 18)
              ? formatUrl(String(Number(addressValue) / 10 ** 8), 18)
              : 0}{' '}
            {activeNetwork.chainId === 57 ? 'SYS' : 'tSYS'}
          </small>

          <IconButton onClick={() => copyText(address)}>
            <Icon
              name="copy"
              className="px-1 text-brand-white hover:text-fields-input-borderfocus"
            />
          </IconButton>
        </div>
      </li>
    ));

  const { blockHash, confirmations, blockTime, valueIn, value, fees } =
    transactionDetails;

  const checkNetwork = (checkValue: any) =>
    activeNetwork.chainId === 57
      ? `${checkValue / 10 ** 8} SYS`
      : `${checkValue / 10 ** 8} tSYS`;

  const txData = [
    {
      label: 'Block hash',
      value: ellipsis(blockHash),
    },
    {
      label: 'Type',
      value: transactionType || 'Transaction',
    },
    {
      label: 'Confirmations',
      value: confirmations,
    },
    {
      label: 'Mined',
      value: blockTime
        ? formatDate(new Date(blockTime * 1000).toDateString())
        : '',
    },
    {
      label: 'Total input',
      value: valueIn ? checkNetwork(valueIn) : '',
    },
    {
      label: 'Total output',
      value: value ? checkNetwork(value) : '',
    },
    {
      label: 'Fees',
      value: fees ? checkNetwork(fees) : '',
    },
  ];

  return (
    <>
      {isSyscoinChain &&
        txData.map(({ label, value: currentValue }: any) => (
          <>
            <div
              key={label}
              className="flex items-center justify-between my-1 px-6 py-2 w-full text-xs border-b border-dashed border-bkg-2 cursor-default transition-all duration-300"
            >
              <p>{label}</p>
              <b>{currentValue}</b>
            </div>
          </>
        ))}

      {!isSyscoinChain &&
        transactionDetails
          .filter((item: any) => txAddress.hash === item.hash)
          .map((label, i: number) => {
            setTransactionHash(`${label?.hash}`);
            return (
              <div key={i}>
                <div className="flex items-center justify-between my-1 px-6 py-2 w-full text-xs border-b border-dashed border-bkg-2 cursor-default transition-all duration-300">
                  <b>Blockhash</b>
                  <p>{ellipsis(label?.hash)}</p>
                </div>

                <div className="flex items-center justify-between my-1 px-6 py-2 w-full text-xs border-b border-dashed border-bkg-2 cursor-default transition-all duration-300">
                  <b>Type</b>
                  <p>Transaction</p>
                </div>

                <div className="flex items-center justify-between my-1 px-6 py-2 w-full text-xs border-b border-dashed border-bkg-2 cursor-default transition-all duration-300">
                  <b>Confirmations</b>
                  <p>{label?.confirmations}</p>
                </div>
                <div className="flex items-center justify-between my-1 px-6 py-2 w-full text-xs border-b border-dashed border-bkg-2 cursor-default transition-all duration-300">
                  <b>Blocknumber</b>
                  <p>{label?.blockNumber}</p>
                </div>
                <div className="flex items-center justify-between my-1 px-6 py-2 w-full text-xs border-b border-dashed border-bkg-2 cursor-default transition-all duration-300">
                  <b>Mined</b>
                  <p>
                    {label?.timestamp
                      ? formatDate(
                          new Date(label?.timestamp * 1000).toDateString()
                        )
                      : ''}
                  </p>
                </div>

                <div className="flex items-center justify-between my-1 px-6 py-2 w-full text-xs border-b border-dashed border-bkg-2 cursor-default transition-all duration-300">
                  <b>From</b>
                  <p
                    onClick={() => copyText(label.from)}
                    className="hover:text-fields-input-borderfocus cursor-pointer"
                  >
                    {ellipsis(label?.from)}
                  </p>
                </div>

                <div className="flex items-center justify-between my-1 px-6 py-2 w-full text-xs border-b border-dashed border-bkg-2 cursor-default transition-all duration-300">
                  <b>To</b>
                  <p
                    onClick={() => copyText(label.to)}
                    className="hover:text-fields-input-borderfocus cursor-pointer"
                  >
                    {ellipsis(label?.to)}
                  </p>
                </div>

                <div className="flex items-center justify-between my-1 px-6 py-2 w-full text-xs border-b border-dashed border-bkg-2 cursor-default transition-all duration-300">
                  <b>Value</b>
                  <p>
                    {`${web3Provider.utils.fromWei(
                      `${parseInt(String(label.value.hex), 16)}`,
                      'ether'
                    )} ${activeNetwork.currency?.toUpperCase()}`}
                  </p>
                </div>

                <div className="flex items-center justify-between my-1 px-6 py-2 w-full text-xs border-b border-dashed border-bkg-2 cursor-default transition-all duration-300">
                  <b>Nonce</b>
                  <p>{label.nonce}</p>
                </div>

                <div className="flex items-center justify-between my-1 px-6 py-2 w-full text-xs border-b border-dashed border-bkg-2 cursor-default transition-all duration-300">
                  <b>Gas Price</b>
                  <p>
                    {`${web3Provider.utils.fromWei(
                      `${parseInt(String(label.gasPrice.hex), 16)}`,
                      'ether'
                    )}`}
                  </p>
                </div>
                <div className="flex items-center justify-between my-1 px-6 py-2 w-full text-xs border-b border-dashed border-bkg-2 cursor-default transition-all duration-300">
                  <b>Gas Limit</b>
                  <p>
                    {`${web3Provider.utils.fromWei(
                      `${parseInt(String(label.gasLimit.hex), 16)}`,
                      'ether'
                    )}`}
                  </p>
                </div>
              </div>
            );
          })}

      {isSyscoinChain && Object.values(newSenders).length > 0 && (
        <Disclosure>
          {({ open }) => (
            <>
              <div className="px-6">
                <Disclosure.Button
                  className={`${
                    open ? 'rounded-t-md' : 'rounded-md'
                  } mt-3 py-2 px-2 flex justify-between items-center  w-full border border-bkg-3 bg-bkg-1 cursor-pointer transition-all duration-300 text-xs`}
                >
                  From
                  <Icon
                    name="select-down"
                    className={`${
                      open ? 'transform rotate-180' : ''
                    } mb-1 text-brand-white`}
                  />
                </Disclosure.Button>
              </div>

              <Disclosure.Panel>
                <div className="px-6">
                  <div className="flex flex-col pb-2 px-2 w-full text-brand-white text-sm bg-bkg-3 border border-t-0 border-bkg-4 rounded-lg rounded-t-none transition-all duration-300">
                    {Object.values(newSenders).length &&
                      renderAddresses(newSenders)}
                  </div>
                </div>
              </Disclosure.Panel>
            </>
          )}
        </Disclosure>
      )}

      {isSyscoinChain && Object.values(newRecipients).length > 0 && (
        <Disclosure>
          {({ open }) => (
            <>
              <div className="px-6">
                <Disclosure.Button
                  className={`${
                    open ? 'rounded-t-md' : 'rounded-md'
                  } mt-3 py-2 px-2 flex justify-between items-center  w-full border border-bkg-3 bg-bkg-1 cursor-pointer transition-all duration-300 text-xs`}
                >
                  To
                  <Icon
                    name="select-down"
                    className={`${
                      open ? 'transform rotate-180' : ''
                    } mb-1 text-brand-white`}
                  />
                </Disclosure.Button>
              </div>

              <div className="px-6">
                <Disclosure.Panel>
                  <div className="flex flex-col pb-2 px-2 w-full text-brand-white text-sm bg-bkg-3 border border-t-0 border-bkg-4 rounded-lg rounded-t-none transition-all duration-300">
                    {Object.values(newRecipients).length &&
                      renderAddresses(newRecipients)}
                  </div>
                </Disclosure.Panel>
              </div>
            </>
          )}
        </Disclosure>
      )}

      {copied && showSuccessAlert()}
    </>
  );
}
Example #15
Source File: ConnectHardwareWallet.tsx    From pali-wallet with MIT License 4 votes vote down vote up
ConnectHardwareWalletView: FC = () => {
  const [selected, setSelected] = useState<boolean>(false);
  const [isTestnet, setIsTestnet] = useState<boolean>(false);

  const controller = getController();

  const handleCreateHardwareWallet = async () => {
    await controller.wallet.trezor.connectHardware();
  };

  const { activeNetwork } = useStore();

  useEffect(() => {
    setIsTestnet(
      !(activeNetwork.chainId === 57 || activeNetwork.chainId === 1)
    );
  }, [activeNetwork]);

  return (
    <Layout title="HARDWARE WALLET" id="hardware-wallet-title">
      <div className="flex flex-col items-center justify-center w-full md:max-w-md">
        <div className="scrollbar-styled px-4 h-85 text-sm overflow-y-auto md:px-0 md:w-full md:max-w-md md:h-3/4">
          <p className="mb-1 mt-8 mx-2.5 w-80 text-white text-sm md:mx-0 md:w-full">
            Select the hardware wallet you'd like to connect to Pali
          </p>

          <p
            className={`${
              selected
                ? 'bg-bkg-3 border-brand-deepPink'
                : 'bg-bkg-1 border-brand-royalblue'
            } rounded-full py-2 w-80 md:w-full mx-auto text-center border text-sm my-6 cursor-pointer`}
            onClick={() => setSelected(!selected)}
            id="trezor-btn"
          >
            Trezor
          </p>

          <div className="mb-6 mx-auto p-4 w-80 text-brand-white text-xs bg-bkg-4 border border-dashed border-brand-royalblue rounded-lg md:w-full">
            <p>
              <b>Don't have a hardware wallet?</b>
              <br />
              <br />
              Order a Trezor wallet and keep your funds in cold storage.
            </p>

            <p
              className="mt-2 w-16 hover:text-brand-white text-button-primary cursor-pointer"
              onClick={() => window.open('https://trezor.io/')}
            >
              Buy now
            </p>
          </div>

          <Disclosure>
            {({ open }) => (
              <>
                <Disclosure.Button
                  className={`${
                    open ? 'rounded-t-lg' : 'rounded-lg'
                  } mt-3 w-80 md:w-full py-2 px-4 flex justify-between items-center mx-auto border border-bkg-1 cursor-pointer transition-all duration-300 bg-bkg-1 learn-more-btn`}
                >
                  Learn more
                  <Icon
                    name="select-down"
                    className={`${
                      open ? 'transform rotate-180' : ''
                    } mb-1 text-brand-deepPink100`}
                  />
                </Disclosure.Button>

                <Disclosure.Panel>
                  <div className="flex flex-col items-start justify-start mx-auto px-4 py-2 w-80 bg-bkg-3 border border-bkg-3 rounded-b-lg cursor-pointer transition-all duration-300 md:w-full md:max-w-md">
                    <p className="my-2 text-sm">
                      1 - Connect a hardware wallet
                    </p>

                    <span className="mb-4 text-xs">
                      Connect your hardware wallet directly to your computer.
                    </span>

                    <p className="my-2 text-sm">
                      2 - Start using SYS powered sites and more
                    </p>

                    <span className="mb-1 text-xs">
                      Use your hardware account like you would with any SYS
                      account. Connect to SYS web3 sites, send SYS, buy and
                      store SPT tokens.
                    </span>
                  </div>
                </Disclosure.Panel>
              </>
            )}
          </Disclosure>
        </div>

        <div className="absolute bottom-12 md:static md:mt-6">
          <SecondaryButton
            type="button"
            onClick={handleCreateHardwareWallet}
            disabled={isTestnet || !selected}
            id="connect-btn"
          >
            <Tooltip
              content={
                isTestnet &&
                "Trezor doesn't support SYS testnet. Change your network to be able to connect to trezor."
              }
            >
              <p>Connect</p>
            </Tooltip>
          </SecondaryButton>
        </div>
      </div>
    </Layout>
  );
}