Merge pull request #6872 from BlueWallet/menu

REF: Use tooltip menu for SendDetails on Android
This commit is contained in:
GLaDOS 2024-08-08 17:42:40 +00:00 committed by GitHub
commit 812319154b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 116 additions and 145 deletions

View File

@ -36,7 +36,7 @@ const ToolTipMenu = React.memo((props: ToolTipMenuProps, ref?: Ref<any>) => {
actionKey: action.id.toString(),
actionTitle: action.text,
icon: action.icon?.iconValue ? ({ iconType: 'SYSTEM', iconValue: action.icon.iconValue } as IconConfig) : undefined,
state: action.menuStateOn ? ('on' as MenuState) : ('off' as MenuState),
state: action.menuState ?? undefined,
attributes: action.disabled ? ['disabled'] : [],
};
}, []);
@ -46,8 +46,7 @@ const ToolTipMenu = React.memo((props: ToolTipMenuProps, ref?: Ref<any>) => {
return {
id: action.id.toString(),
title: action.text,
image: action.menuStateOn && Platform.OS === 'android' ? 'checkbox_on_background' : action.icon?.iconValue || undefined,
state: action.menuStateOn ? ('on' as MenuState) : undefined,
state: action.menuState === undefined ? undefined : ((action.menuState ? 'on' : 'off') as MenuState),
attributes: { disabled: action.disabled },
};
}, []);

View File

@ -7,7 +7,7 @@ export interface Action {
iconValue: string;
};
menuTitle?: string;
menuStateOn?: boolean;
menuState?: 'mixed' | boolean | undefined;
disabled?: boolean;
displayInline?: boolean;
}

View File

@ -21,7 +21,6 @@
"close": "Close",
"change_input_currency": "Change input currency",
"refresh": "Refresh",
"more": "More",
"pick_image": "Choose image from library",
"pick_file": "Choose a file",
"enter_amount": "Enter amount",

76
package-lock.json generated
View File

@ -20,7 +20,7 @@
"@react-native-async-storage/async-storage": "1.24.0",
"@react-native-clipboard/clipboard": "1.14.1",
"@react-native-community/push-notification-ios": "1.11.0",
"@react-native-menu/menu": "1.1.2",
"@react-native-menu/menu": "https://github.com/BlueWallet/menu.git#958fac3d40811f38b53042ada9168175e321b99f",
"@react-native/metro-config": "0.74.87",
"@react-navigation/drawer": "6.7.2",
"@react-navigation/native": "6.1.18",
@ -3550,6 +3550,8 @@
},
"node_modules/@react-native-menu/menu": {
"version": "1.1.2",
"resolved": "git+ssh://git@github.com/BlueWallet/menu.git#958fac3d40811f38b53042ada9168175e321b99f",
"integrity": "sha512-0j8qsd04s36qSLQIFZ0mfpgzikZU0A0lriq4OFaUvCFfDTDgc5iVKnVr0MzxkFa66qX4NuCbhiQ82Fsdar5RHA==",
"license": "MIT",
"peerDependencies": {
"react": "*",
@ -3784,8 +3786,6 @@
},
"node_modules/@react-native/eslint-config/node_modules/eslint-config-prettier": {
"version": "8.10.0",
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz",
"integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==",
"dev": true,
"license": "MIT",
"bin": {
@ -3928,8 +3928,6 @@
},
"node_modules/@react-native/eslint-config/node_modules/eslint-plugin-prettier": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz",
"integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -3948,6 +3946,61 @@
}
}
},
"node_modules/@react-native/eslint-config/node_modules/eslint-plugin-react": {
"version": "7.35.0",
"dev": true,
"license": "MIT",
"dependencies": {
"array-includes": "^3.1.8",
"array.prototype.findlast": "^1.2.5",
"array.prototype.flatmap": "^1.3.2",
"array.prototype.tosorted": "^1.1.4",
"doctrine": "^2.1.0",
"es-iterator-helpers": "^1.0.19",
"estraverse": "^5.3.0",
"hasown": "^2.0.2",
"jsx-ast-utils": "^2.4.1 || ^3.0.0",
"minimatch": "^3.1.2",
"object.entries": "^1.1.8",
"object.fromentries": "^2.0.8",
"object.values": "^1.2.0",
"prop-types": "^15.8.1",
"resolve": "^2.0.0-next.5",
"semver": "^6.3.1",
"string.prototype.matchall": "^4.0.11",
"string.prototype.repeat": "^1.0.0"
},
"engines": {
"node": ">=4"
},
"peerDependencies": {
"eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7"
}
},
"node_modules/@react-native/eslint-config/node_modules/eslint-plugin-react/node_modules/semver": {
"version": "6.3.1",
"dev": true,
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/@react-native/eslint-config/node_modules/resolve": {
"version": "2.0.0-next.5",
"dev": true,
"license": "MIT",
"dependencies": {
"is-core-module": "^2.13.0",
"path-parse": "^1.0.7",
"supports-preserve-symlinks-flag": "^1.0.0"
},
"bin": {
"resolve": "bin/resolve"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/@react-native/eslint-plugin": {
"version": "0.74.87",
"resolved": "https://registry.npmjs.org/@react-native/eslint-plugin/-/eslint-plugin-0.74.87.tgz",
@ -14874,6 +14927,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/string.prototype.repeat": {
"version": "1.0.0",
"dev": true,
"license": "MIT",
"dependencies": {
"define-properties": "^1.1.3",
"es-abstract": "^1.17.5"
}
},
"node_modules/string.prototype.trim": {
"version": "1.2.9",
"dev": true,
@ -15342,6 +15404,8 @@
},
"node_modules/tsutils": {
"version": "3.21.0",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
"integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -15356,6 +15420,8 @@
},
"node_modules/tsutils/node_modules/tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
"dev": true,
"license": "0BSD"
},

