TST: Update tests

This commit is contained in:
Marcos Rodriguez Velez 2024-08-04 22:13:25 -04:00
parent 89d5c8e357
commit 2a0e83d019
No known key found for this signature in database
GPG key ID: 6030B2F48CCE86D7
3 changed files with 190 additions and 202 deletions

View file

@ -128,11 +128,15 @@ const SendDetails = () => {
return initialFee; return initialFee;
}, [customFee, feePrecalc, networkTransactionFees]); }, [customFee, feePrecalc, networkTransactionFees]);
const onReplaceableFeeSwitchValueChanged = (value: boolean) => { useEffect(() => {
setIsTransactionReplaceable(value); console.log('send/details - useEffect');
}; if (wallet) {
setHeaderRightOptions();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [colors, wallet, isTransactionReplaceable, balance, addresses, isEditable, isLoading]);
// keyboard effects // keyboad effects
useEffect(() => { useEffect(() => {
const _keyboardDidShow = () => { const _keyboardDidShow = () => {
setWalletSelectionOrCoinsSelectedHidden(true); setWalletSelectionOrCoinsSelectedHidden(true);
@ -228,7 +232,8 @@ const SendDetails = () => {
} else { } else {
setAddresses([{ address: '', key: String(Math.random()) } as IPaymentDestinations]); // key is for the FlatList setAddresses([{ address: '', key: String(Math.random()) } as IPaymentDestinations]); // key is for the FlatList
} }
}, [routeParams.uri, routeParams.address, routeParams.addRecipientParams, addresses, routeParams, setParams]); // eslint-disable-next-line react-hooks/exhaustive-deps
}, [routeParams.uri, routeParams.address, routeParams.addRecipientParams]);
useEffect(() => { useEffect(() => {
// check if we have a suitable wallet // check if we have a suitable wallet
@ -270,7 +275,7 @@ const SendDetails = () => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut); LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
setNetworkTransactionFeesIsLoading(false); setNetworkTransactionFeesIsLoading(false);
}); });
}, [navigation, routeParams.walletID, wallets]); }, []); // eslint-disable-line react-hooks/exhaustive-deps
// change header and reset state on wallet change // change header and reset state on wallet change
useEffect(() => { useEffect(() => {
@ -281,7 +286,6 @@ const SendDetails = () => {
setUtxo(null); setUtxo(null);
setChangeAddress(null); setChangeAddress(null);
setIsTransactionReplaceable(wallet.type === HDSegwitBech32Wallet.type && !routeParams.noRbf ? true : undefined); setIsTransactionReplaceable(wallet.type === HDSegwitBech32Wallet.type && !routeParams.noRbf ? true : undefined);
// update wallet UTXO // update wallet UTXO
wallet wallet
.fetchUtxo() .fetchUtxo()
@ -290,8 +294,7 @@ const SendDetails = () => {
setDumb(v => !v); setDumb(v => !v);
}) })
.catch(e => console.log('fetchUtxo error', e)); .catch(e => console.log('fetchUtxo error', e));
// eslint-disable-next-line react-hooks/exhaustive-deps }, [wallet]); // eslint-disable-line react-hooks/exhaustive-deps
}, [wallet]);
// recalc fees in effect so we don't block render // recalc fees in effect so we don't block render
useEffect(() => { useEffect(() => {
@ -374,7 +377,7 @@ const SendDetails = () => {
setFeePrecalc(newFeePrecalc); setFeePrecalc(newFeePrecalc);
setFrozenBlance(frozen); setFrozenBlance(frozen);
}, [wallet, networkTransactionFees, utxo, addresses, feeRate, dumb, feePrecalc]); }, [wallet, networkTransactionFees, utxo, addresses, feeRate, dumb]); // eslint-disable-line react-hooks/exhaustive-deps
// we need to re-calculate fees if user opens-closes coin control // we need to re-calculate fees if user opens-closes coin control
useFocusEffect( useFocusEffect(
@ -606,6 +609,7 @@ const SendDetails = () => {
if (tx && routeParams.launchedBy && psbt) { if (tx && routeParams.launchedBy && psbt) {
console.warn('navigating back to ', routeParams.launchedBy); console.warn('navigating back to ', routeParams.launchedBy);
feeModalRef.current?.dismiss(); feeModalRef.current?.dismiss();
// @ts-ignore idk how to fix FIXME? // @ts-ignore idk how to fix FIXME?
navigation.navigate(routeParams.launchedBy, { psbt }); navigation.navigate(routeParams.launchedBy, { psbt });
@ -613,6 +617,7 @@ const SendDetails = () => {
if (wallet?.type === WatchOnlyWallet.type) { if (wallet?.type === WatchOnlyWallet.type) {
feeModalRef.current?.dismiss(); feeModalRef.current?.dismiss();
// watch-only wallets with enabled HW wallet support have different flow. we have to show PSBT to user as QR code // watch-only wallets with enabled HW wallet support have different flow. we have to show PSBT to user as QR code
// so he can scan it and sign it. then we have to scan it back from user (via camera and QR code), and ask // so he can scan it and sign it. then we have to scan it back from user (via camera and QR code), and ask
// user whether he wants to broadcast it // user whether he wants to broadcast it
@ -628,6 +633,7 @@ const SendDetails = () => {
if (wallet?.type === MultisigHDWallet.type) { if (wallet?.type === MultisigHDWallet.type) {
feeModalRef.current?.dismiss(); feeModalRef.current?.dismiss();
navigation.navigate('PsbtMultisig', { navigation.navigate('PsbtMultisig', {
memo: transactionMemo, memo: transactionMemo,
psbtBase64: psbt.toBase64(), psbtBase64: psbt.toBase64(),
@ -673,49 +679,22 @@ const SendDetails = () => {
if (newWallet) { if (newWallet) {
setWallet(newWallet); setWallet(newWallet);
} }
}, [routeParams.walletID, wallets]); // eslint-disable-next-line react-hooks/exhaustive-deps
}, [routeParams.walletID]);
const importQrTransactionOnBarScanned = useCallback(
(ret: any) => {
navigation.getParent()?.getParent()?.dispatch(popAction);
if (!wallet) return;
if (!ret.data) ret = { data: ret };
if (ret.data.toUpperCase().startsWith('UR')) {
presentAlert({ title: loc.errors.error, message: 'BC-UR not decoded. This should never happen' });
} else if (ret.data.indexOf('+') === -1 && ret.data.indexOf('=') === -1 && ret.data.indexOf('=') === -1) {
// this looks like NOT base64, so maybe its transaction's hex
// we dont support it in this flow
} else {
feeModalRef.current?.dismiss();
// psbt base64?
// we construct PSBT object and pass to next screen
// so user can do smth with it:
const psbt = bitcoin.Psbt.fromBase64(ret.data);
navigation.navigate('PsbtWithHardwareWallet', {
memo: transactionMemo,
fromWallet: wallet,
psbt,
});
setIsLoading(false);
}
},
[navigation, popAction, transactionMemo, wallet],
);
/** /**
* same as `importTransaction`, but opens camera instead. * same as `importTransaction`, but opens camera instead.
* *
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
const importQrTransaction = useCallback(() => { const importQrTransaction = () => {
if (wallet?.type !== WatchOnlyWallet.type) { if (wallet?.type !== WatchOnlyWallet.type) {
return presentAlert({ title: loc.errors.error, message: 'Importing transaction in non-watchonly wallet (this should never happen)' }); return presentAlert({ title: loc.errors.error, message: 'Importing transaction in non-watchonly wallet (this should never happen)' });
} }
requestCameraAuthorization().then(() => { requestCameraAuthorization().then(() => {
feeModalRef.current?.dismiss(); feeModalRef.current?.dismiss();
navigation.navigate('ScanQRCodeRoot', { navigation.navigate('ScanQRCodeRoot', {
screen: 'ScanQRCode', screen: 'ScanQRCode',
params: { params: {
@ -724,7 +703,34 @@ const SendDetails = () => {
}, },
}); });
}); });
}, [importQrTransactionOnBarScanned, navigation, wallet?.type]); };
const importQrTransactionOnBarScanned = (ret: any) => {
navigation.getParent()?.getParent()?.dispatch(popAction);
if (!wallet) return;
if (!ret.data) ret = { data: ret };
if (ret.data.toUpperCase().startsWith('UR')) {
presentAlert({ title: loc.errors.error, message: 'BC-UR not decoded. This should never happen' });
} else if (ret.data.indexOf('+') === -1 && ret.data.indexOf('=') === -1 && ret.data.indexOf('=') === -1) {
// this looks like NOT base64, so maybe its transaction's hex
// we dont support it in this flow
} else {
feeModalRef.current?.dismiss();
// psbt base64?
// we construct PSBT object and pass to next screen
// so user can do smth with it:
const psbt = bitcoin.Psbt.fromBase64(ret.data);
navigation.navigate('PsbtWithHardwareWallet', {
memo: transactionMemo,
fromWallet: wallet,
psbt,
});
setIsLoading(false);
}
};
/** /**
* watch-only wallets with enabled HW wallet support have different flow. we have to show PSBT to user as QR code * watch-only wallets with enabled HW wallet support have different flow. we have to show PSBT to user as QR code
@ -734,7 +740,7 @@ const SendDetails = () => {
* *
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
const importTransaction = useCallback(async () => { const importTransaction = async () => {
if (wallet?.type !== WatchOnlyWallet.type) { if (wallet?.type !== WatchOnlyWallet.type) {
return presentAlert({ title: loc.errors.error, message: 'Importing transaction in non-watchonly wallet (this should never happen)' }); return presentAlert({ title: loc.errors.error, message: 'Importing transaction in non-watchonly wallet (this should never happen)' });
} }
@ -785,7 +791,7 @@ const SendDetails = () => {
presentAlert({ title: loc.errors.error, message: loc.send.details_no_signed_tx }); presentAlert({ title: loc.errors.error, message: loc.send.details_no_signed_tx });
} }
} }
}, [navigation, transactionMemo, wallet]); };
const askCosignThisTransaction = async () => { const askCosignThisTransaction = async () => {
return new Promise(resolve => { return new Promise(resolve => {
@ -808,59 +814,53 @@ const SendDetails = () => {
}); });
}; };
const _importTransactionMultisig = useCallback( const _importTransactionMultisig = async (base64arg: string | false) => {
async (base64arg: string | false) => { try {
try { const base64 = base64arg || (await fs.openSignedTransaction());
const base64 = base64arg || (await fs.openSignedTransaction()); if (!base64) return;
if (!base64) return; const psbt = bitcoin.Psbt.fromBase64(base64); // if it doesnt throw - all good, its valid
const psbt = bitcoin.Psbt.fromBase64(base64); // if it doesnt throw - all good, its valid
if ((wallet as MultisigHDWallet)?.howManySignaturesCanWeMake() > 0 && (await askCosignThisTransaction())) { if ((wallet as MultisigHDWallet)?.howManySignaturesCanWeMake() > 0 && (await askCosignThisTransaction())) {
setIsLoading(true); setIsLoading(true);
await sleep(100); await sleep(100);
(wallet as MultisigHDWallet).cosignPsbt(psbt); (wallet as MultisigHDWallet).cosignPsbt(psbt);
setIsLoading(false); setIsLoading(false);
await sleep(100); await sleep(100);
}
if (wallet) {
navigation.navigate('PsbtMultisig', {
memo: transactionMemo,
psbtBase64: psbt.toBase64(),
walletID: wallet.getID(),
});
}
} catch (error: any) {
presentAlert({ title: loc.send.problem_with_psbt, message: error.message });
} }
setIsLoading(false);
},
[navigation, sleep, transactionMemo, wallet],
);
const importTransactionMultisig = useCallback(() => { if (wallet) {
navigation.navigate('PsbtMultisig', {
memo: transactionMemo,
psbtBase64: psbt.toBase64(),
walletID: wallet.getID(),
});
}
} catch (error: any) {
presentAlert({ title: loc.send.problem_with_psbt, message: error.message });
}
setIsLoading(false);
};
const importTransactionMultisig = () => {
return _importTransactionMultisig(false); return _importTransactionMultisig(false);
}, [_importTransactionMultisig]); };
const onBarScanned = useCallback( const onBarScanned = (ret: any) => {
(ret: any) => { navigation.getParent()?.dispatch(popAction);
navigation.getParent()?.dispatch(popAction); if (!ret.data) ret = { data: ret };
if (!ret.data) ret = { data: ret }; if (ret.data.toUpperCase().startsWith('UR')) {
if (ret.data.toUpperCase().startsWith('UR')) { presentAlert({ title: loc.errors.error, message: 'BC-UR not decoded. This should never happen' });
presentAlert({ title: loc.errors.error, message: 'BC-UR not decoded. This should never happen' }); } else if (ret.data.indexOf('+') === -1 && ret.data.indexOf('=') === -1 && ret.data.indexOf('=') === -1) {
} else if (ret.data.indexOf('+') === -1 && ret.data.indexOf('=') === -1 && ret.data.indexOf('=') === -1) { // this looks like NOT base64, so maybe its transaction's hex
// this looks like NOT base64, so maybe its transaction's hex // we dont support it in this flow
// we dont support it in this flow } else {
} else { // psbt base64?
// psbt base64? return _importTransactionMultisig(ret.data);
return _importTransactionMultisig(ret.data); }
} };
},
[_importTransactionMultisig, navigation, popAction],
);
const importTransactionMultisigScanQr = useCallback(async () => { const importTransactionMultisigScanQr = async () => {
requestCameraAuthorization().then(() => { await requestCameraAuthorization().then(() => {
navigation.navigate('ScanQRCodeRoot', { navigation.navigate('ScanQRCodeRoot', {
screen: 'ScanQRCode', screen: 'ScanQRCode',
params: { params: {
@ -869,19 +869,19 @@ const SendDetails = () => {
}, },
}); });
}); });
}, [navigation, onBarScanned]); };
const handleAddRecipient = useCallback(async () => { const handleAddRecipient = async () => {
console.debug('handleAddRecipient'); console.debug('handleAddRecipient');
setAddresses(addrs => [...addrs, { address: '', key: String(Math.random()) } as IPaymentDestinations]); await setAddresses(addrs => [...addrs, { address: '', key: String(Math.random()) } as IPaymentDestinations]);
await sleep(200); // wait for animation await sleep(200); // wait for animation
scrollView.current?.scrollToEnd(); scrollView.current?.scrollToEnd();
if (addresses.length === 0) return; if (addresses.length === 0) return;
scrollView.current?.flashScrollIndicators(); scrollView.current?.flashScrollIndicators();
}, [addresses.length, sleep]); };
const handleRemoveRecipient = useCallback(async () => { const handleRemoveRecipient = async () => {
const last = scrollIndex.current === addresses.length - 1; const last = scrollIndex.current === addresses.length - 1;
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut); LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
setAddresses(addrs => { setAddresses(addrs => {
@ -893,22 +893,22 @@ const SendDetails = () => {
await sleep(200); // wait for animation await sleep(200); // wait for animation
scrollView.current?.flashScrollIndicators(); scrollView.current?.flashScrollIndicators();
if (last && Platform.OS === 'android') scrollView.current?.scrollToEnd(); // fix white screen on android if (last && Platform.OS === 'android') scrollView.current?.scrollToEnd(); // fix white screen on android
}, [addresses.length, sleep]); };
const handleCoinControl = useCallback(async () => { const handleCoinControl = async () => {
if (!wallet) return; if (!wallet) return;
navigation.navigate('CoinControl', { navigation.navigate('CoinControl', {
walletID: wallet?.getID(), walletID: wallet?.getID(),
onUTXOChoose: (u: CreateTransactionUtxo[]) => setUtxo(u), onUTXOChoose: (u: CreateTransactionUtxo[]) => setUtxo(u),
}); });
}, [navigation, wallet]); };
const handleInsertContact = useCallback(async () => { const handleInsertContact = async () => {
if (!wallet) return; if (!wallet) return;
navigation.navigate('PaymentCodeList', { walletID: wallet.getID() }); navigation.navigate('PaymentCodeList', { walletID: wallet.getID() });
}, [navigation, wallet]); };
const handlePsbtSign = useCallback(async () => { const handlePsbtSign = async () => {
setIsLoading(true); setIsLoading(true);
await new Promise(resolve => setTimeout(resolve, 100)); // sleep for animations await new Promise(resolve => setTimeout(resolve, 100)); // sleep for animations
@ -948,9 +948,37 @@ const SendDetails = () => {
showAnimatedQr: true, showAnimatedQr: true,
psbt, psbt,
}); });
}, [name, navigation, wallet]); };
const headerRightActions = useCallback(() => { // Header Right Button
const headerRightOnPress = (id: string) => {
if (id === SendDetails.actionKeys.AddRecipient) {
handleAddRecipient();
} else if (id === SendDetails.actionKeys.RemoveRecipient) {
handleRemoveRecipient();
} else if (id === SendDetails.actionKeys.SignPSBT) {
handlePsbtSign();
} else if (id === SendDetails.actionKeys.SendMax) {
onUseAllPressed();
} else if (id === SendDetails.actionKeys.AllowRBF) {
onReplaceableFeeSwitchValueChanged(!isTransactionReplaceable);
} else if (id === SendDetails.actionKeys.ImportTransaction) {
importTransaction();
} else if (id === SendDetails.actionKeys.ImportTransactionQR) {
importQrTransaction();
} else if (id === SendDetails.actionKeys.ImportTransactionMultsig) {
importTransactionMultisig();
} else if (id === SendDetails.actionKeys.CoSignTransaction) {
importTransactionMultisigScanQr();
} else if (id === SendDetails.actionKeys.CoinControl) {
handleCoinControl();
} else if (id === SendDetails.actionKeys.InsertContact) {
handleInsertContact();
}
};
const headerRightActions = () => {
const actions: Action[] & Action[][] = []; const actions: Action[] & Action[][] = [];
if (isEditable) { if (isEditable) {
if (wallet?.allowBIP47() && wallet?.isBIP47Enabled()) { if (wallet?.allowBIP47() && wallet?.isBIP47Enabled()) {
@ -1017,10 +1045,52 @@ const SendDetails = () => {
actions.push({ id: SendDetails.actionKeys.CoinControl, text: loc.cc.header, icon: SendDetails.actionIcons.CoinControl }); actions.push({ id: SendDetails.actionKeys.CoinControl, text: loc.cc.header, icon: SendDetails.actionIcons.CoinControl });
return actions; return actions;
}, [isEditable, wallet, isTransactionReplaceable, addresses, balance]); };
const onUseAllPressed = useCallback(async () => { const setHeaderRightOptions = () => {
triggerHapticFeedback(HapticFeedbackTypes.NotificationWarning); navigation.setOptions({
// eslint-disable-next-line react/no-unstable-nested-components
headerRight: () => (
<ToolTipMenu
disabled={isLoading}
isButton
isMenuPrimaryAction
onPressMenuItem={headerRightOnPress}
actions={headerRightActions()}
testID="advancedOptionsMenuButton"
>
<Icon size={22} name="more-horiz" type="material" color={colors.foregroundColor} style={styles.advancedOptions} />
</ToolTipMenu>
),
});
};
const onReplaceableFeeSwitchValueChanged = (value: boolean) => {
setIsTransactionReplaceable(value);
};
//
// because of https://github.com/facebook/react-native/issues/21718 we use
// onScroll for android and onMomentumScrollEnd for iOS
const handleRecipientsScrollEnds = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
if (Platform.OS === 'android') return; // for android we use handleRecipientsScroll
const contentOffset = e.nativeEvent.contentOffset;
const viewSize = e.nativeEvent.layoutMeasurement;
const index = Math.floor(contentOffset.x / viewSize.width);
scrollIndex.current = index;
};
const handleRecipientsScroll = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
if (Platform.OS === 'ios') return; // for iOS we use handleRecipientsScrollEnds
const contentOffset = e.nativeEvent.contentOffset;
const viewSize = e.nativeEvent.layoutMeasurement;
const index = Math.floor(contentOffset.x / viewSize.width);
scrollIndex.current = index;
};
const onUseAllPressed = async () => {
await triggerHapticFeedback(HapticFeedbackTypes.NotificationWarning);
const message = frozenBalance > 0 ? loc.send.details_adv_full_sure_frozen : loc.send.details_adv_full_sure; const message = frozenBalance > 0 ? loc.send.details_adv_full_sure_frozen : loc.send.details_adv_full_sure;
Alert.alert( Alert.alert(
loc.send.details_adv_full, loc.send.details_adv_full,
@ -1050,74 +1120,6 @@ const SendDetails = () => {
], ],
{ cancelable: false }, { cancelable: false },
); );
}, [frozenBalance]);
const HeaderRightButton = useMemo(() => {
const headerRightOnPress = (id: string) => {
if (id === SendDetails.actionKeys.AddRecipient) {
handleAddRecipient();
} else if (id === SendDetails.actionKeys.RemoveRecipient) {
handleRemoveRecipient();
} else if (id === SendDetails.actionKeys.SignPSBT) {
handlePsbtSign();
} else if (id === SendDetails.actionKeys.SendMax) {
onUseAllPressed();
} else if (id === SendDetails.actionKeys.AllowRBF) {
onReplaceableFeeSwitchValueChanged(!isTransactionReplaceable);
} else if (id === SendDetails.actionKeys.ImportTransaction) {
importTransaction();
} else if (id === SendDetails.actionKeys.ImportTransactionQR) {
importQrTransaction();
} else if (id === SendDetails.actionKeys.ImportTransactionMultsig) {
importTransactionMultisig();
} else if (id === SendDetails.actionKeys.CoSignTransaction) {
importTransactionMultisigScanQr();
} else if (id === SendDetails.actionKeys.CoinControl) {
handleCoinControl();
} else if (id === SendDetails.actionKeys.InsertContact) {
handleInsertContact();
}
};
return (
<ToolTipMenu disabled={isLoading} isButton isMenuPrimaryAction onPressMenuItem={headerRightOnPress} actions={headerRightActions()}>
<Icon size={22} name="more-horiz" type="material" color={colors.foregroundColor} style={styles.advancedOptions} />
</ToolTipMenu>
);
}, [
colors.foregroundColor,
handleAddRecipient,
handleCoinControl,
handleInsertContact,
handlePsbtSign,
handleRemoveRecipient,
headerRightActions,
importQrTransaction,
importTransaction,
importTransactionMultisig,
importTransactionMultisigScanQr,
isLoading,
isTransactionReplaceable,
onUseAllPressed,
]);
//
// because of https://github.com/facebook/react-native/issues/21718 we use
// onScroll for android and onMomentumScrollEnd for iOS
const handleRecipientsScrollEnds = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
if (Platform.OS === 'android') return; // for android we use handleRecipientsScroll
const contentOffset = e.nativeEvent.contentOffset;
const viewSize = e.nativeEvent.layoutMeasurement;
const index = Math.floor(contentOffset.x / viewSize.width);
scrollIndex.current = index;
};
const handleRecipientsScroll = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
if (Platform.OS === 'ios') return; // for iOS we use handleRecipientsScrollEnds
const contentOffset = e.nativeEvent.contentOffset;
const viewSize = e.nativeEvent.layoutMeasurement;
const index = Math.floor(contentOffset.x / viewSize.width);
scrollIndex.current = index;
}; };
const formatFee = (fee: number) => formatBalance(fee, feeUnit!, true); const formatFee = (fee: number) => formatBalance(fee, feeUnit!, true);
@ -1199,6 +1201,7 @@ const SendDetails = () => {
style={styles.selectTouch} style={styles.selectTouch}
onPress={() => { onPress={() => {
feeModalRef.current?.dismiss(); feeModalRef.current?.dismiss();
navigation.navigate('SelectWallet', { chainType: Chain.ONCHAIN }); navigation.navigate('SelectWallet', { chainType: Chain.ONCHAIN });
}} }}
> >
@ -1316,21 +1319,6 @@ const SendDetails = () => {
); );
}; };
const setHeaderRightOptions = useCallback(() => {
// Header Right Button
navigation.setOptions({
headerRight: () => HeaderRightButton,
});
}, [HeaderRightButton, navigation]);
useEffect(() => {
console.log('send/details - useEffect');
if (wallet) {
setHeaderRightOptions();
}
}, [colors, wallet, isTransactionReplaceable, balance, addresses, isEditable, isLoading, setHeaderRightOptions]);
if (isLoading || !wallet) { if (isLoading || !wallet) {
return ( return (
<View style={[styles.loading, stylesHook.loading]}> <View style={[styles.loading, stylesHook.loading]}>

View file

@ -208,23 +208,23 @@ describe('BlueWallet UI Tests - import BIP84 wallet', () => {
// lest add another two outputs // lest add another two outputs
await element(by.id('advancedOptionsMenuButton')).tap(); await element(by.id('advancedOptionsMenuButton')).tap();
await element(by.id('AddRecipient')).tap(); await element(by.text('Add Recipient')).tap();
await yo('Transaction1'); // adding a recipient autoscrolls it to the last one await yo('Transaction1'); // adding a recipient autoscrolls it to the last one
await element(by.id('AddressInput').withAncestor(by.id('Transaction1'))).replaceText('bc1q063ctu6jhe5k4v8ka99qac8rcm2tzjjnuktyrl'); await element(by.id('AddressInput').withAncestor(by.id('Transaction1'))).replaceText('bc1q063ctu6jhe5k4v8ka99qac8rcm2tzjjnuktyrl');
await element(by.id('BitcoinAmountInput').withAncestor(by.id('Transaction1'))).replaceText('0.0002\n'); await element(by.id('BitcoinAmountInput').withAncestor(by.id('Transaction1'))).replaceText('0.0002\n');
await element(by.id('advancedOptionsMenuButton')).tap(); await element(by.id('advancedOptionsMenuButton')).tap();
await element(by.id('AddRecipient')).tap(); await element(by.text('Add Recipient')).tap();
await yo('Transaction2'); // adding a recipient autoscrolls it to the last one await yo('Transaction2'); // adding a recipient autoscrolls it to the last one
// remove last output, check if second output is shown // remove last output, check if second output is shown
await element(by.id('advancedOptionsMenuButton')).tap(); await element(by.id('advancedOptionsMenuButton')).tap();
await element(by.id('RemoveRecipient')).tap(); await element(by.text('Remove Recipient')).tap();
await yo('Transaction1'); await yo('Transaction1');
// adding it again // adding it again
await element(by.id('advancedOptionsMenuButton')).tap(); await element(by.id('advancedOptionsMenuButton')).tap();
await element(by.id('AddRecipient')).tap(); await element(by.text('Add Recipient')).tap();
await yo('Transaction2'); // adding a recipient autoscrolls it to the last one await yo('Transaction2'); // adding a recipient autoscrolls it to the last one
await element(by.id('AddressInput').withAncestor(by.id('Transaction2'))).replaceText('bc1qh6tf004ty7z7un2v5ntu4mkf630545gvhs45u7'); await element(by.id('AddressInput').withAncestor(by.id('Transaction2'))).replaceText('bc1qh6tf004ty7z7un2v5ntu4mkf630545gvhs45u7');
await element(by.id('BitcoinAmountInput').withAncestor(by.id('Transaction2'))).replaceText('0.0003\n'); await element(by.id('BitcoinAmountInput').withAncestor(by.id('Transaction2'))).replaceText('0.0003\n');
@ -233,7 +233,7 @@ describe('BlueWallet UI Tests - import BIP84 wallet', () => {
await element(by.id('Transaction2')).swipe('right', 'fast', NaN, 0.2); await element(by.id('Transaction2')).swipe('right', 'fast', NaN, 0.2);
await sleep(5000); await sleep(5000);
await element(by.id('advancedOptionsMenuButton')).tap(); await element(by.id('advancedOptionsMenuButton')).tap();
await element(by.id('RemoveRecipient')).tap(); await element(by.text('Remove Recipient')).tap();
// creating and verifying. tx should have 3 outputs // creating and verifying. tx should have 3 outputs
if (process.env.TRAVIS) await sleep(5000); if (process.env.TRAVIS) await sleep(5000);
@ -282,7 +282,7 @@ describe('BlueWallet UI Tests - import BIP84 wallet', () => {
await element(by.id('AddressInput')).replaceText('bc1qnapskphjnwzw2w3dk4anpxntunc77v6qrua0f7'); await element(by.id('AddressInput')).replaceText('bc1qnapskphjnwzw2w3dk4anpxntunc77v6qrua0f7');
await element(by.id('BitcoinAmountInput')).typeText('0.0001\n'); await element(by.id('BitcoinAmountInput')).typeText('0.0001\n');
await element(by.id('advancedOptionsMenuButton')).tap(); await element(by.id('advancedOptionsMenuButton')).tap();
await element(by.id('sendMaxButton')).tap(); await element(by.text('Use Full Balance')).tap();
await element(by.text('OK')).tap(); await element(by.text('OK')).tap();
if (process.env.TRAVIS) await sleep(5000); if (process.env.TRAVIS) await sleep(5000);
@ -301,7 +301,7 @@ describe('BlueWallet UI Tests - import BIP84 wallet', () => {
await device.pressBack(); await device.pressBack();
await device.pressBack(); await device.pressBack();
await element(by.id('advancedOptionsMenuButton')).tap(); await element(by.id('advancedOptionsMenuButton')).tap();
await element(by.id('AddRecipient')).tap(); await element(by.text('Add Recipient')).tap();
await yo('Transaction1'); await yo('Transaction1');
await element(by.id('AddressInput').withAncestor(by.id('Transaction1'))).replaceText('bc1q063ctu6jhe5k4v8ka99qac8rcm2tzjjnuktyrl'); await element(by.id('AddressInput').withAncestor(by.id('Transaction1'))).replaceText('bc1q063ctu6jhe5k4v8ka99qac8rcm2tzjjnuktyrl');
await element(by.id('BitcoinAmountInput').withAncestor(by.id('Transaction1'))).typeText('0.0001\n'); await element(by.id('BitcoinAmountInput').withAncestor(by.id('Transaction1'))).typeText('0.0001\n');
@ -342,7 +342,7 @@ describe('BlueWallet UI Tests - import BIP84 wallet', () => {
await element(by.id('SendButton')).tap(); await element(by.id('SendButton')).tap();
await element(by.id('advancedOptionsMenuButton')).tap(); await element(by.id('advancedOptionsMenuButton')).tap();
await element(by.id('PsbtSign')).tap(); await element(by.text('Sign a transaction')).tap();
// tapping 5 times invisible button is a backdoor: // tapping 5 times invisible button is a backdoor:
for (let c = 0; c <= 5; c++) { for (let c = 0; c <= 5; c++) {
@ -491,7 +491,7 @@ describe('BlueWallet UI Tests - import BIP84 wallet', () => {
await element(by.text('Imported HD SegWit (BIP84 Bech32 Native)')).tap(); await element(by.text('Imported HD SegWit (BIP84 Bech32 Native)')).tap();
await element(by.id('SendButton')).tap(); await element(by.id('SendButton')).tap();
await element(by.id('advancedOptionsMenuButton')).tap(); await element(by.id('advancedOptionsMenuButton')).tap();
await element(by.id('CoinControl')).tap(); await element(by.text('Coin Control')).tap();
await waitFor(element(by.id('Loading'))) // wait for outputs to be loaded await waitFor(element(by.id('Loading'))) // wait for outputs to be loaded
.not.toExist() .not.toExist()
.withTimeout(300 * 1000); .withTimeout(300 * 1000);
@ -510,7 +510,7 @@ describe('BlueWallet UI Tests - import BIP84 wallet', () => {
await element(by.id('UseCoin')).tap(); await element(by.id('UseCoin')).tap();
await element(by.id('AddressInput')).replaceText('bc1q063ctu6jhe5k4v8ka99qac8rcm2tzjjnuktyrl'); await element(by.id('AddressInput')).replaceText('bc1q063ctu6jhe5k4v8ka99qac8rcm2tzjjnuktyrl');
await element(by.id('advancedOptionsMenuButton')).tap(); await element(by.id('advancedOptionsMenuButton')).tap();
await element(by.id('sendMaxButton')).tap(); await element(by.text('Use Full Balance')).tap();
await element(by.text('OK')).tap(); await element(by.text('OK')).tap();
// setting fee rate: // setting fee rate:
await element(by.id('chooseFee')).tap(); await element(by.id('chooseFee')).tap();
@ -539,7 +539,7 @@ describe('BlueWallet UI Tests - import BIP84 wallet', () => {
await element(by.id('SendButton')).tap(); await element(by.id('SendButton')).tap();
await element(by.id('AddressInput')).replaceText('bc1q063ctu6jhe5k4v8ka99qac8rcm2tzjjnuktyrl'); await element(by.id('AddressInput')).replaceText('bc1q063ctu6jhe5k4v8ka99qac8rcm2tzjjnuktyrl');
await element(by.id('advancedOptionsMenuButton')).tap(); await element(by.id('advancedOptionsMenuButton')).tap();
await element(by.id('sendMaxButton')).tap(); await element(by.text('Use Full Balance')).tap();
await element(by.text('OK')).tap(); await element(by.text('OK')).tap();
// setting fee rate: // setting fee rate:
await element(by.id('chooseFee')).tap(); await element(by.id('chooseFee')).tap();

View file

@ -56,7 +56,7 @@ describe('BlueWallet UI Tests - import Watch-only wallet (zpub)', () => {
await element(by.text('OK')).tap(); await element(by.text('OK')).tap();
await element(by.id('advancedOptionsMenuButton')).tap(); await element(by.id('advancedOptionsMenuButton')).tap();
await element(by.id('ImportQrTransactionButton')).tap(); // opens camera await element(by.text('Import Transaction (QR)')).tap(); // opens camera
// produced by real Keystone device using MNEMONICS_KEYSTONE // produced by real Keystone device using MNEMONICS_KEYSTONE
const unsignedPsbt = const unsignedPsbt =