utils#disableSendForm TypeScript Examples

The following examples show how to use utils#disableSendForm. 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: ChainSelection.tsx    From frontend-v1 with GNU Affero General Public License v3.0 4 votes vote down vote up
ChainSelection: React.FC = () => {
  const { init } = onboard;
  const { isConnected, provider, chainId, error } = useConnection();
  const sendState = useAppSelector((state) => state.send);
  const dispatch = useAppDispatch();

  const { trackEvent } = useMatomo();

  /*
    The following block will attempt to change the dropdown when the user connects the app.

    Otherwise, it just makes sure to map the dropdown value when the currentSelected block changes.

    This will also change the dropdown value in <AddressSelection /> because of the hook in there.
  */
  const previousChainId = usePrevious(chainId);
  useEffect(() => {
    if (chainId && previousChainId === undefined) {
      const findChain = CHAINS_SELECTION.find((x) => x.chainId === chainId);
      const notFindChain = CHAINS_SELECTION.filter(
        (x) => x.chainId !== chainId
      );

      if (findChain && notFindChain) {
        dispatch(actions.updateSelectedFromChain(findChain));
        dispatch(
          actions.updateSelectedToChain(notFindChain[notFindChain.length - 1])
        );
        dispatch(
          actions.fromChain({ ...sendState, fromChain: findChain.chainId })
        );
        dispatch(
          actions.toChain({
            ...sendState,
            toChain: notFindChain[notFindChain.length - 1].chainId,
          })
        );
      }
    }
  }, [
    chainId,
    previousChainId,
    sendState.currentlySelectedFromChain,
    dispatch,
    sendState,
  ]);

  const wrongNetworkSend =
    provider &&
    chainId &&
    (error instanceof UnsupportedChainIdError ||
      chainId !== sendState.currentlySelectedFromChain.chainId);

  const buttonText = wrongNetworkSend
    ? `Switch to ${CHAINS[sendState.currentlySelectedFromChain.chainId].name}`
    : !isConnected
    ? "Connect Wallet"
    : null;

  const handleClick = () => {
    if (!provider) {
      init();
    } else if (wrongNetworkSend) {
      switchChain(provider, sendState.currentlySelectedFromChain.chainId);
    }
  };

  const {
    isOpen,
    selectedItem,
    getLabelProps,
    getToggleButtonProps,
    getItemProps,
    getMenuProps,
  } = useSelect({
    items: CHAINS_SELECTION,
    defaultSelectedItem: sendState.currentlySelectedFromChain,
    selectedItem: sendState.currentlySelectedFromChain,
    onSelectedItemChange: ({ selectedItem }) => {
      if (selectedItem) {
        // Matomo track fromChain
        trackEvent({
          category: "send",
          action: "setFromChain",
          name: selectedItem.chainId.toString(),
        });

        const nextState = { ...sendState, fromChain: selectedItem.chainId };
        dispatch(actions.fromChain(nextState));
        dispatch(actions.updateSelectedFromChain(selectedItem));
        const nsToChain = { ...sendState, toChain: ChainId.MAINNET };
        if (selectedItem.chainId === ChainId.MAINNET) {
          nsToChain.toChain = ChainId.OPTIMISM;
          dispatch(actions.toChain(nsToChain));
          dispatch(actions.updateSelectedToChain(CHAINS_SELECTION[0]));
        }
        if (
          selectedItem.chainId !== ChainId.MAINNET &&
          sendState.currentlySelectedToChain.chainId !== ChainId.MAINNET
        ) {
          dispatch(
            actions.updateSelectedToChain(
              CHAINS_SELECTION[CHAINS_SELECTION.length - 1]
            )
          );
        }
      }
    },
  });

  return (
    <Section>
      <Wrapper>
        {disableSendForm && (
          <SendBlockedWarning>
            <div>
              Across V1 sending is disabled, please visit{" "}
              <a href="https://v2.across.to" target="_blank" rel="noreferrer">
                {" "}
                Across V2
              </a>{" "}
            </div>
          </SendBlockedWarning>
        )}
        <SectionTitle>From</SectionTitle>
        <InputGroup>
          <RoundBox as="label" {...getLabelProps()}>
            <ToggleButton type="button" {...getToggleButtonProps()}>
              <Logo src={selectedItem?.logoURI} alt={selectedItem?.name} />
              <ToggleChainName>{selectedItem?.name}</ToggleChainName>
              <ToggleIcon />
            </ToggleButton>
          </RoundBox>
          <Menu isOpen={isOpen} {...getMenuProps()}>
            {isOpen &&
              CHAINS_SELECTION.map((t, index) => {
                return (
                  <Item
                    className={
                      t === sendState.currentlySelectedFromChain
                        ? "disabled"
                        : ""
                    }
                    {...getItemProps({ item: t, index })}
                    initial={{ y: -10 }}
                    animate={{ y: 0 }}
                    exit={{ y: -10 }}
                    key={t.chainId}
                  >
                    <Logo src={t.logoURI} alt={t.name} />
                    <div>{t.name}</div>
                    <span className="layer-type">
                      {index !== CHAINS_SELECTION.length - 1 ? "L2" : "L1"}
                    </span>
                  </Item>
                );
              })}
          </Menu>
        </InputGroup>
        {(wrongNetworkSend || !isConnected) && (
          <ConnectButton onClick={handleClick}>{buttonText}</ConnectButton>
        )}
      </Wrapper>
    </Section>
  );
}
Example #2
Source File: SendAction.tsx    From frontend-v1 with GNU Affero General Public License v3.0 4 votes vote down vote up
SendAction: React.FC = () => {
  const {
    amount,
    token,
    send,
    hasToApprove,
    canApprove,
    canSend,
    toAddress,
    approve,
    fees,
    spender,
  } = useSend();
  const { signer, account, name } = useConnection();
  const sendState = useAppSelector((state) => state.send);
  const [isInfoModalOpen, setOpenInfoModal] = useState(false);
  const toggleInfoModal = () => setOpenInfoModal((oldOpen) => !oldOpen);
  const [isSendPending, setSendPending] = useState(false);
  const [isApprovalPending, setApprovalPending] = useState(false);
  const { addTransaction } = useTransactions();
  const { addDeposit } = useDeposits();
  const [updateEthBalance] = api.endpoints.ethBalance.useLazyQuery();
  const { trackEvent } = useMatomo();
  // trigger balance update
  const [updateBalances] = api.endpoints.balances.useLazyQuery();
  const tokenInfo = TOKENS_LIST[
    sendState.currentlySelectedFromChain.chainId
  ].find((t) => t.address === token);
  const { error, addError, removeError } = useContext(ErrorContext);
  const { refetch } = useAllowance(
    {
      owner: account!,
      spender,
      chainId: sendState.currentlySelectedFromChain.chainId,
      token,
      amount,
    },
    { skip: !account }
  );
  const handleApprove = async () => {
    const tx = await approve();
    if (tx) {
      addTransaction({ ...tx, meta: { label: TransactionTypes.APPROVE } });
      await tx.wait(CONFIRMATIONS);
      refetch();
    }
  };

  const handleSend = async () => {
    const { tx, fees } = await send();
    if (tx && fees) {
      addTransaction({ ...tx, meta: { label: TransactionTypes.DEPOSIT } });
      const receipt = await tx.wait(CONFIRMATIONS);
      addDeposit({
        tx: receipt,
        toChain: sendState.currentlySelectedToChain.chainId,
        fromChain: sendState.currentlySelectedFromChain.chainId,
        amount,
        token,
        toAddress,
        fees,
      });
      // update balances after tx
      if (account) {
        updateEthBalance({
          chainId: sendState.currentlySelectedFromChain.chainId,
          account,
        });
        updateBalances({
          chainId: sendState.currentlySelectedFromChain.chainId,
          account,
        });
      }
    }
  };
  const handleClick = () => {
    if (amount.lte(0) || !signer || disableSendForm) {
      return;
    }
    if (hasToApprove) {
      setApprovalPending(true);
      handleApprove()
        .catch((err) => {
          addError(new Error(`Error in approve call: ${err.message}`));
          console.error(err);
        })
        .finally(() => setApprovalPending(false));
      return;
    }
    if (canSend) {
      // Matomo track send transactions
      trackEvent({
        category: "send",
        action: "bridge",
        name:
          tokenInfo &&
          JSON.stringify({
            symbol: tokenInfo.symbol,
            from: sendState.currentlySelectedFromChain.chainId,
            to: sendState.currentlySelectedToChain.chainId,
          }),
        value: tokenInfo && Number(formatUnits(amount, tokenInfo.decimals)),
      });
      setSendPending(true);
      if (error) removeError();
      handleSend()
        .catch((err) => {
          addError(new Error(`Error with send call: ${err.message}`));
          console.error(err);
        })
        // this actually happens after component unmounts, which is not good. it causes a react warning, but we need
        // it here if user cancels the send. so keep this until theres a better way.
        .finally(() => setSendPending(false));
    }
  };

  const buttonMsg = () => {
    if (isSendPending) return "Sending in progress...";
    if (isApprovalPending) return "Approval in progress...";
    if (hasToApprove) return "Approve";
    return "Send";
  };
  const amountMinusFees = useMemo(() => {
    if (sendState.currentlySelectedFromChain.chainId === ChainId.MAINNET) {
      return amount;
    }
    return receiveAmount(amount, fees);
  }, [amount, fees, sendState.currentlySelectedFromChain.chainId]);

  const buttonDisabled =
    isSendPending ||
    isApprovalPending ||
    (!hasToApprove && !canSend) ||
    (hasToApprove && !canApprove) ||
    amountMinusFees.lte(0);

  const isWETH = tokenInfo?.symbol === "WETH";

  return (
    <AccentSection>
      <Wrapper>
        {amount.gt(0) && fees && tokenInfo && (
          <>
            <InfoHeadlineContainer>
              <SlippageDisclaimer>
                <ConfettiIcon />
                All transfers are slippage free!
              </SlippageDisclaimer>
              <FeesButton onClick={toggleInfoModal}>Fees info</FeesButton>
            </InfoHeadlineContainer>
            <InfoContainer>
              <Info>
                {`Time to ${
                  CHAINS[sendState.currentlySelectedToChain.chainId].name
                }`}
                <div>
                  {getEstimatedDepositTime(
                    sendState.currentlySelectedToChain.chainId
                  )}
                </div>
              </Info>
              {sendState.currentlySelectedFromChain.chainId !==
                ChainId.MAINNET && (
                <Info>
                  <div>Ethereum Network Gas</div>
                  <div>
                    {formatUnits(
                      fees.instantRelayFee.total.add(fees.slowRelayFee.total),
                      tokenInfo.decimals
                    )}{" "}
                    {tokenInfo.symbol}
                  </div>
                </Info>
              )}
              <Info>
                <div>
                  {sendState.currentlySelectedFromChain.chainId ===
                  ChainId.MAINNET
                    ? "Native Bridge Fee"
                    : "Across Bridge Fee"}
                </div>
                <div>
                  {sendState.currentlySelectedFromChain.chainId ===
                  ChainId.MAINNET
                    ? "Free"
                    : `${formatUnits(fees.lpFee.total, tokenInfo.decimals)}
                  ${tokenInfo.symbol}`}
                </div>
              </Info>
            </InfoContainer>
            <AmountToReceive>
              You will receive
              <span>
                {formatUnits(amountMinusFees, tokenInfo.decimals)}{" "}
                {isWETH ? "ETH" : tokenInfo.symbol}
              </span>
            </AmountToReceive>
          </>
        )}

        <PrimaryButton
          onClick={handleClick}
          disabled={buttonDisabled || !!disableSendForm}
        >
          <span>{buttonMsg()}</span>
        </PrimaryButton>
        {name && name === "WalletConnect" && (
          <WalletConnectWarning>
            <span>
              Do not change networks after connecting to Across with
              WalletConnect. Across is not responsible for wallet-based
              integration issues with WalletConnect.
            </span>
          </WalletConnectWarning>
        )}

        {sendState.currentlySelectedFromChain.chainId === ChainId.MAINNET && (
          <L1Info>
            <div>L1 to L2 transfers use the destination’s native bridge</div>
          </L1Info>
        )}
      </Wrapper>
      <InformationDialog isOpen={isInfoModalOpen} onClose={toggleInfoModal} />
    </AccentSection>
  );
}