mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-02-23 15:20:55 +01:00
Merge branch 'master' into viewinvoicehooks
This commit is contained in:
commit
07500682f9
9 changed files with 66 additions and 77 deletions
|
@ -236,6 +236,7 @@ export class BlueWalletNavigationHeader extends Component {
|
|||
}
|
||||
|
||||
static contextType = BlueStorageContext;
|
||||
walletBalanceText = React.createRef();
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
@ -276,7 +277,7 @@ export class BlueWalletNavigationHeader extends Component {
|
|||
};
|
||||
|
||||
showAndroidTooltip = () => {
|
||||
showPopupMenu(this.toolTipMenuOptions(), this.handleToolTipSelection, this.walletBalanceText);
|
||||
showPopupMenu(this.toolTipMenuOptions(), this.handleToolTipSelection, this.walletBalanceText.current);
|
||||
};
|
||||
|
||||
handleToolTipSelection = item => {
|
||||
|
@ -314,7 +315,7 @@ export class BlueWalletNavigationHeader extends Component {
|
|||
});
|
||||
}
|
||||
|
||||
changeWalletBalanceUnit() {
|
||||
changeWalletBalanceUnit = () => {
|
||||
let walletPreviousPreferredUnit = this.state.wallet.getPreferredBalanceUnit();
|
||||
const wallet = this.state.wallet;
|
||||
if (walletPreviousPreferredUnit === BitcoinUnit.BTC) {
|
||||
|
@ -334,7 +335,7 @@ export class BlueWalletNavigationHeader extends Component {
|
|||
this.setState({ wallet, walletPreviousPreferredUnit: walletPreviousPreferredUnit }, () => {
|
||||
this.props.onWalletUnitChange(wallet);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
manageFundsPressed = () => {
|
||||
this.props.onManageFundsPressed();
|
||||
|
@ -402,8 +403,8 @@ export class BlueWalletNavigationHeader extends Component {
|
|||
)}
|
||||
<TouchableOpacity
|
||||
style={styles.balance}
|
||||
onPress={() => this.changeWalletBalanceUnit()}
|
||||
ref={ref => (this.walletBalanceText = ref)}
|
||||
onPress={this.changeWalletBalanceUnit}
|
||||
ref={this.walletBalanceText}
|
||||
onLongPress={() => (Platform.OS === 'ios' ? this.tooltip.showMenu() : this.showAndroidTooltip())}
|
||||
>
|
||||
{this.state.wallet.hideBalance ? (
|
||||
|
@ -572,7 +573,7 @@ export const BlueCreateTxNavigationStyle = (navigation, withAdvancedOptionsMenuB
|
|||
headerTintColor: BlueCurrentTheme.colors.foregroundColor,
|
||||
headerLeft: () => (
|
||||
<TouchableOpacity
|
||||
style={{ minWwidth: 40, height: 40, justifyContent: 'center', paddingHorizontal: 14 }}
|
||||
style={{ minWidth: 40, height: 40, justifyContent: 'center', paddingHorizontal: 14 }}
|
||||
onPress={() => {
|
||||
Keyboard.dismiss();
|
||||
navigation.goBack(null);
|
||||
|
@ -589,13 +590,13 @@ export const BlueCreateTxNavigationStyle = (navigation, withAdvancedOptionsMenuB
|
|||
export const BluePrivateBalance = () => {
|
||||
return Platform.select({
|
||||
ios: (
|
||||
<View style={{ flexDirection: 'row' }}>
|
||||
<View style={{ flexDirection: 'row', marginTop: 13 }}>
|
||||
<BlurView style={styles.balanceBlur} blurType="light" blurAmount={25} />
|
||||
<Icon name="eye-slash" type="font-awesome" color="#FFFFFF" />
|
||||
</View>
|
||||
),
|
||||
android: (
|
||||
<View style={{ flexDirection: 'row' }}>
|
||||
<View style={{ flexDirection: 'row', marginTop: 13 }}>
|
||||
<View style={{ backgroundColor: '#FFFFFF', opacity: 0.5, height: 30, width: 100, marginRight: 8 }} />
|
||||
<Icon name="eye-slash" type="font-awesome" color="#FFFFFF" />
|
||||
</View>
|
||||
|
|
|
@ -1,21 +1,19 @@
|
|||
/* global alert */
|
||||
import { PermissionsAndroid, Platform } from 'react-native';
|
||||
import { Alert, Linking, PermissionsAndroid, Platform } from 'react-native';
|
||||
import RNFS from 'react-native-fs';
|
||||
import Share from 'react-native-share';
|
||||
import loc from '../loc';
|
||||
import { getSystemName } from 'react-native-device-info';
|
||||
import DocumentPicker from 'react-native-document-picker';
|
||||
import isCatalyst from 'react-native-is-catalyst';
|
||||
const LocalQRCode = require('@remobile/react-native-qrcode-local-image');
|
||||
|
||||
const isDesktop = getSystemName() === 'Mac OS X';
|
||||
|
||||
const writeFileAndExport = async function (filename, contents) {
|
||||
if (Platform.OS === 'ios') {
|
||||
const filePath = RNFS.TemporaryDirectoryPath + `/${filename}`;
|
||||
await RNFS.writeFile(filePath, contents);
|
||||
Share.open({
|
||||
url: 'file://' + filePath,
|
||||
saveToFiles: isDesktop,
|
||||
saveToFiles: isCatalyst,
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
|
@ -39,6 +37,16 @@ const writeFileAndExport = async function (filename, contents) {
|
|||
alert(loc.formatString(loc._.file_saved, { filePath: filename }));
|
||||
} else {
|
||||
console.log('Storage Permission: Denied');
|
||||
Alert.alert(loc.send.permission_storage_title, loc.send.permission_storage_denied_message, [
|
||||
{
|
||||
text: loc.send.open_settings,
|
||||
onPress: () => {
|
||||
Linking.openSettings();
|
||||
},
|
||||
style: 'default',
|
||||
},
|
||||
{ text: loc._.cancel, onPress: () => {}, style: 'cancel' },
|
||||
]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -208,8 +208,9 @@
|
|||
"permission_camera_title": "Permission to use camera",
|
||||
"open_settings": "Open Settings",
|
||||
"permission_storage_later": "Ask Me Later",
|
||||
"permission_storage_message": "BlueWallet needs your permission to access your storage to save this transaction.",
|
||||
"permission_storage_title": "BlueWallet Storage Access Permission",
|
||||
"permission_storage_message": "BlueWallet needs your permission to access your storage to save this file.",
|
||||
"permission_storage_denied_message": "BlueWallet is unable save this file. Please, open your device settings and enable Storage Permission.",
|
||||
"permission_storage_title": "Storage Access Permission",
|
||||
"psbt_clipboard": "Copy to Clipboard",
|
||||
"psbt_this_is_psbt": "This is a partially signed bitcoin transaction (PSBT). Please finish signing it with your hardware wallet.",
|
||||
"psbt_tx_export": "Export to file",
|
||||
|
|
|
@ -14,6 +14,7 @@ import {
|
|||
View,
|
||||
Platform,
|
||||
PermissionsAndroid,
|
||||
Alert,
|
||||
} from 'react-native';
|
||||
import Clipboard from '@react-native-community/clipboard';
|
||||
import { Icon } from 'react-native-elements';
|
||||
|
@ -25,9 +26,8 @@ import Privacy from '../../Privacy';
|
|||
import { BitcoinUnit } from '../../models/bitcoinUnits';
|
||||
import loc from '../../loc';
|
||||
import { BlueCurrentTheme } from '../../components/themes';
|
||||
import { getSystemName } from 'react-native-device-info';
|
||||
import isCatalyst from 'react-native-is-catalyst';
|
||||
const currency = require('../../blue_modules/currency');
|
||||
const isDesktop = getSystemName() === 'Mac OS X';
|
||||
|
||||
export default class SendCreate extends Component {
|
||||
constructor(props) {
|
||||
|
@ -59,7 +59,7 @@ export default class SendCreate extends Component {
|
|||
await RNFS.writeFile(filePath, this.state.tx);
|
||||
Share.open({
|
||||
url: 'file://' + filePath,
|
||||
saveToFiles: isDesktop,
|
||||
saveToFiles: isCatalyst,
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
|
@ -84,6 +84,16 @@ export default class SendCreate extends Component {
|
|||
alert(loc.formatString(loc.send.txSaved, { filePath }));
|
||||
} else {
|
||||
console.log('Storage Permission: Denied');
|
||||
Alert.alert(loc.send.permission_storage_title, loc.send.permission_storage_denied_message, [
|
||||
{
|
||||
text: loc.send.open_settings,
|
||||
onPress: () => {
|
||||
Linking.openSettings();
|
||||
},
|
||||
style: 'default',
|
||||
},
|
||||
{ text: loc._.cancel, onPress: () => {}, style: 'cancel' },
|
||||
]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -222,7 +222,7 @@ export default class SendDetails extends Component {
|
|||
let fromWallet = null;
|
||||
if (props.route.params) fromWallet = props.route.params.fromWallet;
|
||||
|
||||
const wallets = context.wallets.filter(wallet => wallet.type !== LightningCustodianWallet.type);
|
||||
const wallets = context.wallets.filter(wallet => wallet.type !== LightningCustodianWallet.type && wallet.allowSend());
|
||||
|
||||
if (wallets.length === 0) {
|
||||
alert(loc.send.details_wallet_before_tx);
|
||||
|
@ -330,6 +330,7 @@ export default class SendDetails extends Component {
|
|||
|
||||
async componentDidMount() {
|
||||
console.log('send/details - componentDidMount');
|
||||
if (!this.state.fromWallet) return;
|
||||
this.renderNavigationHeader();
|
||||
this.context.setSelectedWallet(this.state.fromWallet.getID());
|
||||
/** @type {BitcoinTransaction[]} */
|
||||
|
|
|
@ -11,6 +11,7 @@ import {
|
|||
PermissionsAndroid,
|
||||
Text,
|
||||
StyleSheet,
|
||||
Alert,
|
||||
} from 'react-native';
|
||||
import ImagePicker from 'react-native-image-picker';
|
||||
import Clipboard from '@react-native-community/clipboard';
|
||||
|
@ -34,6 +35,7 @@ import ScanQRCode from './ScanQRCode';
|
|||
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
||||
import Notifications from '../../blue_modules/notifications';
|
||||
import { useNavigation, useRoute, useTheme } from '@react-navigation/native';
|
||||
import isCatalyst from 'react-native-is-catalyst';
|
||||
const BlueElectrum = require('../../blue_modules/BlueElectrum');
|
||||
/** @type {AppStorage} */
|
||||
const bitcoin = require('bitcoinjs-lib');
|
||||
|
@ -178,7 +180,7 @@ const PsbtWithHardwareWallet = () => {
|
|||
await RNFS.writeFile(filePath, typeof psbt === 'string' ? psbt : psbt.toBase64());
|
||||
Share.open({
|
||||
url: 'file://' + filePath,
|
||||
saveToFiles: isDesktop,
|
||||
saveToFiles: isCatalyst,
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
|
@ -202,6 +204,16 @@ const PsbtWithHardwareWallet = () => {
|
|||
alert(loc.formatString(loc.send.txSaved, { filePath: fileName }));
|
||||
} else {
|
||||
console.log('Storage Permission: Denied');
|
||||
Alert.alert(loc.send.permission_storage_title, loc.send.permission_storage_denied_message, [
|
||||
{
|
||||
text: loc.send.open_settings,
|
||||
onPress: () => {
|
||||
Linking.openSettings();
|
||||
},
|
||||
style: 'default',
|
||||
},
|
||||
{ text: loc._.cancel, onPress: () => {}, style: 'cancel' },
|
||||
]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -29,11 +29,10 @@ import loc from '../../loc';
|
|||
import { useTheme, useRoute, useNavigation } from '@react-navigation/native';
|
||||
import RNFS from 'react-native-fs';
|
||||
import Share from 'react-native-share';
|
||||
import { getSystemName } from 'react-native-device-info';
|
||||
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
||||
import Notifications from '../../blue_modules/notifications';
|
||||
import isCatalyst from 'react-native-is-catalyst';
|
||||
const prompt = require('../../blue_modules/prompt');
|
||||
const isDesktop = getSystemName() === 'Mac OS X';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
|
@ -258,7 +257,7 @@ const WalletDetails = () => {
|
|||
await RNFS.writeFile(filePath, contents);
|
||||
Share.open({
|
||||
url: 'file://' + filePath,
|
||||
saveToFiles: isDesktop,
|
||||
saveToFiles: isCatalyst,
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
|
@ -283,6 +282,16 @@ const WalletDetails = () => {
|
|||
alert(loc.formatString(loc.send.txSaved, { filePath: fileName }));
|
||||
} else {
|
||||
console.log('Storage Permission: Denied');
|
||||
Alert.alert(loc.send.permission_storage_title, loc.send.permission_storage_denied_message, [
|
||||
{
|
||||
text: loc.send.open_settings,
|
||||
onPress: () => {
|
||||
Linking.openSettings();
|
||||
},
|
||||
style: 'default',
|
||||
},
|
||||
{ text: loc._.cancel, onPress: () => {}, style: 'cancel' },
|
||||
]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -421,7 +421,7 @@ const WalletTransactions = () => {
|
|||
fromSecret: wallet.current.getSecret(),
|
||||
// ScanLndInvoice actrually uses `fromSecret` so keeping it for now
|
||||
uri: ret.data ? ret.data : ret,
|
||||
fromWallet: wallet,
|
||||
fromWallet: wallet.current,
|
||||
};
|
||||
if (wallet.current.chain === Chain.ONCHAIN) {
|
||||
navigate('SendDetailsRoot', { screen: 'SendDetails', params });
|
||||
|
|
|
@ -471,59 +471,6 @@ describe('BlueWallet UI Tests', () => {
|
|||
process.env.TRAVIS && require('fs').writeFileSync(lockFile, '1');
|
||||
});
|
||||
|
||||
it('can import zpub as watch-only and create PSBT, and scan txhex back', async () => {
|
||||
const lockFile = '/tmp/travislock.' + hashIt(jasmine.currentTest.fullName);
|
||||
if (process.env.TRAVIS) {
|
||||
if (require('fs').existsSync(lockFile))
|
||||
return console.warn('skipping', JSON.stringify(jasmine.currentTest.fullName), 'as it previously passed on Travis');
|
||||
}
|
||||
await helperImportWallet(
|
||||
'zpub6r7jhKKm7BAVx3b3nSnuadY1WnshZYkhK8gKFoRLwK9rF3Mzv28BrGcCGA3ugGtawi1WLb2vyjQAX9ZTDGU5gNk2bLdTc3iEXr6tzR1ipNP',
|
||||
'Imported Watch-only',
|
||||
'0.002 BTC',
|
||||
);
|
||||
|
||||
await element(by.id('SendButton')).tap();
|
||||
await element(by.text('OK')).tap();
|
||||
|
||||
await element(by.id('AddressInput')).replaceText('bc1q063ctu6jhe5k4v8ka99qac8rcm2tzjjnuktyrl');
|
||||
await element(by.id('BitcoinAmountInput')).typeText('0.0005\n');
|
||||
|
||||
// setting fee rate:
|
||||
const feeRate = 1;
|
||||
await element(by.id('chooseFee')).tap();
|
||||
await element(by.id('feeCustom')).tap();
|
||||
await element(by.type('android.widget.EditText')).typeText(feeRate + '');
|
||||
await element(by.text('OK')).tap();
|
||||
|
||||
if (process.env.TRAVIS) await sleep(5000);
|
||||
try {
|
||||
await element(by.id('CreateTransactionButton')).tap();
|
||||
} catch (_) {}
|
||||
|
||||
await yo('TextHelperForPSBT');
|
||||
|
||||
// now lets test scanning back QR with txhex. this should lead straight to broadcast dialog
|
||||
|
||||
await element(by.id('PsbtWithHardwareScrollView')).swipe('up', 'fast', 1); // in case emu screen is small and it doesnt fit
|
||||
await element(by.id('PsbtTxScanButton')).tap(); // opening camera
|
||||
|
||||
// tapping 10 times invisible button is a backdoor:
|
||||
for (let c = 0; c <= 5; c++) {
|
||||
await element(by.id('ScanQrBackdoorButton')).tap();
|
||||
await sleep(1000);
|
||||
}
|
||||
|
||||
const randomTxHex =
|
||||
'020000000001011628f58e8e81bfcfff1b106bb8968e342fb86f09aa810ed2939e43d5127c51040200000000000000000227e42d000000000017a914c679a827d57a9b8b539515dbafb4e573d2bcc6ca87df15cf02000000002200209705cdfcbc459a220e7f39ffe547a31335505c2357f452ae12a22b9ae36ea59d04004730440220626c5205a6f49d1dd1577c85c0af4c5fc70f41de61f891d71a5cf57af09110d4022045bcb1e7d4e93e1a9baf6ae1ad0b4087c9e9f73ec366e97576912377d9f6904301473044022044aea98e8983f09cb0639f08d34526bb7e3ed47d208b7bf714fb29a1b5f9535a02200baa510b94cf434775b4aa2184682f2fb33f15e5e76f79aa0885e7ee12bdc8f70169522102e67ce679d617d674d68eea95ecb166c67b4b5520105c4745adf37ce8a40b92dc21029ff54b8bf26dbddd7bd4336593d2ff17519d5374989f36a6f5f8239675ff79a421039000ee2853c6db4bd956e80b1ecfb8711bf3e0a9a8886d15450c29458b60473153ae00000000';
|
||||
await element(by.id('scanQrBackdoorInput')).replaceText(randomTxHex);
|
||||
await element(by.id('scanQrBackdoorOkButton')).tap();
|
||||
await expect(element(by.id('ScanQrBackdoorButton'))).toBeNotVisible();
|
||||
await yo('PsbtWithHardwareWalletBroadcastTransactionButton');
|
||||
|
||||
process.env.TRAVIS && require('fs').writeFileSync(lockFile, '1');
|
||||
});
|
||||
|
||||
/**
|
||||
* test plan:
|
||||
* 1. import wallet
|
||||
|
|
Loading…
Add table
Reference in a new issue