import { useEffect, useState, useMemo } from 'react';
import { Tablist, Pane } from '@cybercongress/gravity';
import Slider from 'rc-slider';
import BigNumber from 'bignumber.js';
import { useIbcDenom } from 'src/contexts/ibcDenom';
import { useQueryClient } from 'src/contexts/queryClient';
import { Btn, ItemBalance } from './ui';
import 'rc-slider/assets/index.css';
import { formatNumber, getDisplayAmount } from '../../utils/utils';
import { CYBER } from '../../utils/config';
import ERatio from './eRatio';
import {
  Dots,
  CardStatisics,
  ValueImg,
  DenomArr,
  Tabs,
} from '../../components';
import useGetSlots from './useGetSlots';
import { TableSlots } from '../energy/ui';
import ActionBar from './actionBar';
import { useAdviser } from 'src/features/adviser/context';
import Display from 'src/components/containerGradient/Display/Display';
import ImgDenom from 'src/components/valueImg/imgDenom';
import { useAppSelector } from 'src/redux/hooks';
import { selectCurrentAddress } from 'src/redux/features/pocket';
import styles from './Mint.module.scss';

const BASE_VESTING_TIME = 86401;
const BASE_MAX_MINT_TIME = 41;

const grid = {
  display: 'grid',
  gridTemplateColumns: '250px 1fr 250px',
  gridTemplateRows: 'auto',
  alignItems: 'center',
  margin: '64px 8px 0 8px',
  gridGap: '16px 16px',
  position: 'relative',
  paddingBottom: '150px',
};

const returnColorDot = (marks) => {
  return {
    style: {
      color: '#fff',
      whiteSpace: 'nowrap',
    },
    label: marks,
  };
};

const SLOTS_MAX = 16;

enum SelectedState {
  millivolt = 'millivolt',
  milliampere = 'milliampere',
}

