synapsecns/sanguine

View on GitHub
packages/widget/src/hooks/useValidations.tsx

Summary

Maintainability
B
4 hrs
Test Coverage
import { useContext, useMemo } from 'react'
import { ZeroAddress } from 'ethers'
import { Web3Context } from 'providers/Web3Provider'

import { useBridgeState } from '@/state/slices/bridge/hooks'
import { checkExists } from '@/utils/checkExists'
import { useCurrentTokenBalance } from '@/hooks/useCurrentTokenBalance'
import { stringToBigInt } from '@/utils/stringToBigInt'
import { isOnlyZeroes } from '@/utils/isOnlyZeroes'
import { useWalletState } from '@/state/slices/wallet/hooks'

export const useValidations = (): {
  hasValidSelections: boolean
  hasEnoughBalance: boolean
  isInputValid: boolean
  isApproved: boolean
  onSelectedChain: boolean
} => {
  const {
    debouncedInputAmount,
    originChainId,
    originToken,
    destinationChainId,
    destinationToken,
  } = useBridgeState()

  const { balances, allowance } = useWalletState()

  const currentTokenBalance = useCurrentTokenBalance()

  const web3Context = useContext(Web3Context)
  const { networkId } = web3Context.web3Provider

  const hasValidSelections: boolean = useMemo(() => {
    return Boolean(
      originChainId && originToken && destinationChainId && destinationToken
    )
  }, [originChainId, originToken, destinationChainId, destinationToken])

  const hasEnoughBalance: boolean = useMemo(() => {
    if (
      !checkExists(debouncedInputAmount) ||
      !checkExists(currentTokenBalance.rawBalance)
    ) {
      return false
    } else {
      const formattedInput = stringToBigInt(
        debouncedInputAmount,
        currentTokenBalance.decimals
      )
      return Boolean(BigInt(currentTokenBalance.rawBalance) >= formattedInput)
    }
  }, [balances, debouncedInputAmount, originToken, destinationToken])

  const isInputValid: boolean = useMemo(() => {
    if (debouncedInputAmount === '') return false
    if (isOnlyZeroes(debouncedInputAmount)) return false
    return true
  }, [debouncedInputAmount])

  const onSelectedChain: boolean = useMemo(() => {
    return networkId === originChainId
  }, [originChainId, networkId])

  const formattedInputAmount: bigint = useMemo(() => {
    return stringToBigInt(
      debouncedInputAmount ?? '0',
      originToken?.decimals[originChainId]
    )
  }, [debouncedInputAmount, originToken])

  const isApproved: boolean = useMemo(() => {
    if (originToken?.addresses[originChainId] === ZeroAddress) {
      return true
    }
    if (!checkExists(allowance)) return true
    if (!formattedInputAmount) return true
    return (
      formattedInputAmount <=
      stringToBigInt(allowance, originToken?.decimals[originChainId])
    )
  }, [formattedInputAmount, allowance, originToken, originChainId])

  return {
    hasValidSelections,
    hasEnoughBalance,
    isInputValid,
    isApproved,
    onSelectedChain,
  }
}