mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-01-18 21:35:21 +01:00
Merge branch 'master' into scanlndhook
This commit is contained in:
commit
ba907b6ceb
@ -345,6 +345,7 @@ export class BlueWalletNavigationHeader extends Component {
|
||||
<LinearGradient
|
||||
colors={WalletGradient.gradientsFor(this.state.wallet.type)}
|
||||
style={{ padding: 15, minHeight: 140, justifyContent: 'center' }}
|
||||
{...WalletGradient.linearGradientProps(this.state.wallet.type)}
|
||||
>
|
||||
<Image
|
||||
source={(() => {
|
||||
@ -452,6 +453,34 @@ export class BlueWalletNavigationHeader extends Component {
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
{this.state.wallet.type === MultisigHDWallet.type && (
|
||||
<TouchableOpacity onPress={this.manageFundsPressed}>
|
||||
<View
|
||||
style={{
|
||||
marginTop: 14,
|
||||
marginBottom: 10,
|
||||
backgroundColor: 'rgba(255,255,255,0.2)',
|
||||
borderRadius: 9,
|
||||
minHeight: 39,
|
||||
alignSelf: 'flex-start',
|
||||
paddingHorizontal: 12,
|
||||
height: 39,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
style={{
|
||||
fontWeight: '500',
|
||||
fontSize: 14,
|
||||
color: '#FFFFFF',
|
||||
}}
|
||||
>
|
||||
{loc.multisig.manage_keys}
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</LinearGradient>
|
||||
);
|
||||
}
|
||||
@ -915,15 +944,13 @@ export const BlueSpacing40 = props => {
|
||||
return <View {...props} style={{ height: 50 }} />;
|
||||
};
|
||||
|
||||
export class BlueSpacingVariable extends Component {
|
||||
render() {
|
||||
if (isIpad) {
|
||||
return <BlueSpacing40 {...this.props} />;
|
||||
} else {
|
||||
return <BlueSpacing {...this.props} />;
|
||||
}
|
||||
export const BlueSpacingVariable = props => {
|
||||
if (isIpad) {
|
||||
return <BlueSpacing40 {...props} />;
|
||||
} else {
|
||||
return <BlueSpacing {...props} />;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export class is {
|
||||
static ipad() {
|
||||
@ -1015,61 +1042,59 @@ export class BlueUseAllFundsButton extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
export class BlueDismissKeyboardInputAccessory extends Component {
|
||||
static InputAccessoryViewID = 'BlueDismissKeyboardInputAccessory';
|
||||
export const BlueDismissKeyboardInputAccessory = () => {
|
||||
const { colors } = useTheme();
|
||||
BlueDismissKeyboardInputAccessory.InputAccessoryViewID = 'BlueDismissKeyboardInputAccessory';
|
||||
|
||||
render() {
|
||||
return Platform.OS !== 'ios' ? null : (
|
||||
<InputAccessoryView nativeID={BlueDismissKeyboardInputAccessory.InputAccessoryViewID}>
|
||||
<View
|
||||
style={{
|
||||
backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor,
|
||||
height: 44,
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'flex-end',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<BlueButtonLink title={loc.send.input_done} onPress={() => Keyboard.dismiss()} />
|
||||
</View>
|
||||
</InputAccessoryView>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class BlueDoneAndDismissKeyboardInputAccessory extends Component {
|
||||
static InputAccessoryViewID = 'BlueDoneAndDismissKeyboardInputAccessory';
|
||||
|
||||
onPasteTapped = async () => {
|
||||
const clipboard = await Clipboard.getString();
|
||||
this.props.onPasteTapped(clipboard);
|
||||
};
|
||||
|
||||
render() {
|
||||
const inputView = (
|
||||
return Platform.OS !== 'ios' ? null : (
|
||||
<InputAccessoryView nativeID={BlueDismissKeyboardInputAccessory.InputAccessoryViewID}>
|
||||
<View
|
||||
style={{
|
||||
backgroundColor: BlueCurrentTheme.colors.inputBackgroundColor,
|
||||
backgroundColor: colors.inputBackgroundColor,
|
||||
height: 44,
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'flex-end',
|
||||
alignItems: 'center',
|
||||
maxHeight: 44,
|
||||
}}
|
||||
>
|
||||
<BlueButtonLink title={loc.send.input_clear} onPress={this.props.onClearTapped} />
|
||||
<BlueButtonLink title={loc.send.input_paste} onPress={this.onPasteTapped} />
|
||||
<BlueButtonLink title={loc.send.input_done} onPress={() => Keyboard.dismiss()} />
|
||||
<BlueButtonLink title={loc.send.input_done} onPress={Keyboard.dismiss} />
|
||||
</View>
|
||||
);
|
||||
</InputAccessoryView>
|
||||
);
|
||||
};
|
||||
|
||||
if (Platform.OS === 'ios') {
|
||||
return <InputAccessoryView nativeID={BlueDoneAndDismissKeyboardInputAccessory.InputAccessoryViewID}>{inputView}</InputAccessoryView>;
|
||||
} else {
|
||||
return <KeyboardAvoidingView>{inputView}</KeyboardAvoidingView>;
|
||||
}
|
||||
export const BlueDoneAndDismissKeyboardInputAccessory = props => {
|
||||
const { colors } = useTheme();
|
||||
BlueDoneAndDismissKeyboardInputAccessory.InputAccessoryViewID = 'BlueDoneAndDismissKeyboardInputAccessory';
|
||||
|
||||
const onPasteTapped = async () => {
|
||||
const clipboard = await Clipboard.getString();
|
||||
props.onPasteTapped(clipboard);
|
||||
};
|
||||
|
||||
const inputView = (
|
||||
<View
|
||||
style={{
|
||||
backgroundColor: colors.inputBackgroundColor,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'flex-end',
|
||||
alignItems: 'center',
|
||||
maxHeight: 44,
|
||||
}}
|
||||
>
|
||||
<BlueButtonLink title={loc.send.input_clear} onPress={props.onClearTapped} />
|
||||
<BlueButtonLink title={loc.send.input_paste} onPress={onPasteTapped} />
|
||||
<BlueButtonLink title={loc.send.input_done} onPress={Keyboard.dismiss} />
|
||||
</View>
|
||||
);
|
||||
|
||||
if (Platform.OS === 'ios') {
|
||||
return <InputAccessoryView nativeID={BlueDoneAndDismissKeyboardInputAccessory.InputAccessoryViewID}>{inputView}</InputAccessoryView>;
|
||||
} else {
|
||||
return <KeyboardAvoidingView>{inputView}</KeyboardAvoidingView>;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const BlueLoading = props => {
|
||||
return (
|
||||
|
@ -9,7 +9,7 @@ const createHash = require('create-hash');
|
||||
*/
|
||||
export default class Lnurl {
|
||||
static TAG_PAY_REQUEST = 'payRequest'; // type of LNURL
|
||||
static TAG_WITHDRAW_REQUEST = "withdrawRequest"; // type of LNURL
|
||||
static TAG_WITHDRAW_REQUEST = 'withdrawRequest'; // type of LNURL
|
||||
|
||||
constructor(url, AsyncStorage) {
|
||||
this._lnurl = url;
|
||||
@ -31,12 +31,12 @@ export default class Lnurl {
|
||||
const found = Lnurl.findlnurl(lnurlExample);
|
||||
if (!found) return false;
|
||||
|
||||
const decoded = bech32.decode(lnurlExample, 10000);
|
||||
const decoded = bech32.decode(found, 10000);
|
||||
return Buffer.from(bech32.fromWords(decoded.words)).toString();
|
||||
}
|
||||
|
||||
static isLnurl(url) {
|
||||
return Lnurl.findlnurl(url) !== null
|
||||
return Lnurl.findlnurl(url) !== null;
|
||||
}
|
||||
|
||||
async fetchGet(url) {
|
||||
|
@ -72,6 +72,21 @@ export default class WalletGradient {
|
||||
return gradient;
|
||||
}
|
||||
|
||||
static linearGradientProps(type) {
|
||||
let props;
|
||||
switch (type) {
|
||||
case MultisigHDWallet.type:
|
||||
/* Example
|
||||
props = { start: { x: 0, y: 0 } };
|
||||
https://github.com/react-native-linear-gradient/react-native-linear-gradient
|
||||
*/
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
static headerColorFor(type) {
|
||||
let gradient;
|
||||
switch (type) {
|
||||
|
@ -171,6 +171,9 @@ export class AbstractWallet {
|
||||
// It is a ColdCard Hardware Wallet
|
||||
masterFingerprint = Number(parsedSecret.keystore.ckcc_xfp);
|
||||
}
|
||||
if (parsedSecret.keystore.label) {
|
||||
this.setLabel(parsedSecret.keystore.label);
|
||||
}
|
||||
this.secret = parsedSecret.keystore.xpub;
|
||||
this.masterFingerprint = masterFingerprint;
|
||||
}
|
||||
|
@ -278,7 +278,7 @@ PODS:
|
||||
- react-native-tcp-socket (3.7.1):
|
||||
- CocoaAsyncSocket
|
||||
- React
|
||||
- react-native-webview (10.10.0):
|
||||
- react-native-webview (11.0.0):
|
||||
- React-Core
|
||||
- react-native-widget-center (0.0.4):
|
||||
- React
|
||||
@ -359,7 +359,7 @@ PODS:
|
||||
- React-Core
|
||||
- RNDefaultPreference (1.4.3):
|
||||
- React
|
||||
- RNDeviceInfo (6.2.0):
|
||||
- RNDeviceInfo (7.0.2):
|
||||
- React-Core
|
||||
- RNFS (2.16.6):
|
||||
- React
|
||||
@ -709,7 +709,7 @@ SPEC CHECKSUMS:
|
||||
react-native-safe-area-context: 01158a92c300895d79dee447e980672dc3fb85a6
|
||||
react-native-slider: b733e17fdd31186707146debf1f04b5d94aa1a93
|
||||
react-native-tcp-socket: 96a4f104cdcc9c6621aafe92937f163d88447c5b
|
||||
react-native-webview: 2e330b109bfd610e9818bf7865d1979f898960a7
|
||||
react-native-webview: f0da708d7e471b60ebdbf861c114d2c5d7f7af2d
|
||||
react-native-widget-center: 0f81d17beb163e7fb5848b06754d7d277fe7d99a
|
||||
React-RCTActionSheet: 53ea72699698b0b47a6421cb1c8b4ab215a774aa
|
||||
React-RCTAnimation: 1befece0b5183c22ae01b966f5583f42e69a83c2
|
||||
@ -729,7 +729,7 @@ SPEC CHECKSUMS:
|
||||
RNCMaskedView: f5c7d14d6847b7b44853f7acb6284c1da30a3459
|
||||
RNCPushNotificationIOS: eaf01f848a0b872b194d31bcad94bb864299e01e
|
||||
RNDefaultPreference: 21816c0a6f61a2829ccc0cef034392e9b509ee5f
|
||||
RNDeviceInfo: 980848feea8d74412b16f2e3e8758c8294d63ca2
|
||||
RNDeviceInfo: a37a15a98822c31c3982cb28eba6d336ba4d0968
|
||||
RNFS: 2bd9eb49dc82fa9676382f0585b992c424cd59df
|
||||
RNGestureHandler: 7a5833d0f788dbd107fbb913e09aa0c1ff333c39
|
||||
RNHandoff: d3b0754cca3a6bcd9b25f544f733f7f033ccf5fa
|
||||
|
@ -406,6 +406,7 @@
|
||||
"xpub_copiedToClipboard": "Copied to clipboard.",
|
||||
"pull_to_refresh": "Pull to Refresh",
|
||||
"warning_do_not_disclose": "Warning! Do not disclose",
|
||||
"add_ln_wallet_first": "You must first add a Lightning wallet.",
|
||||
"xpub_title": "Wallet XPUB"
|
||||
},
|
||||
"multisig": {
|
||||
@ -419,6 +420,7 @@
|
||||
"confirm": "Confirm",
|
||||
"header": "Send",
|
||||
"share": "Share",
|
||||
"manage_keys": "Manage Keys",
|
||||
"how_many_signatures_can_bluewallet_make": "How Many Signatures Can BlueWallet Make",
|
||||
"scan_or_import_file": "Scan or import file",
|
||||
"export_coordination_setup": "Export Coordination Setup",
|
||||
|
@ -42,7 +42,7 @@ const LNDCreateInvoice = () => {
|
||||
const { name } = useRoute();
|
||||
const { colors } = useTheme();
|
||||
const { navigate, dangerouslyGetParent, goBack, pop, setParams } = useNavigation();
|
||||
const [unit, setUnit] = useState(wallet.current.getPreferredBalanceUnit());
|
||||
const [unit, setUnit] = useState(wallet.current?.getPreferredBalanceUnit() || BitcoinUnit.BTC);
|
||||
const [amount, setAmount] = useState();
|
||||
const [renderWalletSelectionButtonHidden, setRenderWalletSelectionButtonHidden] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
@ -131,6 +131,10 @@ const LNDCreateInvoice = () => {
|
||||
},
|
||||
});
|
||||
}
|
||||
} else {
|
||||
ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false });
|
||||
alert(loc.wallets.add_ln_wallet_first);
|
||||
goBack();
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [wallet]),
|
||||
@ -194,7 +198,7 @@ const LNDCreateInvoice = () => {
|
||||
|
||||
navigate('LNDViewInvoice', {
|
||||
invoice: invoiceRequest,
|
||||
walletID,
|
||||
walletID: wallet.current.getID(),
|
||||
isModal: true,
|
||||
});
|
||||
} catch (Err) {
|
||||
@ -206,7 +210,7 @@ const LNDCreateInvoice = () => {
|
||||
|
||||
const processLnurl = async data => {
|
||||
setIsLoading(true);
|
||||
if (!wallet) {
|
||||
if (!wallet.current) {
|
||||
ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false });
|
||||
alert(loc.wallets.no_ln_wallet_error);
|
||||
return goBack();
|
||||
@ -233,7 +237,7 @@ const LNDCreateInvoice = () => {
|
||||
screen: 'LnurlPay',
|
||||
params: {
|
||||
lnurl: data,
|
||||
fromWalletID: walletID || wallet.current.getID(),
|
||||
fromWalletID: wallet.current.getID(),
|
||||
},
|
||||
});
|
||||
return;
|
||||
@ -342,7 +346,7 @@ const LNDCreateInvoice = () => {
|
||||
pop();
|
||||
};
|
||||
|
||||
if (wallet.current === undefined || !walletID) {
|
||||
if (!wallet.current) {
|
||||
return (
|
||||
<View style={[styles.root, styleHooks.root]}>
|
||||
<StatusBar barStyle="light-content" />
|
||||
|
@ -189,6 +189,7 @@ const WalletsAddMultisigStep2 = () => {
|
||||
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
||||
setCosigners(cosignersCopy);
|
||||
setVaultKeyData({ keyIndex: cosignersCopy.length, seed: w.getSecret(), xpub: w.getXpub(), isLoading: false });
|
||||
setIsLoading(true);
|
||||
setIsMnemonicsModalVisible(true);
|
||||
if (cosignersCopy.length === n) setIsOnCreateButtonEnabled(true);
|
||||
// filling cache
|
||||
@ -196,6 +197,7 @@ const WalletsAddMultisigStep2 = () => {
|
||||
// filling cache
|
||||
setXpubCacheForMnemonics(w.getSecret());
|
||||
setFpCacheForMnemonics(w.getSecret());
|
||||
setIsLoading(false);
|
||||
}, 500);
|
||||
});
|
||||
};
|
||||
@ -570,7 +572,11 @@ const WalletsAddMultisigStep2 = () => {
|
||||
<BlueSpacing10 />
|
||||
<View style={styles.secretContainer}>{renderSecret(vaultKeyData.seed.split(' '))}</View>
|
||||
<BlueSpacing20 />
|
||||
<BlueButton title={loc.send.success_done} onPress={() => setIsMnemonicsModalVisible(false)} />
|
||||
{isLoading ? (
|
||||
<ActivityIndicator />
|
||||
) : (
|
||||
<BlueButton title={loc.send.success_done} onPress={() => setIsMnemonicsModalVisible(false)} />
|
||||
)}
|
||||
</View>
|
||||
</BottomModal>
|
||||
);
|
||||
|
@ -12,7 +12,7 @@ import { BlueStorageContext } from '../../blue_modules/storage-context';
|
||||
const styles = StyleSheet.create({
|
||||
loading: {
|
||||
flex: 1,
|
||||
paddingTop: 20,
|
||||
justifyContent: 'center',
|
||||
},
|
||||
root: {
|
||||
flex: 1,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useCallback, useContext, useState } from 'react';
|
||||
import React, { useCallback, useContext, useRef, useState } from 'react';
|
||||
import { ActivityIndicator, InteractionManager, ScrollView, StatusBar, StyleSheet, View } from 'react-native';
|
||||
import { BlueNavigationStyle, BlueSpacing20, BlueText, SafeBlueArea } from '../../BlueComponents';
|
||||
import { DynamicQRCode } from '../../components/DynamicQRCode';
|
||||
@ -14,29 +14,32 @@ const ExportMultisigCoordinationSetup = () => {
|
||||
const walletId = useRoute().params.walletId;
|
||||
const { wallets } = useContext(BlueStorageContext);
|
||||
const wallet = wallets.find(w => w.getID() === walletId);
|
||||
const qrCodeContents = Buffer.from(wallet.getXpub(), 'ascii').toString('hex');
|
||||
const qrCodeContents = useRef();
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [isShareButtonTapped, setIsShareButtonTapped] = useState(false);
|
||||
const { goBack } = useNavigation();
|
||||
const { colors } = useTheme();
|
||||
const stylesHook = {
|
||||
...styles,
|
||||
const stylesHook = StyleSheet.create({
|
||||
loading: {
|
||||
...styles.loading,
|
||||
backgroundColor: colors.elevated,
|
||||
},
|
||||
root: {
|
||||
...styles.root,
|
||||
backgroundColor: colors.elevated,
|
||||
},
|
||||
type: { ...styles.type, color: colors.foregroundColor },
|
||||
secret: { ...styles.secret, color: colors.foregroundColor },
|
||||
type: { color: colors.foregroundColor },
|
||||
secret: { color: colors.foregroundColor },
|
||||
exportButton: {
|
||||
backgroundColor: colors.buttonDisabledBackgroundColor,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
const exportTxtFile = async () => {
|
||||
await fs.writeFileAndExport(wallet.getLabel() + '.txt', wallet.getXpub());
|
||||
setIsShareButtonTapped(true);
|
||||
setTimeout(() => {
|
||||
fs.writeFileAndExport(wallet.getLabel() + '.txt', wallet.getXpub()).finally(() => {
|
||||
setIsShareButtonTapped(false);
|
||||
});
|
||||
}, 10);
|
||||
};
|
||||
|
||||
useFocusEffect(
|
||||
@ -51,7 +54,7 @@ const ExportMultisigCoordinationSetup = () => {
|
||||
return goBack();
|
||||
}
|
||||
}
|
||||
|
||||
qrCodeContents.current = Buffer.from(wallet.getXpub(), 'ascii').toString('hex');
|
||||
setIsLoading(false);
|
||||
}
|
||||
});
|
||||
@ -63,22 +66,26 @@ const ExportMultisigCoordinationSetup = () => {
|
||||
);
|
||||
|
||||
return isLoading ? (
|
||||
<View style={stylesHook.loading}>
|
||||
<View style={[styles.loading, stylesHook.loading]}>
|
||||
<ActivityIndicator />
|
||||
</View>
|
||||
) : (
|
||||
<SafeBlueArea style={stylesHook.root}>
|
||||
<SafeBlueArea style={[styles.root, stylesHook.root]}>
|
||||
<StatusBar barStyle="light-content" />
|
||||
<ScrollView contentContainerStyle={styles.scrollViewContent}>
|
||||
<View>
|
||||
<BlueText style={stylesHook.type}>{wallet.getLabel()}</BlueText>
|
||||
<BlueText style={[styles.type, stylesHook.type]}>{wallet.getLabel()}</BlueText>
|
||||
</View>
|
||||
<BlueSpacing20 />
|
||||
<DynamicQRCode value={qrCodeContents} capacity={400} />
|
||||
<DynamicQRCode value={qrCodeContents.current} capacity={400} />
|
||||
<BlueSpacing20 />
|
||||
<SquareButton style={[styles.exportButton, stylesHook.exportButton]} onPress={exportTxtFile} title={loc.multisig.share} />
|
||||
{isShareButtonTapped ? (
|
||||
<ActivityIndicator />
|
||||
) : (
|
||||
<SquareButton style={[styles.exportButton, stylesHook.exportButton]} onPress={exportTxtFile} title={loc.multisig.share} />
|
||||
)}
|
||||
<BlueSpacing20 />
|
||||
<BlueText style={stylesHook.secret}>{wallet.getXpub()}</BlueText>
|
||||
<BlueText style={[styles.secret, stylesHook.secret]}>{wallet.getXpub()}</BlueText>
|
||||
</ScrollView>
|
||||
</SafeBlueArea>
|
||||
);
|
||||
@ -87,7 +94,7 @@ const ExportMultisigCoordinationSetup = () => {
|
||||
const styles = StyleSheet.create({
|
||||
loading: {
|
||||
flex: 1,
|
||||
paddingTop: 20,
|
||||
justifyContent: 'center',
|
||||
},
|
||||
root: {
|
||||
flex: 1,
|
||||
|
@ -1,27 +1,18 @@
|
||||
import React, { Component } from 'react';
|
||||
import React from 'react';
|
||||
import { WebView } from 'react-native-webview';
|
||||
import { BlueNavigationStyle, SafeBlueArea } from '../../BlueComponents';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useRoute } from '@react-navigation/native';
|
||||
|
||||
export default class HodlHodlWebview extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
const HodlHodlWebview = () => {
|
||||
const { uri } = useRoute().params;
|
||||
|
||||
const uri = props.route.params.uri;
|
||||
|
||||
this.state = {
|
||||
uri,
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<SafeBlueArea>
|
||||
<WebView source={{ uri: this.state.uri }} incognito />
|
||||
</SafeBlueArea>
|
||||
);
|
||||
}
|
||||
}
|
||||
return (
|
||||
<SafeBlueArea>
|
||||
<WebView source={{ uri }} incognito />
|
||||
</SafeBlueArea>
|
||||
);
|
||||
};
|
||||
|
||||
HodlHodlWebview.propTypes = {
|
||||
route: PropTypes.shape({
|
||||
@ -31,6 +22,8 @@ HodlHodlWebview.propTypes = {
|
||||
}),
|
||||
};
|
||||
|
||||
export default HodlHodlWebview;
|
||||
|
||||
HodlHodlWebview.navigationOptions = ({ navigation }) => ({
|
||||
...BlueNavigationStyle(navigation, true),
|
||||
title: '',
|
||||
|
@ -26,7 +26,7 @@ import { useRoute, useNavigation, useTheme, useFocusEffect } from '@react-naviga
|
||||
import { Chain } from '../../models/bitcoinUnits';
|
||||
import { BlueTransactionListItem, BlueWalletNavigationHeader, BlueAlertWalletExportReminder, BlueListItem } from '../../BlueComponents';
|
||||
import WalletGradient from '../../class/wallet-gradient';
|
||||
import { LightningCustodianWallet, WatchOnlyWallet } from '../../class';
|
||||
import { LightningCustodianWallet, MultisigHDWallet, WatchOnlyWallet } from '../../class';
|
||||
import HandoffSettings from '../../class/handoff';
|
||||
import ActionSheet from '../ActionSheet';
|
||||
import loc from '../../loc';
|
||||
@ -569,6 +569,12 @@ const WalletTransactions = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const navigateToViewEditCosigners = () => {
|
||||
navigate('ViewEditMultisigCosigners', {
|
||||
walletId: wallet.current.getID(),
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={styles.flex}>
|
||||
<StatusBar barStyle="light-content" backgroundColor={WalletGradient.headerColorFor(wallet.current.type)} />
|
||||
@ -588,23 +594,27 @@ const WalletTransactions = () => {
|
||||
})
|
||||
}
|
||||
onManageFundsPressed={() => {
|
||||
if (wallet.current.getUserHasSavedExport()) {
|
||||
setIsManageFundsModalVisible(true);
|
||||
} else {
|
||||
BlueAlertWalletExportReminder({
|
||||
onSuccess: async () => {
|
||||
wallet.current.setUserHasSavedExport(true);
|
||||
await saveToDisk();
|
||||
setIsManageFundsModalVisible(true);
|
||||
},
|
||||
onFailure: () =>
|
||||
navigate('WalletExportRoot', {
|
||||
screen: 'WalletExport',
|
||||
params: {
|
||||
walletID: wallet.current.getID(),
|
||||
},
|
||||
}),
|
||||
});
|
||||
if (wallet.current.type === MultisigHDWallet.type) {
|
||||
navigateToViewEditCosigners();
|
||||
} else if (wallet.current.type === LightningCustodianWallet.type) {
|
||||
if (wallet.current.getUserHasSavedExport()) {
|
||||
setIsManageFundsModalVisible(true);
|
||||
} else {
|
||||
BlueAlertWalletExportReminder({
|
||||
onSuccess: async () => {
|
||||
wallet.current.setUserHasSavedExport(true);
|
||||
await saveToDisk();
|
||||
setIsManageFundsModalVisible(true);
|
||||
},
|
||||
onFailure: () =>
|
||||
navigate('WalletExportRoot', {
|
||||
screen: 'WalletExport',
|
||||
params: {
|
||||
walletID: wallet.current.getID(),
|
||||
},
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
@ -41,6 +41,8 @@ import MultipleStepsListItem, {
|
||||
MultipleStepsListItemDashType,
|
||||
} from '../../components/MultipleStepsListItem';
|
||||
import ScanQRCode from '../send/ScanQRCode';
|
||||
import Privacy from '../../Privacy';
|
||||
import Biometric from '../../class/biometrics';
|
||||
const LocalQRCode = require('@remobile/react-native-qrcode-local-image');
|
||||
|
||||
const isDesktop = getSystemName() === 'Mac OS X';
|
||||
@ -48,7 +50,7 @@ const isDesktop = getSystemName() === 'Mac OS X';
|
||||
const ViewEditMultisigCosigners = () => {
|
||||
const { colors } = useTheme();
|
||||
const { wallets, setWalletsWithNewOrder } = useContext(BlueStorageContext);
|
||||
const { navigate, goBack } = useNavigation();
|
||||
const { navigate } = useNavigation();
|
||||
const route = useRoute();
|
||||
const { walletId } = route.params;
|
||||
const w = useRef(wallets.find(wallet => wallet.getID() === walletId));
|
||||
@ -121,6 +123,16 @@ const ViewEditMultisigCosigners = () => {
|
||||
|
||||
const onSave = async () => {
|
||||
setIsLoading(true);
|
||||
|
||||
const isBiometricsEnabled = await Biometric.isBiometricUseCapableAndEnabled();
|
||||
|
||||
if (isBiometricsEnabled) {
|
||||
if (!(await Biometric.unlockWithBiometrics())) {
|
||||
setIsLoading(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line prefer-const
|
||||
let newWallets = wallets.filter(w => {
|
||||
return w.getID() !== walletId;
|
||||
@ -128,14 +140,22 @@ const ViewEditMultisigCosigners = () => {
|
||||
await wallet.fetchBalance();
|
||||
newWallets.push(wallet);
|
||||
setWalletsWithNewOrder(newWallets);
|
||||
goBack();
|
||||
goBack();
|
||||
goBack();
|
||||
navigate('WalletsList');
|
||||
};
|
||||
useFocusEffect(
|
||||
useCallback(() => {
|
||||
setIsLoading(true);
|
||||
const task = InteractionManager.runAfterInteractions(() => {
|
||||
|
||||
Privacy.enableBlur();
|
||||
|
||||
const task = InteractionManager.runAfterInteractions(async () => {
|
||||
const isBiometricsEnabled = await Biometric.isBiometricUseCapableAndEnabled();
|
||||
|
||||
if (isBiometricsEnabled) {
|
||||
if (!(await Biometric.unlockWithBiometrics())) {
|
||||
return goBack();
|
||||
}
|
||||
}
|
||||
if (!w.current) {
|
||||
// lets create fake wallet so renderer wont throw any errors
|
||||
w.current = new MultisigHDWallet();
|
||||
@ -148,9 +168,11 @@ const ViewEditMultisigCosigners = () => {
|
||||
setIsLoading(false);
|
||||
});
|
||||
return () => {
|
||||
Privacy.disableBlur();
|
||||
task.cancel();
|
||||
};
|
||||
}, []),
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [walletId]),
|
||||
);
|
||||
|
||||
const hideMnemonicsModal = () => {
|
||||
|
@ -165,6 +165,22 @@ describe('unit - DeepLinkSchemaMatch', function () {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
argument: {
|
||||
url:
|
||||
'https://lnbits.com/?lightning=LNURL1DP68GURN8GHJ7MRWVF5HGUEWVDHK6TMHD96XSERJV9MJ7CTSDYHHVVF0D3H82UNV9UM9JDENFPN5SMMK2359J5RKWVMKZ5ZVWAV4VJD63TM',
|
||||
},
|
||||
expected: [
|
||||
'LNDCreateInvoiceRoot',
|
||||
{
|
||||
screen: 'LNDCreateInvoice',
|
||||
params: {
|
||||
uri:
|
||||
'https://lnbits.com/?lightning=LNURL1DP68GURN8GHJ7MRWVF5HGUEWVDHK6TMHD96XSERJV9MJ7CTSDYHHVVF0D3H82UNV9UM9JDENFPN5SMMK2359J5RKWVMKZ5ZVWAV4VJD63TM',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const asyncNavigationRouteFor = async function (event) {
|
||||
|
@ -21,6 +21,12 @@ describe('LNURL', function () {
|
||||
Lnurl.getUrlFromLnurl('LNURL1DP68GURN8GHJ7MRWW3UXYMM59E3XJEMNW4HZU7RE0GHKCMN4WFKZ7URP0YLH2UM9WF5KG0FHXYCNV9G9W58'),
|
||||
'https://lntxbot.bigsun.xyz/lnurl/pay?userid=7116',
|
||||
);
|
||||
assert.strictEqual(
|
||||
Lnurl.getUrlFromLnurl(
|
||||
'https://lnbits.com/?lightning=LNURL1DP68GURN8GHJ7MRWVF5HGUEWVDHK6TMHD96XSERJV9MJ7CTSDYHHVVF0D3H82UNV9UM9JDENFPN5SMMK2359J5RKWVMKZ5ZVWAV4VJD63TM',
|
||||
),
|
||||
'https://lnbits.com/withdraw/api/v1/lnurl/6Y73HgHovThYPvs7aPLwYV',
|
||||
);
|
||||
assert.strictEqual(Lnurl.getUrlFromLnurl('bs'), false);
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user