View File

@ -114,7 +114,7 @@
"@react-native-async-storage/async-storage": "1.24.0",
"@react-native-clipboard/clipboard": "1.14.1",
"@react-native-community/push-notification-ios": "1.11.0",
"@react-native-menu/menu": "1.1.2",
"@react-native-menu/menu": "https://github.com/BlueWallet/menu.git#958fac3d40811f38b53042ada9168175e321b99f",
"@react-navigation/drawer": "6.7.2",
"@react-navigation/native": "6.1.18",
"@react-navigation/native-stack": "6.11.0",

View File

@ -19,7 +19,6 @@ import {
Text,
TextInput,
TouchableOpacity,
TouchableWithoutFeedback,
View,
} from 'react-native';
import DocumentPicker from 'react-native-document-picker';
@ -36,11 +35,10 @@ import { AbstractHDElectrumWallet } from '../../class/wallets/abstract-hd-electr
import AddressInput from '../../components/AddressInput';
import presentAlert from '../../components/Alert';
import AmountInput from '../../components/AmountInput';
import BottomModal, { BottomModalHandle } from '../../components/BottomModal';
import { BottomModalHandle } from '../../components/BottomModal';
import Button from '../../components/Button';
import CoinsSelected from '../../components/CoinsSelected';
import InputAccessoryAllFunds from '../../components/InputAccessoryAllFunds';
import ListItem from '../../components/ListItem';
import { useTheme } from '../../components/themes';
import ToolTipMenu from '../../components/TooltipMenu';
import { requestCameraAuthorization, scanQrHelper } from '../../helpers/scan-qr';
@ -92,10 +90,9 @@ const SendDetails = () => {
const [isLoading, setIsLoading] = useState(false);
const [wallet, setWallet] = useState<TWallet | null>(null);
const feeModalRef = useRef<BottomModalHandle>(null);
const optionsModalRef = useRef<BottomModalHandle>(null);
const [walletSelectionOrCoinsSelectedHidden, setWalletSelectionOrCoinsSelectedHidden] = useState(false);
const [isAmountToolbarVisibleForAndroid, setIsAmountToolbarVisibleForAndroid] = useState(false);
const [isTransactionReplaceable, setIsTransactionReplaceable] = useState<boolean>(false);
const [isTransactionReplaceable, setIsTransactionReplaceable] = useState<boolean | undefined>(false);
const [addresses, setAddresses] = useState<IPaymentDestinations[]>([]);
const [units, setUnits] = useState<BitcoinUnit[]>([]);
const [transactionMemo, setTransactionMemo] = useState<string>('');
@ -288,8 +285,7 @@ const SendDetails = () => {
// reset other values
setUtxo(null);
setChangeAddress(null);
setIsTransactionReplaceable(wallet.type === HDSegwitBech32Wallet.type && !routeParams.noRbf);
setIsTransactionReplaceable(wallet.type === HDSegwitBech32Wallet.type && !routeParams.noRbf ? true : undefined);
// update wallet UTXO
wallet
.fetchUtxo()
@ -390,7 +386,6 @@ const SendDetails = () => {
setDumb(v => !v);
return () => {
feeModalRef.current?.dismiss();
optionsModalRef.current?.dismiss();
};
}, []),
);
@ -614,7 +609,7 @@ const SendDetails = () => {
if (tx && routeParams.launchedBy && psbt) {
console.warn('navigating back to ', routeParams.launchedBy);
feeModalRef.current?.dismiss();
optionsModalRef.current?.dismiss();
// @ts-ignore idk how to fix FIXME?
navigation.navigate(routeParams.launchedBy, { psbt });
@ -622,7 +617,7 @@ const SendDetails = () => {
if (wallet?.type === WatchOnlyWallet.type) {
feeModalRef.current?.dismiss();
optionsModalRef.current?.dismiss();
// 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
// user whether he wants to broadcast it
@ -638,7 +633,7 @@ const SendDetails = () => {
if (wallet?.type === MultisigHDWallet.type) {
feeModalRef.current?.dismiss();
optionsModalRef.current?.dismiss();
navigation.navigate('PsbtMultisig', {
memo: transactionMemo,
psbtBase64: psbt.toBase64(),
@ -664,7 +659,6 @@ const SendDetails = () => {
recipients = outputs;
}
feeModalRef.current?.dismiss();
optionsModalRef.current?.dismiss();
navigation.navigate('Confirm', {
fee: new BigNumber(fee).dividedBy(100000000).toNumber(),
@ -700,7 +694,7 @@ const SendDetails = () => {
requestCameraAuthorization().then(() => {
feeModalRef.current?.dismiss();
optionsModalRef.current?.dismiss();
navigation.navigate('ScanQRCodeRoot', {
screen: 'ScanQRCode',
params: {
@ -722,7 +716,7 @@ const SendDetails = () => {
// we dont support it in this flow
} else {
feeModalRef.current?.dismiss();
optionsModalRef.current?.dismiss();
// psbt base64?
// we construct PSBT object and pass to next screen
@ -747,7 +741,6 @@ const SendDetails = () => {
* @returns {Promise<void>}
*/
const importTransaction = async () => {
await optionsModalRef.current?.dismiss();
if (wallet?.type !== WatchOnlyWallet.type) {
return presentAlert({ title: loc.errors.error, message: 'Importing transaction in non-watchonly wallet (this should never happen)' });
}
@ -822,7 +815,6 @@ const SendDetails = () => {
};
const _importTransactionMultisig = async (base64arg: string | false) => {
await optionsModalRef.current?.dismiss();
try {
const base64 = base64arg || (await fs.openSignedTransaction());
if (!base64) return;
@ -868,8 +860,7 @@ const SendDetails = () => {
};
const importTransactionMultisigScanQr = async () => {
await optionsModalRef.current?.dismiss();
requestCameraAuthorization().then(() => {
await requestCameraAuthorization().then(() => {
navigation.navigate('ScanQRCodeRoot', {
screen: 'ScanQRCode',
params: {
@ -882,8 +873,7 @@ const SendDetails = () => {
const handleAddRecipient = async () => {
console.debug('handleAddRecipient');
await optionsModalRef.current?.dismiss();
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
scrollView.current?.scrollToEnd();
@ -892,7 +882,6 @@ const SendDetails = () => {
};
const handleRemoveRecipient = async () => {
await optionsModalRef.current?.dismiss();
const last = scrollIndex.current === addresses.length - 1;
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
setAddresses(addrs => {
@ -907,7 +896,6 @@ const SendDetails = () => {
};
const handleCoinControl = async () => {
await optionsModalRef.current?.dismiss();
if (!wallet) return;
navigation.navigate('CoinControl', {
walletID: wallet?.getID(),
@ -916,13 +904,11 @@ const SendDetails = () => {
};
const handleInsertContact = async () => {
await optionsModalRef.current?.dismiss();
if (!wallet) return;
navigation.navigate('PaymentCodeList', { walletID: wallet.getID() });
};
const handlePsbtSign = async () => {
await optionsModalRef.current?.dismiss();
setIsLoading(true);
await new Promise(resolve => setTimeout(resolve, 100)); // sleep for animations
@ -1006,8 +992,8 @@ const SendDetails = () => {
actions.push([{ id: SendDetails.actionKeys.SendMax, text: loc.send.details_adv_full, disabled: balance === 0 || isSendMaxUsed }]);
}
if (wallet?.type === HDSegwitBech32Wallet.type) {
actions.push([{ id: SendDetails.actionKeys.AllowRBF, text: loc.send.details_adv_fee_bump, menuStateOn: isTransactionReplaceable }]);
if (wallet?.type === HDSegwitBech32Wallet.type && isTransactionReplaceable !== undefined) {
actions.push([{ id: SendDetails.actionKeys.AllowRBF, text: loc.send.details_adv_fee_bump, menuState: !!isTransactionReplaceable }]);
}
const transactionActions = [];
if (wallet?.type === WatchOnlyWallet.type && wallet.isHd()) {
@ -1060,38 +1046,22 @@ const SendDetails = () => {
return actions;
};
const setHeaderRightOptions = () => {
navigation.setOptions({
headerRight: Platform.select({
// eslint-disable-next-line react/no-unstable-nested-components
ios: () => (
<ToolTipMenu
disabled={isLoading}
isButton
isMenuPrimaryAction
onPressMenuItem={headerRightOnPress}
// @ts-ignore idk how to fix
actions={headerRightActions()}
>
<Icon size={22} name="more-horiz" type="material" color={colors.foregroundColor} style={styles.advancedOptions} />
</ToolTipMenu>
),
// eslint-disable-next-line react/no-unstable-nested-components
default: () => (
<TouchableOpacity
accessibilityRole="button"
accessibilityLabel={loc._.more}
disabled={isLoading}
style={styles.advancedOptions}
onPress={() => {
optionsModalRef.current?.present();
}}
testID="advancedOptionsMenuButton"
>
<Icon size={22} name="more-horiz" type="material" color={colors.foregroundColor} />
</TouchableOpacity>
),
}),
// 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>
),
});
};
@ -1119,8 +1089,7 @@ const SendDetails = () => {
scrollIndex.current = index;
};
const onUseAllPressed = async () => {
await optionsModalRef.current?.dismiss();
const onUseAllPressed = () => {
triggerHapticFeedback(HapticFeedbackTypes.NotificationWarning);
const message = frozenBalance > 0 ? loc.send.details_adv_full_sure_frozen : loc.send.details_adv_full_sure;
Alert.alert(
@ -1145,9 +1114,7 @@ const SendDetails = () => {
},
{
text: loc._.cancel,
onPress: () => {
optionsModalRef.current?.present();
},
onPress: () => {},
style: 'cancel',
},
],
@ -1194,60 +1161,6 @@ const SendDetails = () => {
return totalWithFee;
};
const renderOptionsModal = () => {
const isSendMaxUsed = addresses.some(element => element.amount === BitcoinUnit.MAX);
return (
<BottomModal ref={optionsModalRef} backgroundColor={colors.modal} contentContainerStyle={styles.optionsContent}>
{wallet?.allowBIP47() && wallet.isBIP47Enabled() && (
<ListItem testID="InsertContactButton" title={loc.send.details_insert_contact} onPress={handleInsertContact} />
)}
{isEditable && (
<ListItem
testID="sendMaxButton"
disabled={balance === 0 || isSendMaxUsed}
title={loc.send.details_adv_full}
onPress={onUseAllPressed}
/>
)}
{wallet?.type === HDSegwitBech32Wallet.type && isEditable && (
<ListItem
title={loc.send.details_adv_fee_bump}
Component={TouchableWithoutFeedback}
switch={{ value: isTransactionReplaceable, onValueChange: onReplaceableFeeSwitchValueChanged }}
/>
)}
{wallet?.type === WatchOnlyWallet.type && wallet.isHd() && (
<ListItem title={loc.send.details_adv_import} onPress={importTransaction} />
)}
{wallet?.type === WatchOnlyWallet.type && wallet.isHd() && (
<ListItem testID="ImportQrTransactionButton" title={loc.send.details_adv_import_qr} onPress={importQrTransaction} />
)}
{wallet?.type === MultisigHDWallet.type && isEditable && (
<ListItem title={loc.send.details_adv_import} onPress={importTransactionMultisig} />
)}
{wallet?.type === MultisigHDWallet.type && wallet.howManySignaturesCanWeMake() > 0 && isEditable && (
<ListItem title={loc.multisig.co_sign_transaction} onPress={importTransactionMultisigScanQr} />
)}
{isEditable && (
<>
<ListItem testID="AddRecipient" title={loc.send.details_add_rec_add} onPress={handleAddRecipient} />
<ListItem
testID="RemoveRecipient"
title={loc.send.details_add_rec_rem}
disabled={addresses.length < 2}
onPress={handleRemoveRecipient}
/>
</>
)}
<ListItem testID="CoinControl" title={loc.cc.header} onPress={handleCoinControl} />
{(wallet as MultisigHDWallet)?.allowCosignPsbt() && isEditable && (
<ListItem testID="PsbtSign" title={loc.send.psbt_sign} onPress={handlePsbtSign} />
)}
</BottomModal>
);
};
const renderCreateButton = () => {
const totalWithFee = calculateTotalAmount();
const isDisabled = totalWithFee === 0 || totalWithFee > balance || balance === 0 || isLoading || addresses.length === 0;
@ -1288,7 +1201,7 @@ const SendDetails = () => {
style={styles.selectTouch}
onPress={() => {
feeModalRef.current?.dismiss();
optionsModalRef.current?.dismiss();
navigation.navigate('SelectWallet', { chainType: Chain.ONCHAIN });
}}
>
@ -1475,7 +1388,6 @@ const SendDetails = () => {
setCustomFee={setCustomFee}
setFeePrecalc={setFeePrecalc}
/>
{renderOptionsModal()}
</KeyboardAvoidingView>
</View>
<BlueDismissKeyboardInputAccessory />
@ -1538,11 +1450,6 @@ const styles = StyleSheet.create({
bottom: 0,
right: 8,
},
optionsContent: {
padding: 22,
},
createButton: {
marginVertical: 16,
marginHorizontal: 16,

View File

@ -208,23 +208,23 @@ describe('BlueWallet UI Tests - import BIP84 wallet', () => {
// lest add another two outputs
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 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('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
// remove last output, check if second output is shown
await element(by.id('advancedOptionsMenuButton')).tap();
await element(by.id('RemoveRecipient')).tap();
await element(by.text('Remove Recipient')).tap();
await yo('Transaction1');
// adding it again
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 element(by.id('AddressInput').withAncestor(by.id('Transaction2'))).replaceText('bc1qh6tf004ty7z7un2v5ntu4mkf630545gvhs45u7');
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 sleep(5000);
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
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('BitcoinAmountInput')).typeText('0.0001\n');
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();
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 element(by.id('advancedOptionsMenuButton')).tap();
await element(by.id('AddRecipient')).tap();
await element(by.text('Add Recipient')).tap();
await yo('Transaction1');
await element(by.id('AddressInput').withAncestor(by.id('Transaction1'))).replaceText('bc1q063ctu6jhe5k4v8ka99qac8rcm2tzjjnuktyrl');
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('advancedOptionsMenuButton')).tap();
await element(by.id('PsbtSign')).tap();
await element(by.text('Sign a transaction')).tap();
// tapping 5 times invisible button is a backdoor:
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.id('SendButton')).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
.not.toExist()
.withTimeout(300 * 1000);
@ -510,7 +510,7 @@ describe('BlueWallet UI Tests - import BIP84 wallet', () => {
await element(by.id('UseCoin')).tap();
await element(by.id('AddressInput')).replaceText('bc1q063ctu6jhe5k4v8ka99qac8rcm2tzjjnuktyrl');
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();
// setting fee rate:
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('AddressInput')).replaceText('bc1q063ctu6jhe5k4v8ka99qac8rcm2tzjjnuktyrl');
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();
// setting fee rate:
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.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
const unsignedPsbt =