dappros/ethora

View on GitHub
client-reactnative/src/components/Modals/TransactionModal/TokensOrItemsTransfer.tsx

Summary

Maintainability
C
1 day
Test Coverage
import {VStack, Input, View, Text} from 'native-base';
import React, {useState} from 'react';
import {ActivityIndicator, FlatList, StyleSheet} from 'react-native';
import {
  commonColors,
  textStyles,
  itemsTransfersAllowed,
  coinsMainName,
} from '../../../../docs/config';
import {alpha} from '../../../helpers/aplha';
import {useStores} from '../../../stores/context';
import SendItem from './SendItem';
import {CoinsTransferList} from './CoinsTransferList';
import {TransferModalButton} from './TransferModalButton';
import {showError} from '../../Toast/toast';
import {
  widthPercentageToDP as wp,
  heightPercentageToDP as hp,
} from 'react-native-responsive-screen';
import {NftListItem} from '../../Transactions/NftListItem';
import {Seperator} from '../../Separator';
import {IDataForTransfer} from '../Chat/types';

export interface ITransferModal {
  dataForTransfer: IDataForTransfer;
  closeModal: () => void;
  hideUserActions: () => void;
}

const emptySelectedItem = {
  contractAddress: '',
  nfmtType: '',
  tokenName: '',
  balance: 0,
  nftId: '',
  balances: [],
};

