Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ref: disable locked utxos in "Select Inputs" #1024

Merged
merged 1 commit into from
Jan 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import {CurrencyImage} from '../../../../components/currency-image/CurrencyImage
import FromWalletSelectorModal from '../components/FromWalletSelectorModal';
import ToWalletSelectorModal from '../../components/ToWalletSelectorModal';
import AmountModal from '../../../../components/amount/AmountModal';
import {WalletRowProps} from '../../../../components/list/WalletRow';
import {
changellyGetPairsParams,
changellyGetFixRateForAmount,
Expand Down Expand Up @@ -180,7 +181,7 @@ const SwapCryptoRoot: React.FC = () => {
const [balanceDetailsModalVisible, setBalanceDetailsModalVisible] =
useState<boolean>(false);
const [fromWalletSelected, setFromWalletSelected] = useState<Wallet>();
const [uiFormattedWallet, setUiFormattedWallet] = useState<any>();
const [uiFormattedWallet, setUiFormattedWallet] = useState<WalletRowProps>();
const [useDefaultToWallet, setUseDefaultToWallet] = useState<boolean>(false);
const [toWalletSelected, setToWalletSelected] = useState<Wallet>();
const [amountFrom, setAmountFrom] = useState<number>(0);
Expand Down
187 changes: 147 additions & 40 deletions src/navigation/wallet/screens/SelectInputs.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import React, {useCallback, useEffect, useLayoutEffect, useState} from 'react';
import React, {
useCallback,
useEffect,
useLayoutEffect,
useMemo,
useState,
} from 'react';
import {useNavigation, useRoute} from '@react-navigation/native';
import {RouteProp} from '@react-navigation/core';
import styled from 'styled-components/native';
Expand All @@ -9,22 +15,30 @@ import {
Utxo,
Wallet,
} from '../../../store/wallet/wallet.models';
import {BaseText, H5, H7, HeaderTitle} from '../../../components/styled/Text';
import {
BaseText,
H5,
H7,
HeaderTitle,
ListItemSubText,
} from '../../../components/styled/Text';
import {useTranslation} from 'react-i18next';
import {WalletGroupParamList} from '../WalletGroup';
import {
ActiveOpacity,
Column,
CtaContainer as _CtaContainer,
Hr,
RowContainer,
SettingIcon,
} from '../../../components/styled/Containers';
import {CurrencyImage} from '../../../components/currency-image/CurrencyImage';
import {GetUtxos} from '../../../store/wallet/effects/transactions/transactions';
import haptic from '../../../components/haptic-feedback/haptic';
import InputSelectionRow from '../../../components/list/InputsRow';
import {GetPrecision} from '../../../store/wallet/utils/currency';
import {useAppDispatch, useAppSelector, useLogger} from '../../../utils/hooks';
import Button from '../../../components/button/Button';
import {FlatList} from 'react-native';
import {FlatList, LayoutAnimation, TouchableOpacity} from 'react-native';
import {
dismissOnGoingProcessModal,
showBottomNotificationModal,
Expand All @@ -43,13 +57,20 @@ import {GetMinFee} from '../../../store/wallet/effects/fee/fee';
import _ from 'lodash';
import {startOnGoingProcessModal} from '../../../store/app/app.effects';
import {toFiat} from '../../../store/wallet/utils/wallet';
import ChevronDownSvg from '../../../../assets/img/chevron-down.svg';
import ChevronUpSvg from '../../../../assets/img/chevron-up.svg';
import Question from '../../../../assets/img/settings/feedback/question.svg';
import {ScrollView} from 'react-native-gesture-handler';
import {buildUIFormattedWallet} from './KeyOverview';
import {WalletRowProps} from '../../../components/list/WalletRow';
import BalanceDetailsModal from '../components/BalanceDetailsModal';

export const CurrencyColumn = styled(Column)`
margin-left: 8px;
`;

const SectionContainer = styled.View`
margin-bottom: 30px;
margin-bottom: 10px;
`;

const ItemRowContainer = styled.View`
Expand All @@ -68,6 +89,10 @@ const SelectInputsContainer = styled.SafeAreaView`
flex: 1;
`;

const AvailableInputsTitle = styled(H5)`
margin-bottom: 10px;
`;

const SelectInputsDetailsContainer = styled.View`
margin-top: 20px;
padding: 0 15px;
Expand All @@ -78,7 +103,20 @@ const InputSelectionRowContainer = styled.View`
`;

const CtaContainer = styled(_CtaContainer)`
padding: 10px 16px;
padding: 0px 16px 10px 16px;
`;

const DropdownRow = styled.TouchableOpacity`
align-items: center;
flex-direction: row;
justify-content: space-between;
flex-wrap: nowrap;
height: 48px;
`;

const DropdownTitle = styled.View`
flex-direction: row;
justify-content: flex-start;
`;

export const InputTouchableContainer = styled.TouchableOpacity`
Expand Down Expand Up @@ -109,6 +147,10 @@ const SelectInputs = () => {
const defaultAltCurrency = useAppSelector(({APP}) => APP.defaultAltCurrency);
const {rates} = useAppSelector(({RATE}) => RATE);
const [inputs, setInputs] = useState<UtxoWithFiatAmount[]>([]);
const [lockedUtxos, setLockedUtxos] = useState<UtxoWithFiatAmount[]>([]);
const [hideLockedUtxos, setHideLockedUtxos] = useState<boolean>(true);
const [uiFormattedWallet, setUiFormattedWallet] = useState<WalletRowProps>();
const [showBalanceDetailsModal, setShowBalanceDetailsModal] = useState(false);
const {wallet, recipient} = route.params;
const {currencyAbbreviation, chain, network, tokenAddress} = wallet;
const precision = dispatch(
Expand All @@ -120,21 +162,6 @@ const SelectInputs = () => {
const [totalFiatAmount, setTotalFiatAmount] = useState<string>();

const logger = useLogger();
let recipientData: TxDetailsSendingTo;

if (recipient.type === 'contact') {
recipientData = {
recipientName: recipient?.name,
recipientAddress: recipient?.address,
img: recipient?.type,
};
} else {
recipientData = {
recipientName: recipient.name,
recipientAddress: recipient.address,
img: wallet?.img || currencyAbbreviation,
};
}

const init = async () => {
try {
Expand Down Expand Up @@ -164,7 +191,13 @@ const SelectInputs = () => {
),
network,
}));
setInputs(_.orderBy(utxosWithFiatAmount, 'amount', 'desc'));

const [_lockedUtxos, _availableUtxos] = [
utxosWithFiatAmount.filter(u => u.locked),
utxosWithFiatAmount.filter(u => !u.locked),
];
setLockedUtxos(_.orderBy(_lockedUtxos, 'amount', 'desc'));
setInputs(_.orderBy(_availableUtxos, 'amount', 'desc'));
} catch (err) {
logger.error(`An error occurred while getting utxos: ${err}`);
}
Expand Down Expand Up @@ -206,6 +239,17 @@ const SelectInputs = () => {
init();
}, []);

useEffect(() => {
const _uiFormattedWallet = buildUIFormattedWallet(
wallet,
defaultAltCurrency.isoCode,
rates,
dispatch,
'symbol',
);
setUiFormattedWallet(_uiFormattedWallet);
}, [lockedUtxos]);

const inputToggled = useCallback(
(item: UtxoWithFiatAmount, index: number) => {
setInputs(prevInputs => {
Expand All @@ -226,12 +270,12 @@ const SelectInputs = () => {
);

const renderItem = useCallback(
({item, index}) => (
({item, index}: {item: UtxoWithFiatAmount; index: number}) => (
<InputSelectionRowContainer>
<InputSelectionRow
item={item}
emit={inputToggled}
key={item}
key={index}
unitCode={precision?.unitCode}
index={index}
/>
Expand Down Expand Up @@ -302,24 +346,76 @@ const SelectInputs = () => {
}
};

const memoizedLockedUtxosList = useMemo(
() => (
<>
<DropdownRow
activeOpacity={ActiveOpacity}
onPress={() => {
LayoutAnimation.configureNext(
LayoutAnimation.Presets.easeInEaseOut,
);
setHideLockedUtxos(!hideLockedUtxos);
// onPress();
}}>
<DropdownTitle>
<H5>{t('Locked Inputs') + ' ' + '(' + lockedUtxos.length + ')'}</H5>
<TouchableOpacity
style={{marginLeft: 10}}
onPress={() => {
setShowBalanceDetailsModal(true);
}}>
<Question width={24} height={24} />
</TouchableOpacity>
</DropdownTitle>
<SettingIcon suffix>
{!hideLockedUtxos ? <ChevronDownSvg /> : <ChevronUpSvg />}
</SettingIcon>
</DropdownRow>
<ScrollView style={{marginBottom: 10, maxHeight: 225}}>
{!hideLockedUtxos
? lockedUtxos.map(
(lockedUtxo: UtxoWithFiatAmount, index: number) => {
return (
<RowContainer
key={index}
activeOpacity={ActiveOpacity}
style={{paddingLeft: 0, paddingRight: 0}}>
<Column>
<H5>
{lockedUtxo.amount}{' '}
{precision?.unitCode?.toUpperCase()}{' '}
</H5>
{/* <Hr /> */}
{lockedUtxo.network !== 'testnet' ? (
<ListItemSubText textAlign={'left'}>
{lockedUtxo.fiatAmount}
</ListItemSubText>
) : null}
<ListItemSubText
numberOfLines={1}
ellipsizeMode={'middle'}>
{lockedUtxo.address}
</ListItemSubText>
</Column>
</RowContainer>
);
},
)
: null}
</ScrollView>
{/* workaround to prevent weird behaviour with dropdown animation */}
{!hideLockedUtxos ? (
<AvailableInputsTitle>{t('Available Inputs')}</AvailableInputsTitle>
) : null}
</>
),
[lockedUtxos, hideLockedUtxos],
);

return (
<SelectInputsContainer>
<SelectInputsDetailsContainer>
<SectionContainer>
<H5>{t('Recipient')}</H5>
<ItemRowContainer>
<RecipientContainer>
<CurrencyImage img={recipientData.img} size={25} />
<H7
numberOfLines={1}
ellipsizeMode={'tail'}
style={{marginLeft: 8, width: '60%'}}>
{recipientData.recipientName || recipientData.recipientAddress}
</H7>
</RecipientContainer>
</ItemRowContainer>
<Hr />
</SectionContainer>
<SectionContainer>
<H5 style={{marginBottom: 10}}>{t('Total Selected Inputs')}</H5>
<ItemRowContainer
Expand All @@ -339,7 +435,10 @@ const SelectInputs = () => {
</ItemRowContainer>
<Hr />
</SectionContainer>
<H5 style={{marginBottom: 10}}>{t('Wallet Inputs')}</H5>
{lockedUtxos.length > 0 ? memoizedLockedUtxosList : null}
{hideLockedUtxos ? (
<AvailableInputsTitle>{t('Available Inputs')}</AvailableInputsTitle>
) : null}
</SelectInputsDetailsContainer>
{inputs && inputs.length ? (
<FlatList
Expand All @@ -366,6 +465,14 @@ const SelectInputs = () => {
{t('Continue')}
</Button>
</CtaContainer>

{wallet && uiFormattedWallet ? (
<BalanceDetailsModal
isVisible={showBalanceDetailsModal}
closeModal={() => setShowBalanceDetailsModal(false)}
wallet={uiFormattedWallet}
/>
) : null}
</SelectInputsContainer>
);
};
Expand Down
15 changes: 6 additions & 9 deletions src/navigation/wallet/screens/send/SendTo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -173,19 +173,16 @@ export const BuildKeyWalletRow = (
value.wallets
.filter(({hideWallet}) => !hideWallet)
.filter(
({
currencyAbbreviation,
chain,
id,
network,
credentials,
}) =>
({currencyAbbreviation, chain, id, network, credentials}) =>
currencyAbbreviation.toLowerCase() ===
currentCurrencyAbbreviation.toLowerCase() &&
chain.toLowerCase() === currentChain.toLowerCase() &&
id !== currentWalletId &&
(IsUtxoCoin(currencyAbbreviation) ||
(!IsUtxoCoin(currencyAbbreviation) && id !== currentWalletId)) &&
network === currentNetwork &&
credentials.walletName.toLowerCase().includes(searchInput.toLowerCase()) &&
credentials.walletName
.toLowerCase()
.includes(searchInput.toLowerCase()) &&
credentials.isComplete(),
)
.map(wallet => {
Expand Down