utils#receiveAmount TypeScript Examples

The following examples show how to use utils#receiveAmount. 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: 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>
  );
}
Example #2
Source File: Confirmation.tsx    From frontend-v1 with GNU Affero General Public License v3.0 4 votes vote down vote up
Confirmation: React.FC = () => {
  const { deposit, toggle } = useDeposits();

  if (!deposit) return null;
  const amountMinusFees = receiveAmount(deposit.amount, deposit.fees);
  const tokenInfo = TOKENS_LIST[deposit.fromChain].find(
    (t) => t.address === deposit.token
  );
  const isWETH = tokenInfo?.symbol === "WETH";

  return (
    <Layout>
      <Wrapper>
        <Header>
          <Heading>Deposit succeeded</Heading>
          <SubHeading>
            Your funds will arrive in{" "}
            {getConfirmationDepositTime(deposit.toChain)}
          </SubHeading>
          <SuccessIcon>
            <Check strokeWidth={4} />
          </SuccessIcon>
        </Header>
        <InfoSection>
          <Link
            href={CHAINS[deposit.fromChain].constructExplorerLink(
              deposit.txHash
            )}
            target="_blank"
            rel="noopener norefferrer"
          >
            Explorer <ArrowUpRight width={16} height={16} />
          </Link>
          <div>
            <Row>
              <Info>
                <h3>Sending</h3>
                <div>
                  <Logo
                    src={tokenInfo?.logoURI}
                    alt={`${tokenInfo?.symbol} logo`}
                  />
                  <div>
                    {formatUnits(deposit.amount, tokenInfo?.decimals ?? 18)}{" "}
                    {tokenInfo?.symbol}
                  </div>
                </div>
              </Info>
              <Info></Info>
              <Info>
                <h3>Receiving</h3>
                <div>
                  <Logo
                    src={isWETH ? MAINNET_ETH?.logoURI : tokenInfo?.logoURI}
                    alt={`${
                      isWETH ? MAINNET_ETH?.symbol : tokenInfo?.symbol
                    } logo`}
                  />
                  <div>
                    {formatUnits(
                      amountMinusFees,
                      (isWETH ? MAINNET_ETH?.decimals : tokenInfo?.decimals) ??
                        18
                    )}{" "}
                    {isWETH ? MAINNET_ETH?.symbol : tokenInfo?.symbol}
                  </div>
                </div>
              </Info>
            </Row>
            <Info>
              <h3>From</h3>
              <div>
                <Logo
                  src={CHAINS[deposit.fromChain].logoURI}
                  alt={`${CHAINS[deposit.fromChain].name} logo`}
                />
                <div>
                  <SecondaryLink
                    href={`${CHAINS[deposit.fromChain].explorerUrl}/address/${
                      deposit.from
                    }`}
                    target="_blank"
                    rel="noopener noreferrer"
                  >
                    <span>{deposit.from}</span>
                    <span>{shortenAddressLong(deposit.from ?? "")}</span>
                  </SecondaryLink>
                </div>
              </div>
            </Info>
            <Info>
              <h3>To</h3>
              <div>
                <Logo
                  src={CHAINS[deposit.toChain].logoURI}
                  alt={`${CHAINS[deposit.toChain].name} logo`}
                />
                <div>
                  <SecondaryLink
                    href={`${CHAINS[deposit.toChain].explorerUrl}/address/${
                      deposit.toAddress
                    }`}
                    target="_blank"
                    rel="noopener noreferrer"
                  >
                    <span>{deposit.toAddress}</span>
                    <span>{shortenAddressLong(deposit.toAddress ?? "")}</span>
                  </SecondaryLink>
                </div>
              </div>
            </Info>
            <Info>
              <h3>Estimated time of arrival</h3>
              <div>
                <div>{getConfirmationDepositTime(deposit.toChain)}</div>
              </div>
            </Info>
          </div>
          <Button onClick={() => toggle({ showConfirmationScreen: false })}>
            Close
          </Button>
        </InfoSection>
      </Wrapper>
    </Layout>
  );
}