function Mint() {
  const queryClient = useQueryClient();
  const { traseDenom } = useIbcDenom();
  const [updateAddress, setUpdateAddress] = useState(0);
  // const { balance } = useGetBalance(addressActive, updateAddress);
  const [selected, setSelected] = useState<SelectedState>(
    SelectedState.milliampere
  );
  const [value, setValue] = useState(0);
  const [valueDays, setValueDays] = useState(1);
  const [max, setMax] = useState(0);
  const [maxMintTime, setMaxMintTime] = useState(BASE_MAX_MINT_TIME);
  const [eRatio, setERatio] = useState(0);
  const [resourceToken, setResourceToken] = useState(0);
  const [height, setHeight] = useState(0);
  const [resourcesParams, setResourcesParams] = useState(null);
  const [balanceHydrogen, SetBalanceHydrogen] = useState(0);

  const addressActive = useAppSelector(selectCurrentAddress);
  const { slotsData, vested, loadingAuthAccounts, originalVesting } =
    useGetSlots(addressActive, updateAddress);

  const { setAdviser } = useAdviser();

  useEffect(() => {
    const availableSlots =
      SLOTS_MAX -
      slotsData.filter((slot) => slot.status === 'Unfreezing').length;

    setAdviser(
      <p>
        {slotsData.length === 0 ? (
          <>investmint - temporarily invest tokens to mint tokens</>
        ) : (
          <>you have {availableSlots} slots available for investmint</>
        )}
        <br />
        choose <ValueImg text="milliampere" /> or <ValueImg text="millivolt" />{' '}
        to mint, the amount of <ValueImg text="hydrogen" /> to invest, and the
        timeframe
      </p>
    );
  }, [setAdviser, slotsData]);

  useEffect(() => {
    const getBalanceH = async () => {
      let amountHydrogen = 0;
      if (queryClient && addressActive !== null) {
        const responseBalance = await queryClient.getBalance(
          addressActive,
          CYBER.DENOM_LIQUID_TOKEN
        );
        if (responseBalance.amount) {
          amountHydrogen = parseFloat(responseBalance.amount);
        }
      }
      SetBalanceHydrogen(amountHydrogen);
    };
    getBalanceH();
  }, [queryClient, addressActive]);

  useEffect(() => {
    const getParam = async () => {
      const responseResourcesParams = await queryClient.resourcesParams();
      if (
        responseResourcesParams.params &&
        Object.keys(responseResourcesParams.params).length > 0
      ) {
        const { params } = responseResourcesParams;
        setResourcesParams((item) => ({ ...item, ...params }));
      }

      const responseGetHeight = await queryClient.getHeight();
      if (responseGetHeight > 0) {
        setHeight(responseGetHeight);
      }
    };
    getParam();
  }, [queryClient]);

  useEffect(() => {
    let vestedTokens = 0;
    let maxValue = 0;
    if (originalVesting[CYBER.DENOM_LIQUID_TOKEN] > 0) {
      vestedTokens =
        parseFloat(originalVesting[CYBER.DENOM_LIQUID_TOKEN]) -
        parseFloat(vested[CYBER.DENOM_LIQUID_TOKEN]);
    }
    if (balanceHydrogen > 0) {
      maxValue = Math.floor(balanceHydrogen) - vestedTokens;
    } else {
      maxValue = 0;
    }

    setMax(maxValue);
  }, [balanceHydrogen, vested, originalVesting]);

  useEffect(() => {
    let vestedTokens = 0;
    if (originalVesting[CYBER.DENOM_LIQUID_TOKEN] > 0) {
      vestedTokens =
        parseFloat(originalVesting[CYBER.DENOM_LIQUID_TOKEN]) -
        parseFloat(vested[CYBER.DENOM_LIQUID_TOKEN]);
    }
    if (vestedTokens > 0 && balanceHydrogen > 0) {
      const procent = (vestedTokens / balanceHydrogen) * 100;
      const eRatioTemp = Math.floor(procent * 100) / 100;
      setERatio(eRatioTemp);
    } else {
      setERatio(0);
    }
  }, [balanceHydrogen, vested, originalVesting]);

  useEffect(() => {
    let maxValueTaime = BASE_MAX_MINT_TIME;
    if (resourcesParams !== null) {
      const {
        halvingPeriodAmpereBlocks: halvingPeriodBlocksAmpere,
        halvingPeriodVoltBlocks: halvingPeriodBlocksVolt,
      } = resourcesParams;
      let halvingPeriod = 0;
      if (selected === 'millivolt') {
        halvingPeriod = halvingPeriodBlocksVolt;
      } else {
        halvingPeriod = halvingPeriodBlocksAmpere;
      }

      const halving = 2 ** Math.floor(height / halvingPeriod);
      maxValueTaime = Math.floor(
        (halvingPeriod * 5 * halving) / BASE_VESTING_TIME
      );
    }
    setMaxMintTime(maxValueTaime);
  }, [resourcesParams, height, selected]);

  useEffect(() => {
    let token = 0;
    if (resourcesParams !== null && value > 0 && valueDays > 0) {
      const hydrogen = value;
      const {
        baseInvestmintAmountVolt,
        baseInvestmintAmountAmpere,
        baseInvestmintPeriodVolt,
        baseInvestmintPeriodAmpere,
        halvingPeriodAmpereBlocks: halvingPeriodBlocksAmpere,
        halvingPeriodVoltBlocks: halvingPeriodBlocksVolt,
      } = resourcesParams;
      let baseLength = 0;
      let baseAmount = 0;
      let halvingPeriod = 0;
      if (selected === 'millivolt') {
        baseLength = baseInvestmintPeriodVolt;
        baseAmount = parseFloat(baseInvestmintAmountVolt.amount);
        halvingPeriod = halvingPeriodBlocksVolt;
      } else {
        baseLength = baseInvestmintPeriodAmpere;
        baseAmount = parseFloat(baseInvestmintAmountAmpere.amount);
        halvingPeriod = halvingPeriodBlocksAmpere;
      }
      const vestingTime = valueDays * BASE_VESTING_TIME;
      const cycles = vestingTime / baseLength;
      const base = hydrogen / baseAmount;
      const halving = 0.5 ** Math.floor(height / halvingPeriod);

      token = Math.floor(cycles * base * halving);
    }
    setResourceToken(token);
  }, [value, valueDays, selected, resourcesParams, height]);

  const updateFunc = () => {
    setValue(0);
    setValueDays(1);
    setUpdateAddress(updateAddress + 1);
  };

  const vestedA = useMemo(() => {
    let amountA = 0;
    if (originalVesting.milliampere > 0) {
      const [{ coinDecimals }] = traseDenom('milliampere');
      const vestedTokensA = new BigNumber(originalVesting.milliampere)
        .minus(vested.milliampere)
        .toNumber();
      amountA = getDisplayAmount(vestedTokensA, coinDecimals);
    }
    return amountA;
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [vested, originalVesting]);

  const vestedV = useMemo(() => {
    let amountV = 0;
    if (originalVesting.millivolt > 0) {
      const [{ coinDecimals }] = traseDenom('millivolt');
      const vestedTokensA = new BigNumber(originalVesting.millivolt)
        .minus(vested.millivolt)
        .toNumber();
      amountV = getDisplayAmount(vestedTokensA, coinDecimals);
    }
    return amountV;
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [vested, originalVesting]);

  return (
    <>
      <main className="block-body">
        <Pane
          marginTop={10}
          marginBottom={50}
          display="grid"
          gridTemplateColumns="300px 300px 300px"
          gridGap="20px"
          justifyContent="center"
        >
          <CardStatisics
            title={<ValueImg text="milliampere" />}
            value={formatNumber(vestedA)}
          />
          <CardStatisics
            title={<ValueImg text="millivolt" />}
            value={formatNumber(vestedV)}
          />
          <CardStatisics
            title="My Energy"
            value={`${formatNumber(vestedA * vestedV)} W`}
          />
        </Pane>

        <div className={styles.tabs}>
          <Tabs
            options={['milliampere', 'millivolt'].map((item) => {
              return {
                text: <DenomArr denomValue={item} />,
                key: item,
                onClick: () => setSelected(item),
              };
            })}
            selected={selected}
          />
        </div>

        <div style={grid}>
          <div
            style={{
              display: 'grid',
              alignContent: 'space-evenly',
              height: '100%',
            }}
          >
            {/* <ItemBalance text="Liquid balance" amount={balance.available} /> */}
            <ItemBalance
              text="Liquid"
              amount={max}
              currency={<ValueImg text={CYBER.DENOM_LIQUID_TOKEN} />}
            />
            <ItemBalance
              text="Frozen"
              amount={
                loadingAuthAccounts
                  ? null
                  : originalVesting[CYBER.DENOM_LIQUID_TOKEN] -
                    vested[CYBER.DENOM_LIQUID_TOKEN]
              }
              currency={<ValueImg text={CYBER.DENOM_LIQUID_TOKEN} />}
            />
          </div>
          <div
            style={{
              height: '100%',
              display: 'grid',
              gridTemplateRows: '1fr 1fr 1fr',
              width: '100%',
              justifyItems: 'center',
              padding: '0 10px',
            }}
          >
            <Pane fontSize="30px">{resourceToken}</Pane>
            <Slider
              value={value}
              min={0}
              max={max}
              marks={{
                [max]: returnColorDot(`${formatNumber(max)} H`),
              }}
              onChange={(eValue) => setValue(eValue)}
              trackStyle={{ backgroundColor: '#3ab793' }}
              railStyle={{ backgroundColor: '#97979775' }}
              dotStyle={{
                backgroundColor: '#97979775',
                borderColor: '#97979775',
              }}
              activeDotStyle={{
                borderColor: '#3ab793',
                backgroundColor: '#3ab793',
              }}
              handleStyle={{
                border: 'none',
                backgroundColor: '#3ab793',
              }}
            />

            <Slider
              value={valueDays}
              min={1}
              max={maxMintTime}
              marks={{
                1: returnColorDot('1 day'),
                [maxMintTime]: returnColorDot(`${maxMintTime} days`),
              }}
              onChange={(eValue) => setValueDays(eValue)}
              trackStyle={{ backgroundColor: '#3ab793' }}
              railStyle={{ backgroundColor: '#97979775' }}
              dotStyle={{
                backgroundColor: '#97979775',
                borderColor: '#97979775',
              }}
              activeDotStyle={{
                borderColor: '#3ab793',
                backgroundColor: '#3ab793',
              }}
              handleStyle={{
                border: 'none',
                backgroundColor: '#3ab793',
              }}
            />
          </div>
          <div>
            <ERatio eRatio={eRatio} />
          </div>
          {value > 0 && (
            <p className={styles.text}>
              You’re freezing <strong>{formatNumber(value)}</strong>{' '}
              <DenomArr denomValue="hydrogen" onlyImg /> for{' '}
              <strong>{valueDays} days</strong>. It will release{' '}
              <strong>{resourceToken}</strong>{' '}
              <DenomArr denomValue={selected} onlyImg /> for you. At the end of
              the period, {selected} becomes liquid automatically, but you can
              use it to boost ranking during the freeze. You can have only{' '}
              <strong>{SLOTS_MAX} slots</strong> for investmint at a time.
            </p>
          )}
        </div>

        {loadingAuthAccounts ? (
          <Dots big />
        ) : (
          <Display noPaddingX>
            <TableSlots data={slotsData} />
          </Display>
        )}
      </main>
      <ActionBar
        value={value}
        selected={selected}
        valueDays={valueDays}
        resourceToken={resourceToken}
        updateFnc={updateFunc}
        addressActive={addressActive}
      />
    </>
  );
}

export default Mint;

Synonyms

cyb/src/index.tsx
pussy-ts/src/index.tsx
bostrom.network/src/pages/Index.tsx
pussy-landing/src/pages/index.tsx
pussy.meme/src/pages/index.tsx
pussy-ts/src/containers/txs/index.tsx
cyb/src/containers/mint/index.tsx
pussy-ts/src/components/ButtonSwap/index.tsx
pussy-ts/src/components/denom/index.tsx
cyb/src/containers/Objects/index.tsx
cyb/src/components/btnGrd/index.tsx
pussy-ts/src/components/Select/index.tsx
cyb/src/components/actionBar/index.tsx
pussy-ts/src/components/BandwidthBar/index.tsx
cyb/src/components/Select/index.tsx
pussy-ts/src/containers/portal/index.tsx
pussy-ts/src/components/btnGrd/index.tsx
cyb/src/components/TextMarkdown/index.tsx
cyb/src/containers/energy/index.tsx
pussy-ts/src/components/MainContainer/index.tsx
pussy-ts/src/components/actionBar/index.tsx
cyb/src/containers/portal/index.tsx
cyb/src/components/ButtonSwap/index.tsx
cyb/src/containers/nebula/index.tsx
pussy-ts/src/components/DonutChart/index.tsx
cyb/src/components/DonutChart/index.tsx
pussy-ts/src/containers/nebula/index.tsx
cyb/src/components/BandwidthBar/index.tsx
pussy-ts/src/containers/energy/index.tsx
cyb/src/components/denom/index.tsx
cyb/src/containers/sigma/index.tsx
cyb/src/components/Input/index.tsx
pussy-ts/src/containers/sigma/index.tsx
pussy-ts/src/containers/taverna/index.tsx
pussy-ts/src/components/Input/index.tsx
cyb/src/containers/blok/index.tsx
cyb/src/components/PDF/index.tsx
cyb/src/containers/txs/index.tsx
cyb/src/containers/taverna/index.tsx
cyb/src/components/MainContainer/index.tsx
pussy-ts/src/components/TextMarkdown/index.tsx
pussy-ts/src/components/PDF/index.tsx
cyb/src/containers/portal/citizenship/index.tsx
pussy-landing/src/components/xp/btnGrd/index.tsx
cyb/src/containers/portal/pasport/index.tsx
pussy-landing/src/components/xp/stars/index.tsx
cyb/src/components/buttons/ButtonIcon/index.tsx
cyb/src/containers/wasm/codes/index.tsx
pussy-ts/src/features/ipfs/Drive/index.tsx
pussy-ts/src/containers/portal/gift/index.tsx
pussy-ts/src/features/ipfs/ipfsSettings/index.tsx
pussy-ts/src/components/buttons/ButtonIcon/index.tsx
pussy-ts/src/containers/portal/release/index.tsx
cyb/src/containers/portal/release/index.tsx
cyb/src/features/ipfs/Drive/index.tsx
pussy-ts/src/containers/portal/pasport/index.tsx
cyb/src/features/ipfs/ipfsSettings/index.tsx
pussy-ts/src/containers/portal/citizenship/index.tsx
cyb/src/containers/portal/gift/index.tsx
cyb/src/components/contentIpfs/component/gateway/index.tsx
pussy-ts/src/containers/portal/components/ReleaseStatus/index.tsx
pussy-ts/src/components/contentIpfs/component/gateway/index.tsx
pussy-ts/src/containers/sigma/components/CardPassport/index.tsx
cyb/src/containers/sigma/components/CardPassport/index.tsx
cyb/src/components/contentIpfs/component/img/index.tsx
pussy-ts/src/components/contentIpfs/component/img/index.tsx
cyb/src/containers/portal/components/ActionBar/index.tsx
pussy-ts/src/components/contentIpfs/component/link/index.tsx
cyb/src/containers/portal/components/ReleaseStatus/index.tsx
cyb/src/containers/portal/components/stars/index.tsx
pussy-ts/src/containers/portal/components/stars/index.tsx
cyb/src/components/contentIpfs/component/link/index.tsx
pussy-ts/src/containers/sigma/components/cardUi/TitleCard/index.tsx
cyb/src/containers/sigma/components/cardUi/TitleCard/index.tsx
cyb/src/containers/sigma/components/cardUi/RowBalancesDetails/index.tsx
pussy-ts/src/containers/sigma/components/cardUi/RowBalancesDetails/index.tsx

Neighbours