import React , { ReactNode , useEffect , useMemo , useState } from "react" ; import { BigNumber , ethers } from "ethers" ; import { useWeb3React } from "@web3-react/core" ; import styled , { keyframes } from "styled-components" ; import { Redirect } from "react-router-dom" ; import { BaseLink , Title } from "shared/lib/designSystem" ; import colors from "shared/lib/designSystem/colors" ; import PerformanceSection from "./PerformanceSection" ; import { useVaultData , useV2VaultData } from "shared/lib/hooks/web3DataContext" ; import { formatSignificantDecimals , isPracticallyZero , } from "shared/lib/utils/math" ; import sizes from "shared/lib/designSystem/sizes" ; import VaultActivity from "../../components/Vault/VaultActivity" ; import usePullUp from "../../hooks/usePullUp" ; import { CHAINID } from "shared/lib/utils/env" ; import { CHAINID_TO_NATIVE_TOKENS , getDisplayAssets , getEtherscanURI , hasVaultVersion , VaultAddressMap , VaultList , VaultOptions , VaultVersion , VaultVersionList , VaultNameOptionMap } from "shared/lib/constants/constants" ; import { productCopies } from "shared/lib/components/Product/productCopies" ; import useVaultOption from "../../hooks/useVaultOption" ; import { getVaultColor } from "shared/lib/utils/vault" ; import { getAssetColor , getAssetDisplay , getAssetLogo , getAssetDecimals } from "shared/lib/utils/asset" ; import { Container } from "react-bootstrap" ; import theme from "shared/lib/designSystem/theme" ; import { getVaultURI } from "../../constants/constants" ; import DesktopActionForm from "../../components/Vault/VaultActionsForm/DesktopActionForm" ; import YourPosition from "../../components/Vault/YourPosition" ; import { truncateAddress } from "shared/lib/utils/address" ; import { ExternalIcon } from "shared/lib/assets/icons/icons" ; import useRedirectOnSwitchChain from "../../hooks/useRedirectOnSwitchChain" ; import useRedirectOnWrongChain from "../../hooks/useRedirectOnWrongChain" ; import Banner from "shared/lib/components/Banner/Banner" ; import TreasuryActionForm from "../../components/Vault/VaultActionsForm/TreasuryActionsForm" ; import VaultInformation from "../../components/Deposit/VaultInformation" ; import useVaultActivity from "shared/lib/hooks/useVaultActivity" ; import { useWhitelist } from "../../hooks/useWhitelist" ; import { isProduction } from "shared/lib/utils/env" ; const { formatUnits } = ethers . utils ; const DepositPageContainer = styled ( Container ) `
  @media (min-width: ${ sizes . xl }px) {
    max-width: 1140px;
  }
` ; const HeroDescriptionContainer = styled ( Container ) `
  @media (min-width: ${ sizes . xl }px) {
    max-width: 1140px;
  }
  top: 50%;
  left: 50%;
  position: absolute;
  transform: translate(-50%, -50%);
` ; const HeroContainer = styled . div < { color : string ; } > `
  background: linear-gradient(
    96.84deg,
    ${ ( props ) => props . color }29 1.04%,
    ${ ( props ) => props . color }07 98.99%
  );
  height: 400px;
  padding: 40px 0;
  overflow: hidden;
` ; const HeroText = styled ( Title ) `
  font-size: 56px;
  line-height: 64px;
  margin-bottom: 24px;
` ; const livelyAnimation = ( position ) => keyframes `
  0% {
    background-position-x: ${ position === "top" ? 0 : 100 }%;
  }

  50% {
    background-position-x: ${ position === "top" ? 100 : 0 }%;
  }

  100% {
    background-position-x: ${ position === "top" ? 0 : 100 }%;
  }
` ; const LiveryBar = styled . div < { color : string ; position : "top" | "bottom" ; } > `
  position: absolute;
  ${ ( props ) => props . position }: 0;
  left: 0;
  width: 100%;
  height: 8px;
  background: ${ ( props ) => `linear-gradient(
    270deg,
    ${ props . color }00 15%,
    ${ props . color } 50%,
    ${ props . color }00 85%
  )` };
  background-size: 200%;
  animation: 10s ${ ( props ) => livelyAnimation ( props . position ) } linear infinite;
` ; const AttributePill = styled . div < { color : string ; } > `
  display: flex;
  background: ${ ( props ) => props . color }29;
  color: ${ colors . primaryText };
  border-radius: ${ theme . border . radiusSmall };
  font-family: VCR, sans-serif;
  font-style: normal;
  font-weight: normal;
  font-size: 12px;
  line-height: 16px;

  text-align: center;
  letter-spacing: 1.5px;
  text-transform: uppercase;
` ; const TagPill = styled ( AttributePill ) `
  padding: 16px;
` ; const AttributeVersionSelector = styled . div < { color : string ; active : boolean ; } > `
  padding: 16px;
  border-radius: ${ theme . border . radiusSmall };
  border: ${ theme . border . width } ${ theme . border . style }
    ${ ( props ) => ( props . active ? props . color : "transparent" ) };
` ; const SplashImage = styled . div `
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 0;
  right: 0;
  width: 600px;
  height: 100%;

  @media (max-width: ${ sizes . xl }px) {
    display: none;
  }
` ; const DesktopActionsFormContainer = styled . div `
  display: flex;

  @media (max-width: ${ sizes . md }px) {
    display: none;
  }

  @media (min-width: ${ sizes . xl }px) {
    padding: 0px 45px 0px 30px;
  }
` ; const ContractButton = styled . div < { color : string ; } > `
  @media (max-width: ${ sizes . md }px) {
    display: flex;
    justify-content: center;
    padding: 10px 16px;
    background: ${ ( props ) => props . color }14;
    border-radius: 100px;
    margin-left: 16px;
    margin-right: 16px;
    margin-top: -15px;
    margin-bottom: 48px;
  }
  @media (min-width: ${ sizes . md + 1 }px) {
    display: none !important;
  }
` ; const ContractButtonTitle = styled ( Title ) `
  letter-spacing: 1px;
` ; const DepositPage = ( ) => { const { vaultOption , vaultVersion } = useVaultOption ( ) ; const { active , chainId } = useWeb3React ( ) ; useRedirectOnSwitchChain ( chainId ) ; useRedirectOnWrongChain ( vaultOption , chainId ) ; usePullUp ( ) ; const { status , deposits , vaultLimit } = useVaultData ( vaultOption || VaultList [ 0 ] ) ; const { data : { asset , cap , decimals , totalBalance } , loading , } = useV2VaultData ( vaultOption || VaultList [ 0 ] ) ; const isLoading = status === "loading" || loading ; const premiumDecimals = getAssetDecimals ( "USDC" ) ; const activities = useVaultActivity ( vaultOption ! , vaultVersion ) ; const web3Whitelist = useWhitelist ( ) ; const whitelist = ! isProduction ( ) ? ( active ? "T-PERP-C" : undefined ) : web3Whitelist ; const depositForm = useMemo ( ( ) => { if ( ! vaultOption ) { return < TreasuryActionForm variant = "desktop" / > ; } return whitelist === Object . keys ( VaultNameOptionMap ) [ Object . values ( VaultNameOptionMap ) . indexOf ( vaultOption ) ] ? < DesktopActionForm vault = { { vaultOption , vaultVersion } } /> : < TreasuryActionForm variant = "desktop" / > ; } , [ whitelist , vaultOption , vaultVersion ] ) ; const totalYields = useMemo ( ( ) => { const yields = activities . activities . map ( ( activity ) => { return ( activity . type === "sales" ) ? Number ( activity . premium ) : 0 ; } ) . reduce ( ( totalYield , roundlyYield ) => totalYield + roundlyYield , 0 ) ; return parseFloat ( formatSignificantDecimals ( formatUnits ( yields , premiumDecimals ) , 2 ) ) ; } , [ activities , premiumDecimals ] ) ; const [ totalDepositStr ] = useMemo ( ( ) => { switch ( vaultVersion ) { case "v1" : return [ parseFloat ( formatSignificantDecimals ( formatUnits ( deposits , decimals ) , 2 ) ) , parseFloat ( formatSignificantDecimals ( formatUnits ( vaultLimit , decimals ) ) ) , ] ; case "v2" : return [ parseFloat ( formatSignificantDecimals ( formatUnits ( totalBalance , decimals ) , 2 ) ) , parseFloat ( formatSignificantDecimals ( formatUnits ( cap , decimals ) ) ) , ] ; } } , [ cap , decimals , deposits , totalBalance , vaultLimit , vaultVersion ] ) ; const vaultInformation = ( < VaultInformation loading = { isLoading } vaultDeposit = { totalDepositStr } vaultYield = { totalYields } displayData = { ! isLoading && totalYields === 0 ? { deposit : "---" , yield : "---" } : undefined } asset = { asset } / > ) ; /**
     * Redirect to homepage if no clear vault is chosen
     */ if ( ! vaultOption ) { return < Redirect to = "/" / > ; } /**
     * Redirect to v1 if vault version given is invalid
     */ if ( chainId && ! hasVaultVersion ( vaultOption , vaultVersion , chainId ) ) { const availableVaultVersions = VaultVersionList . filter ( ( version ) => hasVaultVersion ( vaultOption , version , chainId ) ) ; if ( availableVaultVersions . length <= 0 ) { return < Redirect to = "/" / > ; } return ( < Redirect to = { getVaultURI ( vaultOption , availableVaultVersions [ availableVaultVersions . length - 1 ] ) } / > ) ; } return ( < > < HeroSection vaultInformation = { vaultInformation } vaultOption = { vaultOption } variant = { vaultVersion } v1Inactive = { vaultVersion === "v1" ? ! isLoading && vaultLimit . isZero ( ) : undefined } /> < DepositPageContainer className = "py-5" > < div className = "row" > { VaultAddressMap [ vaultOption ] [ vaultVersion ] && chainId && ( < BaseLink to = { `${ getEtherscanURI ( chainId ) }/address/${ VaultAddressMap [ vaultOption ] [ vaultVersion ] ! }` } target = "_blank" rel = "noreferrer noopener" className = "w-100" > < ContractButton color = { getVaultColor ( vaultOption ) } > < ContractButtonTitle fontSize = { 14 } lineHeight = { 20 } color = { getVaultColor ( vaultOption ) } className = "mr-2" > { `CONTRACT: ${ truncateAddress ( VaultAddressMap [ vaultOption ] [ vaultVersion ] ! ) }` } < /ContractButtonTitle> < ExternalIcon color = { getVaultColor ( vaultOption ) } / > < /ContractButton> < /BaseLink>)} < PerformanceSection vault = { { vaultOption , vaultVersion } } active = { ! ( vaultVersion === "v1" && isPracticallyZero ( vaultLimit , decimals ) ) } /> { } < DesktopActionsFormContainer className = "flex-column col-xl-5 offset-xl-1 col-md-6" > { depositForm } < /DesktopActionsFormContainer> < /div> < VaultActivity vault = { { vaultOption , vaultVersion } } /> < /DepositPageContainer> { } < YourPosition vault = { { vaultOption , vaultVersion } } variant = "desktop" / > < />); } ; const HeroSection = ( { vaultInformation , vaultOption , variant , v1Inactive } ) => { const { chainId } = useWeb3React ( ) ; const color = getVaultColor ( vaultOption ) ; const logo = useMemo ( ( ) => { const asset = getDisplayAssets ( vaultOption ) ; const Logo = getAssetLogo ( asset ) ; switch ( asset ) { case "WETH" : return < Logo width = "55%" style = { { marginTop : 40 } } />; case "WBTC" : return < Logo height = "190%" style = { { marginTop : 40 } } />; case "USDC" : case "yvUSDC" : return ( < Logo height = "180%" style = { { marginTop : 40 , } } markerConfig = { { right : "0px" , border : "none" , } } />); case "AAVE" : return < Logo showBackground / > ; case "WAVAX" : return < Logo showBackground / > ; default : return < Logo />; } } , [ vaultOption ] ) ; const liveryHeroSection = useMemo ( ( ) => { switch ( variant ) { case "v2" : return ( < > < LiveryBar color = { color } position = "top" / > < LiveryBar color = { color } position = "bottom" / > < />); default : return < > < />; } } , [ color , variant ] ) ; return ( < > { } { variant === "v1" && chainId && hasVaultVersion ( vaultOption , "v2" , chainId ) && ( < Banner color = { color } message = { v1Inactive ? "V1 vaults are now inactive and do not accept deposits" : "V2 vaults are now live" } linkURI = { getVaultURI ( vaultOption , "v2" ) } linkText = "Switch to V2" > < /Banner>)} { } { chainId && chainId !== CHAINID . ETH_MAINNET && ( < BridgeBanner > < /BridgeBanner>)} < HeroContainer className = "position-relative" color = { color } > < HeroDescriptionContainer className = "container" > < div className = "row mx-lg-n1 position-relative" > < div style = { { zIndex : 1 } } className = "col-xl-6 d-flex flex-column" > < div className = "d-flex flex-row my-3" > { productCopies [ vaultOption ] . tags . map ( ( tag ) => ( < TagPill className = "mr-2 text-uppercase" key = { tag } color = { color } > { tag } < /TagPill>))} < AttributePill className = "mr-2 text-uppercase" color = { color } > { [ ... VaultVersionList ] . map ( ( version ) => chainId && hasVaultVersion ( vaultOption , version , chainId ) ? ( < BaseLink to = { getVaultURI ( vaultOption , version ) } key = { version } > < AttributeVersionSelector active = { version === variant } color = { color } > < Title color = { color } > { version } < /Title> < /AttributeVersionSelector> < /BaseLink>) : null)} < /AttributePill> < /div> < HeroText > { productCopies [ vaultOption ] . title } < /HeroText> { vaultInformation } < /div> < SplashImage className = "position-absolute col-xl-6" > { logo } < /SplashImage> < /div> < /HeroDescriptionContainer> { liveryHeroSection } < /HeroContainer> < />); } ; const BridgeBanner = ( ) => { const { chainId , library , account } = useWeb3React ( ) ; const [ balance , setBalance ] = useState < BigNumber > ( BigNumber . from ( 1 ) ) ; const chainsSupportedForBridging = chainId === CHAINID . AVAX_MAINNET ; const currentChainId = chainId as CHAINID ; useEffect ( ( ) => { ( async ( ) => { if ( library && chainsSupportedForBridging ) { const balance = await library . getBalance ( account ) ; setBalance ( balance ) ; } } ) ( ) ; } , [ library , account , chainsSupportedForBridging ] ) ; if ( ! chainsSupportedForBridging ) return null ; const token = CHAINID_TO_NATIVE_TOKENS [ currentChainId ] ; const color = getAssetColor ( token ) ; const assetDisplay = getAssetDisplay ( token ) ; return chainId && balance . isZero ( ) ? ( < Banner color = { color } message = { `You do not have an ${ assetDisplay } balance.` } linkText = "Bridge" linkURI = "https://bridge.avax.network/" linkOpensNewTab > < /Banner>) : null; } ; export default DepositPage ;