import { ActionBar } from '@cybercongress/gravity';
import React, { Component } from 'react';
import { createSearchParams } from 'react-router-dom';
import { CID_FOLLOW, CID_TWEET } from 'src/constants/app';
import { PATTERN_IPFS_HASH } from 'src/constants/patterns';
import { useBackend } from 'src/contexts/backend/backend';
import { useQueryClient } from 'src/contexts/queryClient';
import { useSigningClient } from 'src/contexts/signerClient';
import { routes } from 'src/routes';
import { sendCyberlink } from 'src/services/neuron/neuronApi';
import { getTxs } from 'src/services/transactions/lcd';
import { AccountValue } from 'src/types/defaultAccount';
import {
  ActionBar as ActionBarComp,
  ActionBarContentText,
  Button,
  Confirmed,
  Dots,
  RewardsDelegators,
  StartStageSearchActionBar,
  TransactionError,
  TransactionSubmitted,
} from '../../../../components';
import withIpfsAndSigner from '../../../../hocs/withIpfsAndSigner';
import { LEDGER } from '../../../../utils/config';
import { friendlyErrorMessage } from 'src/utils/errorMessages';

const { STAGE_INIT, STAGE_READY, STAGE_SUBMITTED, STAGE_CONFIRMING, STAGE_CONFIRMED, STAGE_ERROR } =
  LEDGER;

type Props = {
  defaultAccount: AccountValue;

  type: string;

  addressSend: string;

  // can be followed
  follow: boolean;
  tweets: boolean;

  signer: ReturnType<typeof useSigningClient>['signer'];
  signingClient: ReturnType<typeof useSigningClient>['signingClient'];
  ipfsApi: ReturnType<typeof useBackend>['ipfsApi'];
  senseApi: ReturnType<typeof useBackend>['senseApi'];
  queryClient: ReturnType<typeof useQueryClient>;

  updateAddress: () => void;

  // add more
};

class ActionBarContainer extends Component<Props> {
  constructor(props: Props) {
    super(props);
    this.state = {
      stage: STAGE_INIT,
      address: null,
      file: null,
      toSend: '',
      toSendAddres: '',
      contentHash: '',
      txMsg: null,
      txHash: null,
      txHeight: null,
      rewards: null,
      errorMessage: null,
      bandwidth: {
        remained: 0,
        max_value: 0,
      },
    };
    this.timeOut = null;
    this.inputOpenFileRef = React.createRef();
  }

  calculationIpfsTo = async (contentHash) => {
    const { file } = this.state;
    const { ipfsApi } = this.props;

    let toCid = contentHash;

    if (file !== null) {
      toCid = await ipfsApi.addContent(file);
    } else if (!contentHash.match(PATTERN_IPFS_HASH)) {
      toCid = await ipfsApi.addContent(contentHash);
    }

    return toCid;
  };

  generateTxSendKplr = async () => {
    const { contentHash, toSendAddres, toSend } = this.state;
    const {
      type,
      addressSend,
      follow,
      tweets,
      signer,
      signingClient,
      ipfsApi,
      senseApi,
      queryClient,
    } = this.props;
    // const amount = parseFloat(toSend) * DIVISOR_CYBER_G;
    // const fee = {
    //   amount: [],
    //   gas: DEFAULT_GAS_LIMITS.toString(),
    // };

    if (signer && signingClient) {
      const [{ address }] = await signer.getAccounts();
      try {
        let txHash = null;

        if (type === 'security') {
          if (address === addressSend) {
            if (!queryClient) {
              return;
            }

            const dataTotalRewards = await queryClient.delegationTotalRewards(address);

            if (dataTotalRewards?.rewards) {
              const { rewards } = dataTotalRewards;
              const validatorAddress = [];
              Object.keys(rewards).forEach((key) => {
                if (rewards[key].reward) {
                  validatorAddress.push(rewards[key].validatorAddress);
                }
              });

              const gasLimitsRewards = 100000 * Object.keys(validatorAddress).length;
              const feeRewards = {
                amount: [],
                gas: gasLimitsRewards.toString(),
              };

              const response = await signingClient.withdrawAllRewards(
                address,
                validatorAddress,
                feeRewards
              );

              txHash = response.transactionHash;

              if (response.code) {
                throw Error(friendlyErrorMessage(response.rawLog));
              }
            }
          }
        } else if (type === 'log' || !type) {
          if (follow) {
            const toCid = await ipfsApi.addContent(addressSend);
            txHash = await sendCyberlink(address, CID_FOLLOW, toCid, {
              signingClient,
              senseApi,
            });
          } else if (tweets) {
            const toCid = await this.calculationIpfsTo(contentHash);
            txHash = await sendCyberlink(address, CID_TWEET, toCid, {
              signingClient,
              senseApi,
            });
          }
        }

        // sholdn't be after refactoring
        if (!txHash) {
          throw new Error('Tx hash is empty');
        }

        this.setState({ stage: STAGE_SUBMITTED, txHash });

        this.timeOut = setTimeout(this.confirmTx, 1500);
      } catch (e) {
        this.setState({
          txHash: null,
          stage: STAGE_ERROR,
          errorMessage: e.message,
        });
      }
    }
  };

  confirmTx = async () => {
    const { updateAddress } = this.props;
    const { txHash } = this.state;
    if (txHash !== null) {
      this.setState({ stage: STAGE_CONFIRMING });
      const res = await getTxs(txHash);
      if (res) {
        const data = res.tx_response;
        if (data.logs) {
          this.setState({
            stage: STAGE_CONFIRMED,
            txHeight: data.height,
          });
          if (updateAddress) {
            updateAddress();
          }
          return;
        }
        if (data.code) {
          this.setState({
            stage: STAGE_ERROR,
            txHeight: data.height,
            errorMessage: friendlyErrorMessage(data.raw_log),
          });
          return;
        }
      }
    }
    this.timeOut = setTimeout(this.confirmTx, 1500);
  };

