mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-03-15 11:59:21 +01:00
TST: Update tests
This commit is contained in:
parent
89d5c8e357
commit
2a0e83d019
3 changed files with 190 additions and 202 deletions
|
@ -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,10 +679,33 @@ 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) => {
|
* same as `importTransaction`, but opens camera instead.
|
||||||
|
*
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
const importQrTransaction = () => {
|
||||||
|
if (wallet?.type !== WatchOnlyWallet.type) {
|
||||||
|
return presentAlert({ title: loc.errors.error, message: 'Importing transaction in non-watchonly wallet (this should never happen)' });
|
||||||
|
}
|
||||||
|
|
||||||
|
requestCameraAuthorization().then(() => {
|
||||||
|
feeModalRef.current?.dismiss();
|
||||||
|
|
||||||
|
navigation.navigate('ScanQRCodeRoot', {
|
||||||
|
screen: 'ScanQRCode',
|
||||||
|
params: {
|
||||||
|
onBarScanned: importQrTransactionOnBarScanned,
|
||||||
|
showFileImportButton: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const importQrTransactionOnBarScanned = (ret: any) => {
|
||||||
navigation.getParent()?.getParent()?.dispatch(popAction);
|
navigation.getParent()?.getParent()?.dispatch(popAction);
|
||||||
if (!wallet) return;
|
if (!wallet) return;
|
||||||
if (!ret.data) ret = { data: ret };
|
if (!ret.data) ret = { data: ret };
|
||||||
|
@ -687,6 +716,7 @@ const SendDetails = () => {
|
||||||
// we dont support it in this flow
|
// we dont support it in this flow
|
||||||
} else {
|
} else {
|
||||||
feeModalRef.current?.dismiss();
|
feeModalRef.current?.dismiss();
|
||||||
|
|
||||||
// psbt base64?
|
// psbt base64?
|
||||||
|
|
||||||
// we construct PSBT object and pass to next screen
|
// we construct PSBT object and pass to next screen
|
||||||
|
@ -700,31 +730,7 @@ const SendDetails = () => {
|
||||||
});
|
});
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
[navigation, popAction, transactionMemo, wallet],
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* same as `importTransaction`, but opens camera instead.
|
|
||||||
*
|
|
||||||
* @returns {Promise<void>}
|
|
||||||
*/
|
|
||||||
const importQrTransaction = useCallback(() => {
|
|
||||||
if (wallet?.type !== WatchOnlyWallet.type) {
|
|
||||||
return presentAlert({ title: loc.errors.error, message: 'Importing transaction in non-watchonly wallet (this should never happen)' });
|
|
||||||
}
|
|
||||||
|
|
||||||
requestCameraAuthorization().then(() => {
|
|
||||||
feeModalRef.current?.dismiss();
|
|
||||||
navigation.navigate('ScanQRCodeRoot', {
|
|
||||||
screen: 'ScanQRCode',
|
|
||||||
params: {
|
|
||||||
onBarScanned: importQrTransactionOnBarScanned,
|
|
||||||
showFileImportButton: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}, [importQrTransactionOnBarScanned, navigation, wallet?.type]);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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,8 +814,7 @@ 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;
|
||||||
|
@ -834,16 +839,13 @@ const SendDetails = () => {
|
||||||
presentAlert({ title: loc.send.problem_with_psbt, message: error.message });
|
presentAlert({ title: loc.send.problem_with_psbt, message: error.message });
|
||||||
}
|
}
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
},
|
};
|
||||||
[navigation, sleep, transactionMemo, wallet],
|
|
||||||
);
|
|
||||||
|
|
||||||
const importTransactionMultisig = useCallback(() => {
|
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')) {
|
||||||
|
@ -855,12 +857,10 @@ const SendDetails = () => {
|
||||||
// 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]}>
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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 =
|
||||||
|
|
Loading…
Add table
Reference in a new issue