type TSelectedItem = typeof emptySelectedItem;
export const TokensOrItemsTransfer: React.FC<ITransferModal> = ({
  dataForTransfer,
  closeModal,
  hideUserActions,
}) => {
  const {walletStore, loginStore} = useStores();
  const [selectedItem, setSelectedItem] =
    useState<TSelectedItem>(emptySelectedItem);
  const [allowedEnterCustomAmount, setAllowedEnterCustomAmount] =
    useState(false);
  const [customTransferAmount, setCustomTransferAmount] = useState('');
  const [displayItems, setDisplayItems] = useState(false);
  const [displayCollections, setDisplayCollections] = useState(false);
  const [loading, setLoading] = useState(false);
  const transferTokens = async (tokenAmount: number) => {
    if (tokenAmount <= 0) {
      showError('Error', 'Amount must be greater than 0');
      return;
    }
    if (!walletStore.coinBalance || +tokenAmount > +walletStore.coinBalance) {
      showError('Error', 'Not enough tokens');
      return;
    }

    const receiverName = dataForTransfer.name;
    const receiverMessageId = dataForTransfer.message_id;
    const senderName = dataForTransfer.senderName;
    const fromWalletAddress = loginStore.initialData.walletAddress;
    const walletAddress = dataForTransfer.walletFromJid;

    const bodyData = {
      toWallet: walletAddress,
      amount: tokenAmount,
      tokenId: 'ERC20',
      tokenName: coinsMainName,
    };

    await walletStore.transferTokens(
      bodyData,
      loginStore.userToken,
      fromWalletAddress,
      senderName,
      receiverName,
      receiverMessageId,
      false,
    );
    closeModal();
  };

  const transferItems = async () => {
    if (!selectedItem?.balance) {
      showError('error', 'Not enough tokens');
    }
    const receiverName = dataForTransfer.name;
    const senderName = dataForTransfer.senderName;
    const fromWalletAddress = loginStore.initialData.walletAddress;
    const walletAddress = dataForTransfer.walletFromJid;

    const bodyData = {
      nftId: selectedItem.nftId,
      receiverWallet: walletAddress,
      amount: 1,
      tokenName: selectedItem.tokenName,
    };

    const nfmtBodyData = {
      to: walletAddress,
      id: selectedItem.nfmtType,
      amount: 1,
      contractAddress: selectedItem?.contractAddress,
      isNfmt: true,
      tokenName: selectedItem.tokenName,
      nftId: selectedItem.nftId,
    };

    await walletStore.transferTokens(
      selectedItem?.balances?.length ? nfmtBodyData : bodyData,
      loginStore.userToken,
      fromWalletAddress,
      senderName,
      receiverName,
      null,
      true,
    );
    closeModal();

    setDisplayItems(false);
    setSelectedItem(emptySelectedItem);
  };

  const transferCollection = async () => {
    setLoading(true);
    const receiverName = dataForTransfer.name;
    const senderName = dataForTransfer.senderName;
    const receiverWalletAddress = dataForTransfer.walletFromJid;

    const bodyData = {
      toAddress: receiverWalletAddress,
      contractAddress: selectedItem?.contractAddress,
    };
    await walletStore.transferCollection(
      bodyData,
      senderName,
      receiverName,
      selectedItem.tokenName + ' (Collection)',
    );
    setLoading(false);
    closeModal();

    setDisplayItems(false);
    setDisplayCollections(false);
    setSelectedItem(emptySelectedItem);
  };
  const onCustomAmountPress = () => {
    setAllowedEnterCustomAmount(true);
    hideUserActions();
  };
  const onSendItemsPress = () => {
    setDisplayItems(true);
    hideUserActions();
  };
  const onSendCollectionsPress = () => {
    setDisplayCollections(true);
    hideUserActions();
  };
  const renderItems = () => {
    const getItemSelected = (pressedItem: TSelectedItem, item:any) => {
      if (item.tokenType === 'NFMT') {
        return (
          pressedItem.nfmtType + pressedItem.contractAddress ===
          item.nfmtType + item.contractAddress
        );
      }
      return pressedItem.contractAddress === item.contractAddress;
    };
    return (
      <FlatList
        data={
          displayItems
            ? walletStore.nftItems.filter((item:any) => !item.external)
            : walletStore.collections
        }
        renderItem={({item}:any) => (
          <NftListItem
            assetUrl={item.imagePreview || item.nftFileUrl}
            name={item.tokenName}
            assetsYouHave={item.balance.toString()}
            totalAssets={item.total}
            onClick={() => setSelectedItem(item)}
            itemSelected={getItemSelected(selectedItem, item)}
            nftId={item.nftId}
            mimetype={item.nftMimetype}
            traitsEnabled={false}
            item={item}
          />
        )}
        nestedScrollEnabled={true}
        keyExtractor={(item, index) => index.toString()}
      />
    );
  };

  if (displayItems) {
    return (
      <View style={styles.itemsContainer}>
        <View style={[styles.tokenTransferContainer]}>
          {renderItems()}

          {<SendItem title={'Send Items'} onPress={transferItems} />}
        </View>
      </View>
    );
  }

  if (displayCollections) {
    return (
      <View style={styles.collectionsContainer}>
        <View style={styles.tokenTransferContainer}>
          {renderItems()}

          {!loading ? (
            <SendItem title={'Send Collections'} onPress={transferCollection} />
          ) : (
            <ActivityIndicator size={30} />
          )}
        </View>
      </View>
    );
  }

  return (
    <View
      w={wp('70%')}
      bg={'#ffff'}
      justifyContent={'center'}
      alignItems={'center'}
      borderRadius={10}
      padding={2}>
      {allowedEnterCustomAmount ? (
        <VStack>
          <Text style={styles.enterAmountText}>Enter Your Amount</Text>
          <View style={{paddingHorizontal: 5, marginVertical: 10}}>
            <Input
              maxLength={15}
              keyboardType="numeric"
              fontFamily={textStyles.lightFont}
              fontSize={hp('1.6%')}
              color={'black'}
              accessibilityLabel={'Enter transfer amount'}
              value={customTransferAmount}
              onChangeText={setCustomTransferAmount}
              placeholder="Enter transfer amount"
              placeholderTextColor={commonColors.primaryDarkColor}
              borderColor={commonColors.primaryDarkColor}
              backgroundColor={alpha(commonColors.primaryDarkColor, 0.1)}
            />
          </View>
          <TransferModalButton
            title={'Send'}
            onPress={() => transferTokens(parseInt(customTransferAmount))}
          />
        </VStack>
      ) : (
        <>
          <View style={styles.tokenTransferContainer}>
            <CoinsTransferList
              name={dataForTransfer.name}
              onTokenTransferPress={transferTokens}
              onCustomAmountPress={onCustomAmountPress}
            />
          </View>

          {walletStore.nftItems.filter((item:any) => !item.external).length > 0 &&
            itemsTransfersAllowed && (
              <>
                <Seperator />

                <SendItem title={'Send Items'} onPress={onSendItemsPress} />
              </>
            )}
          {!!walletStore.collections.length && (
            <>
              <Seperator />

              <SendItem
                title={'Send Collections'}
                onPress={onSendCollectionsPress}
              />
            </>
          )}
          <Seperator />
        </>
      )}
    </View>
  );
};

const styles = StyleSheet.create({
  centeredView: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  itemsContainer: {
    backgroundColor: 'white',
    height: hp('40%'),
    width: wp('90%'),
    padding: 0,
    margin: 0,
    paddingTop: 7,
    justifyContent: 'center',
    alignItems: 'center',
  },
  collectionsContainer: {
    backgroundColor: 'white',
    height: hp('50%'),
    width: wp('100%'),
    padding: 0,
    margin: 0,
    paddingTop: 7,
    justifyContent: 'center',
    alignItems: 'center',
  },

  enterAmountText: {
    color: commonColors.primaryColor,
    fontFamily: textStyles.semiBoldFont,
    textAlign: 'center',
  },
  privacyPolicyMainContainer: {
    backgroundColor: '#fff',
    justifyContent: 'center',
    alignItems: 'center',
    margin: 10,
    height: hp('70%'),
    width: wp('80%'),
  },

  tokenTransferContainer: {
    margin: 10,
    justifyContent: 'center',
    alignItems: 'center',
  },
});