  onChangeInputAmount = (e) => {
    this.setState({
      toSend: e.target.value,
    });
  };

  onChangeInputInputAddressT = (e) => {
    this.setState({
      toSendAddres: e.target.value,
    });
  };

  onClickSend = () => {
    const { defaultAccount } = this.props;
    if (defaultAccount.keys === 'wallet' || defaultAccount.keys === 'ledger') {
      this.generateTxSendKplr();
    }
  };

  clearState = () => {
    this.setState({
      stage: STAGE_INIT,
      address: null,
      toSend: '',
      toSendAddres: '',
      txMsg: null,
      txHash: null,
      txHeight: null,
      contentHash: '',
    });
    this.timeOut = null;
  };

  onChangeInput = async (e) => {
    const { value } = e.target;
    this.setState({
      contentHash: value,
    });
  };

  showOpenFileDlg = () => {
    this.inputOpenFileRef.current.click();
  };

  onFilePickerChange = (files) => {
    const file = files.current.files[0];

    this.setState({
      file,
    });
  };

  onClickClear = () => {
    this.setState({
      file: null,
    });
  };

  render() {
    const { type, addressSend, tweets, follow, defaultAccount } = this.props;
    const {
      stage,
      address,
      txMsg,
      txHash,
      txHeight,
      rewards,
      bandwidth,
      contentHash,
      errorMessage,
      file,
    } = this.state;

    const isOwner = defaultAccount && defaultAccount.bech32 === addressSend;

    if (stage === STAGE_INIT) {
      const followBtn = <Button onClick={this.onClickSend}>Follow</Button>;

      const content = [];

      // main page
      if (!type) {
        if (!isOwner) {
          content.push(
            <Button
              link={`${routes.teleport.send.path}?${createSearchParams({
                recipient: addressSend,
                token: 'boot',
                amount: '1',
              }).toString()}`}
            >
              Send
            </Button>
          );
        }

        // if (follow) {
        //   content.push(followBtn);
        // }
      }

      if (!type) {
        if (follow) {
          content.push(followBtn);
        }

        if (tweets) {
          return (
            <StartStageSearchActionBar
              onClickBtn={this.onClickSend}
              contentHash={file !== null && file !== undefined ? file.name : contentHash}
              onChangeInputContentHash={this.onChangeInput}
              textBtn="Tweet"
              placeholder="What's happening?"
              inputOpenFileRef={this.inputOpenFileRef}
              showOpenFileDlg={this.showOpenFileDlg}
              onChangeInput={this.onFilePickerChange}
              onClickClear={this.onClickClear}
              file={file}
              keys={defaultAccount !== null ? defaultAccount.keys : false}
            />
          );
        }
      }

      if (type === 'security' && isOwner && (defaultAccount.keys === 'wallet' || defaultAccount.keys === 'ledger')) {
        content.push(<Button onClick={this.onClickSend}>Claim rewards</Button>);
      }

      return <ActionBarComp>{content}</ActionBarComp>;
    }

    if (stage === STAGE_READY) {
      if (type === 'security') {
        return (
          <RewardsDelegators
            data={rewards}
            onClickBtnClose={this.clearState}
            onClickBtn={this.generateTx}
          />
        );
      }

      if (type === 'log') {
        return (
          <ActionBar>
            <ActionBarContentText>
              transaction generation <Dots big />
            </ActionBarContentText>
          </ActionBar>
        );
      }
    }

    if (stage === STAGE_SUBMITTED || stage === STAGE_CONFIRMING) {
      return <TransactionSubmitted onClickBtnClose={this.clearState} />;
    }

    if (stage === STAGE_CONFIRMED) {
      return (
        <Confirmed
          txHash={txHash}
          txHeight={txHeight}
          onClickBtn={this.clearState}
          onClickBtnClose={this.clearState}
        />
      );
    }

    if (stage === STAGE_ERROR && errorMessage !== null) {
      return (
        <TransactionError
          errorMessage={errorMessage}
          onClickBtn={this.clearState}
          onClickBtnClose={this.clearState}
        />
      );
    }

    return null;
  }
}

export default withIpfsAndSigner(ActionBarContainer);

Synonyms

cyb/src/features/studio/ActionBar.tsx
cyb/src/containers/mint/actionBar.tsx
cyb/src/layouts/ui/ActionBar.tsx
cyb/src/containers/warp/ActionBar.tsx
pussy-ts/src/containers/warp/ActionBar.tsx
pussy-ts/src/containers/governance/actionBar.tsx
pussy-ts/src/containers/portal/citizenship/ActionBar.tsx
cyb/src/pages/teleport/relayer/ActionBar.tsx
cyb/src/containers/portal/citizenship/ActionBar.tsx
pussy-ts/src/containers/energy/component/actionBar.tsx
cyb/src/containers/energy/component/actionBar.tsx
cyb/src/pages/Keys/ActionBar/actionBar.tsx
pussy-ts/src/pages/Keys/ActionBar/actionBar.tsx
pussy-ts/src/pages/teleport/relayer/ActionBar.tsx
pussy-ts/src/pages/robot/_refactor/account/actionBar.tsx
cyb/src/features/sense/ui/ActionBar/ActionBar.tsx
pussy-ts/src/features/sense/ui/ActionBar/ActionBar.tsx

Neighbours