Merge branch 'master' into elecd

This commit is contained in:
Marcos Rodriguez Velez 2024-10-03 00:25:39 -04:00
commit 14f0ca1c4b
11 changed files with 77 additions and 121 deletions

View File

@ -362,7 +362,7 @@ const styles = StyleSheet.create({
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
marginVertical: 8,
margin: 16,
},
container: {
flexDirection: 'row',

View File

@ -26,7 +26,7 @@ function scanQrHelper(
if (useMerge) {
const onBarScanned = function (data: any) {
setTimeout(() => resolve(data.data || data), 1);
navigationRef.navigate({ name: currentScreenName, params: {}, merge: true });
navigationRef.navigate({ name: currentScreenName, params: data, merge: true });
};
params = {

View File

@ -35,7 +35,7 @@ export type SendDetailsStackParamList = {
};
PsbtWithHardwareWallet: {
memo?: string;
fromWallet: TWallet;
walletID: string;
launchedBy?: string;
psbt?: Psbt;
txhex?: string;
@ -79,18 +79,4 @@ export type SendDetailsStackParamList = {
PaymentCodeList: {
walletID: string;
};
ScanQRCodeRoot: {
screen: string;
params: {
isLoading?: boolean;
cameraStatusGranted?: boolean;
backdoorPressed?: boolean;
launchedBy?: string;
urTotal?: number;
urHave?: number;
backdoorText?: string;
showFileImportButton?: boolean;
onBarScanned: (data: string) => void;
};
};
};

View File

@ -25,7 +25,7 @@ import AmountInput from '../../components/AmountInput';
import Button from '../../components/Button';
import { useTheme } from '../../components/themes';
import { presentWalletExportReminder } from '../../helpers/presentWalletExportReminder';
import { requestCameraAuthorization } from '../../helpers/scan-qr';
import { scanQrHelper } from '../../helpers/scan-qr';
import loc, { formatBalance, formatBalancePlain, formatBalanceWithoutSuffix } from '../../loc';
import { BitcoinUnit, Chain } from '../../models/bitcoinUnits';
import * as NavigationService from '../../NavigationService';
@ -325,16 +325,8 @@ const LNDCreateInvoice = () => {
};
const navigateToScanQRCode = () => {
requestCameraAuthorization().then(() => {
NavigationService.navigate('ScanQRCodeRoot', {
screen: 'ScanQRCode',
params: {
onBarScanned: processLnurl,
launchedBy: name,
},
});
Keyboard.dismiss();
});
scanQrHelper(name, true, processLnurl);
Keyboard.dismiss();
};
const renderScanClickable = () => {

View File

@ -39,7 +39,7 @@ import Button from '../../components/Button';
import CoinsSelected from '../../components/CoinsSelected';
import InputAccessoryAllFunds, { InputAccessoryAllFundsAccessoryViewID } from '../../components/InputAccessoryAllFunds';
import { useTheme } from '../../components/themes';
import { requestCameraAuthorization, scanQrHelper } from '../../helpers/scan-qr';
import { scanQrHelper } from '../../helpers/scan-qr';
import loc, { formatBalance, formatBalanceWithoutSuffix } from '../../loc';
import { BitcoinUnit, Chain } from '../../models/bitcoinUnits';
import NetworkTransactionFees, { NetworkTransactionFee } from '../../models/networkTransactionFees';
@ -600,7 +600,6 @@ const SendDetails = () => {
if (tx && routeParams.launchedBy && psbt) {
console.warn('navigating back to ', routeParams.launchedBy);
feeModalRef.current?.dismiss();
// @ts-ignore idk how to fix FIXME?
@ -608,14 +607,12 @@ const SendDetails = () => {
}
if (wallet?.type === WatchOnlyWallet.type) {
feeModalRef.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
navigation.navigate('PsbtWithHardwareWallet', {
memo: transactionMemo,
fromWallet: wallet,
walletID: wallet.getID(),
psbt,
launchedBy: routeParams.launchedBy,
});
@ -624,8 +621,6 @@ const SendDetails = () => {
}
if (wallet?.type === MultisigHDWallet.type) {
feeModalRef.current?.dismiss();
navigation.navigate('PsbtMultisig', {
memo: transactionMemo,
psbtBase64: psbt.toBase64(),
@ -650,7 +645,6 @@ const SendDetails = () => {
// (ez can be the case for single-address wallet when doing self-payment for consolidation)
recipients = outputs;
}
feeModalRef.current?.dismiss();
navigation.navigate('Confirm', {
fee: new BigNumber(fee).dividedBy(100000000).toNumber(),
@ -679,22 +673,13 @@ const SendDetails = () => {
*
* @returns {Promise<void>}
*/
const importQrTransaction = () => {
const importQrTransaction = async () => {
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 data = await scanQrHelper(route.name, true);
importQrTransactionOnBarScanned(data);
};
const importQrTransactionOnBarScanned = (ret: any) => {
@ -707,8 +692,6 @@ const SendDetails = () => {
// 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
@ -717,7 +700,7 @@ const SendDetails = () => {
navigation.navigate('PsbtWithHardwareWallet', {
memo: transactionMemo,
fromWallet: wallet,
walletID: wallet.getID(),
psbt,
});
setIsLoading(false);
@ -751,7 +734,7 @@ const SendDetails = () => {
const file = await RNFS.readFile(res.uri, 'ascii');
const psbt = bitcoin.Psbt.fromBase64(file);
const txhex = psbt.extractTransaction().toHex();
navigation.navigate('PsbtWithHardwareWallet', { memo: transactionMemo, fromWallet: wallet, txhex });
navigation.navigate('PsbtWithHardwareWallet', { memo: transactionMemo, walletID: wallet.getID(), txhex });
setIsLoading(false);
return;
@ -762,7 +745,7 @@ const SendDetails = () => {
// so user can do smth with it:
const file = await RNFS.readFile(res.uri, 'ascii');
const psbt = bitcoin.Psbt.fromBase64(file);
navigation.navigate('PsbtWithHardwareWallet', { memo: transactionMemo, fromWallet: wallet, psbt });
navigation.navigate('PsbtWithHardwareWallet', { memo: transactionMemo, walletID: wallet.getID(), psbt });
setIsLoading(false);
return;
@ -771,7 +754,7 @@ const SendDetails = () => {
if (DeeplinkSchemaMatch.isTXNFile(res.uri)) {
// plain text file with txhex ready to broadcast
const file = (await RNFS.readFile(res.uri, 'ascii')).replace('\n', '').replace('\r', '');
navigation.navigate('PsbtWithHardwareWallet', { memo: transactionMemo, fromWallet: wallet, txhex: file });
navigation.navigate('PsbtWithHardwareWallet', { memo: transactionMemo, walletID: wallet.getID(), txhex: file });
setIsLoading(false);
return;
@ -852,15 +835,8 @@ const SendDetails = () => {
};
const importTransactionMultisigScanQr = async () => {
await requestCameraAuthorization().then(() => {
navigation.navigate('ScanQRCodeRoot', {
screen: 'ScanQRCode',
params: {
onBarScanned,
showFileImportButton: true,
},
});
});
const data = await scanQrHelper(route.name, true);
onBarScanned(data);
};
const handleAddRecipient = () => {
@ -1173,8 +1149,6 @@ const SendDetails = () => {
accessibilityRole="button"
style={styles.selectTouch}
onPress={() => {
feeModalRef.current?.dismiss();
navigation.navigate('SelectWallet', { chainType: Chain.ONCHAIN });
}}
>

View File

@ -5,7 +5,7 @@ import { BlueButtonLink, BlueCard, BlueSpacing10, BlueSpacing20, BlueText } from
import Button from '../../components/Button';
import SafeArea from '../../components/SafeArea';
import { useTheme } from '../../components/themes';
import { requestCameraAuthorization } from '../../helpers/scan-qr';
import { scanQrHelper } from '../../helpers/scan-qr';
import loc from '../../loc';
import { useStorage } from '../../hooks/context/useStorage';
import { useExtendedNavigation } from '../../hooks/useExtendedNavigation';
@ -57,16 +57,7 @@ const IsItMyAddress = () => {
};
const importScan = () => {
requestCameraAuthorization().then(() => {
navigate('ScanQRCodeRoot', {
screen: 'ScanQRCode',
params: {
launchedBy: name,
onBarScanned,
showFileImportButton: true,
},
});
});
scanQrHelper(name, true, onBarScanned);
};
const clearAddressInput = () => {

View File

@ -15,18 +15,19 @@ import { DynamicQRCode } from '../../components/DynamicQRCode';
import SaveFileButton from '../../components/SaveFileButton';
import { SecondButton } from '../../components/SecondButton';
import { useTheme } from '../../components/themes';
import { requestCameraAuthorization } from '../../helpers/scan-qr';
import { scanQrHelper } from '../../helpers/scan-qr';
import { useBiometrics, unlockWithBiometrics } from '../../hooks/useBiometrics';
import loc from '../../loc';
import { useStorage } from '../../hooks/context/useStorage';
import { useExtendedNavigation } from '../../hooks/useExtendedNavigation';
const PsbtWithHardwareWallet = () => {
const { txMetadata, fetchAndSaveWalletTransactions, isElectrumDisabled } = useStorage();
const { txMetadata, fetchAndSaveWalletTransactions, isElectrumDisabled, wallets } = useStorage();
const { isBiometricUseCapableAndEnabled } = useBiometrics();
const navigation = useExtendedNavigation();
const route = useRoute();
const { fromWallet, memo, psbt, deepLinkPSBT, launchedBy } = route.params;
const { walletID, memo, psbt, deepLinkPSBT, launchedBy } = route.params;
const wallet = wallets.find(w => w.getID() === walletID);
const routeParamsPSBT = useRef(route.params.psbt);
const routeParamsTXHex = route.params.txhex;
const { colors } = useTheme();
@ -60,7 +61,7 @@ const PsbtWithHardwareWallet = () => {
});
const _combinePSBT = receivedPSBT => {
return fromWallet.combinePsbt(psbt, receivedPSBT);
return wallet.combinePsbt(psbt, receivedPSBT);
};
const onBarScanned = ret => {
@ -104,7 +105,7 @@ const PsbtWithHardwareWallet = () => {
if (deepLinkPSBT) {
const newPsbt = bitcoin.Psbt.fromBase64(deepLinkPSBT);
try {
const Tx = fromWallet.combinePsbt(routeParamsPSBT.current, newPsbt);
const Tx = wallet.combinePsbt(routeParamsPSBT.current, newPsbt);
setTxHex(Tx.toHex());
} catch (Err) {
presentAlert({ message: Err });
@ -128,7 +129,7 @@ const PsbtWithHardwareWallet = () => {
try {
await BlueElectrum.ping();
await BlueElectrum.waitTillConnected();
const result = await fromWallet.broadcastTx(txHex);
const result = await wallet.broadcastTx(txHex);
if (result) {
setIsLoading(false);
const txDecoded = bitcoin.Transaction.fromHex(txHex);
@ -139,7 +140,7 @@ const PsbtWithHardwareWallet = () => {
}
navigation.navigate('Success', { amount: undefined });
await new Promise(resolve => setTimeout(resolve, 3000)); // sleep to make sure network propagates
fetchAndSaveWalletTransactions(fromWallet.getID());
fetchAndSaveWalletTransactions(wallet.getID());
} else {
triggerHapticFeedback(HapticFeedbackTypes.NotificationError);
setIsLoading(false);
@ -214,17 +215,11 @@ const PsbtWithHardwareWallet = () => {
}
};
const openScanner = () => {
requestCameraAuthorization().then(() => {
navigation.navigate('ScanQRCodeRoot', {
screen: 'ScanQRCode',
params: {
launchedBy: route.name,
showFileImportButton: false,
onBarScanned,
},
});
});
const openScanner = async () => {
const data = await scanQrHelper(route.name, true);
if (data) {
onBarScanned(data);
}
};
if (txHex) return _renderBroadcastHex();

View File

@ -499,7 +499,7 @@ const ManageWallets: React.FC = () => {
return (
<GestureHandlerRootView style={[{ backgroundColor: colors.background }, styles.root]}>
<NestableScrollContainer contentInsetAdjustmentBehavior="automatic" automaticallyAdjustContentInsets>
<NestableScrollContainer contentInsetAdjustmentBehavior="automatic" automaticallyAdjustContentInsets scrollEnabled>
{renderHeader}
<NestableDraggableFlatList
data={state.tempOrder.filter((item): item is WalletItem => item.type === ItemType.WalletSection)}

View File

@ -4,6 +4,7 @@ import {
Alert,
I18nManager,
InteractionManager,
LayoutAnimation,
ScrollView,
StyleSheet,
Switch,
@ -63,7 +64,7 @@ const WalletDetails: React.FC = () => {
);
const [hideTransactionsInWalletsList, setHideTransactionsInWalletsList] = useState<boolean>(
wallet.getHideTransactionsInWalletsList ? wallet.getHideTransactionsInWalletsList() : false,
wallet.getHideTransactionsInWalletsList ? !wallet.getHideTransactionsInWalletsList() : true,
);
const { setOptions, navigate, addListener } = useExtendedNavigation();
const { colors } = useTheme();
@ -85,6 +86,7 @@ const WalletDetails: React.FC = () => {
}
}, [wallet]);
const [isToolTipMenuVisible, setIsToolTipMenuVisible] = useState<boolean>(false);
const [isMasterFingerPrintVisible, setIsMasterFingerPrintVisible] = useState<boolean>(false);
const onMenuWillShow = () => setIsToolTipMenuVisible(true);
const onMenuWillHide = () => setIsToolTipMenuVisible(false);
@ -96,17 +98,19 @@ const WalletDetails: React.FC = () => {
useFocusEffect(
useCallback(() => {
const task = InteractionManager.runAfterInteractions(() => {
if (wallet.allowMasterFingerprint && wallet.allowMasterFingerprint()) {
if (isMasterFingerPrintVisible && wallet.allowMasterFingerprint && wallet.allowMasterFingerprint()) {
// @ts-expect-error: Need to fix later
if (wallet.getMasterFingerprintHex) {
// @ts-expect-error: Need to fix later
setMasterFingerprint(wallet.getMasterFingerprintHex());
}
} else {
setMasterFingerprint(undefined);
}
});
return () => task.cancel();
}, [wallet]),
}, [isMasterFingerPrintVisible, wallet]),
);
const stylesHook = StyleSheet.create({
@ -279,16 +283,18 @@ const WalletDetails: React.FC = () => {
};
const walletNameTextInputOnBlur = useCallback(async () => {
if (walletName.trim().length === 0) {
const trimmedWalletName = walletName.trim();
if (trimmedWalletName.length === 0) {
const walletLabel = wallet.getLabel();
setWalletName(walletLabel);
} else {
wallet.setLabel(walletName.trim());
} else if (wallet.getLabel() !== trimmedWalletName) {
// Only save if the name has changed
wallet.setLabel(trimmedWalletName);
try {
console.warn('saving wallet name:', walletName.trim());
console.warn('saving wallet name:', trimmedWalletName);
await saveToDisk();
} catch (error) {
console.log((error as Error).message);
console.error((error as Error).message);
}
}
}, [wallet, walletName, saveToDisk]);
@ -373,6 +379,11 @@ const WalletDetails: React.FC = () => {
return `${label}-history.csv`;
}, [wallet]);
const onViewMasterFingerPrintPress = () => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
setIsMasterFingerPrintVisible(true);
};
return (
<ScrollView
automaticallyAdjustKeyboardInsets
@ -430,7 +441,9 @@ const WalletDetails: React.FC = () => {
</View>
<BlueSpacing20 />
<Text style={[styles.textLabel1, stylesHook.textLabel1]}>{loc.wallets.details_type.toLowerCase()}</Text>
<Text style={[styles.textValue, stylesHook.textValue]}>{wallet.typeReadable}</Text>
<Text style={[styles.textValue, stylesHook.textValue]} selectable>
{wallet.typeReadable}
</Text>
{wallet.type === MultisigHDWallet.type && (
<>
@ -473,9 +486,9 @@ const WalletDetails: React.FC = () => {
disabled={isToolTipMenuVisible}
value={hideTransactionsInWalletsList}
onValueChange={async (value: boolean) => {
setHideTransactionsInWalletsList(value);
if (wallet.setHideTransactionsInWalletsList) {
wallet.setHideTransactionsInWalletsList(value);
wallet.setHideTransactionsInWalletsList(!value);
setHideTransactionsInWalletsList(!wallet.getHideTransactionsInWalletsList());
}
try {
await saveToDisk();
@ -545,14 +558,22 @@ const WalletDetails: React.FC = () => {
{wallet.allowMasterFingerprint && wallet.allowMasterFingerprint() && (
<View style={styles.marginRight16}>
<Text style={[styles.textLabel2, stylesHook.textLabel2]}>{loc.wallets.details_master_fingerprint.toLowerCase()}</Text>
<BlueText>{masterFingerprint ?? <ActivityIndicator />}</BlueText>
{isMasterFingerPrintVisible ? (
<BlueText selectable>{masterFingerprint ?? <ActivityIndicator />}</BlueText>
) : (
<TouchableOpacity onPress={onViewMasterFingerPrintPress}>
<BlueText>{loc.multisig.view}</BlueText>
</TouchableOpacity>
)}
</View>
)}
{derivationPath && (
<View>
<Text style={[styles.textLabel2, stylesHook.textLabel2]}>{loc.wallets.details_derivation_path}</Text>
<BlueText testID="DerivationPath">{derivationPath}</BlueText>
<BlueText selectable testID="DerivationPath">
{derivationPath}
</BlueText>
</View>
)}
</View>

View File

@ -469,8 +469,10 @@ const WalletsAddMultisigStep2 = () => {
const scanOrOpenFile = async () => {
await provideMnemonicsModalRef.current.dismiss();
const scanned = await scanQrHelper(name, true, undefined);
onBarScanned({ data: scanned });
const scanned = await scanQrHelper(name, true);
if (scanned) {
onBarScanned(scanned);
}
};
const dashType = ({ index, lastIndex, isChecked, isFocus }) => {

View File

@ -4,7 +4,7 @@ import { Keyboard, Platform, StyleSheet, TouchableWithoutFeedback, View, ScrollV
import { BlueButtonLink, BlueFormLabel, BlueFormMultiInput, BlueSpacing20 } from '../../BlueComponents';
import Button from '../../components/Button';
import { useTheme } from '../../components/themes';
import { requestCameraAuthorization } from '../../helpers/scan-qr';
import { scanQrHelper } from '../../helpers/scan-qr';
import usePrivacy from '../../hooks/usePrivacy';
import loc from '../../loc';
import {
@ -96,16 +96,11 @@ const WalletsImport = () => {
setTimeout(() => importMnemonic(value), 500);
};
const importScan = () => {
requestCameraAuthorization().then(() =>
navigation.navigate('ScanQRCodeRoot', {
screen: 'ScanQRCode',
params: {
launchedBy: route.name,
showFileImportButton: true,
},
}),
);
const importScan = async () => {
const data = await scanQrHelper(navigation, true);
if (data) {
onBarScanned(data);
}
};
const speedBackdoorTap = () => {