From 5b1515ee3fe855fd9c9af16000d2048ab1c1a205 Mon Sep 17 00:00:00 2001 From: Marcos Rodriguez Date: Wed, 11 Dec 2019 21:54:15 -0500 Subject: [PATCH 1/9] FIX: Dismiss modal after success import Update scanQrWif.js --- screen/wallets/scanQrWif.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/screen/wallets/scanQrWif.js b/screen/wallets/scanQrWif.js index 2b99629b..1f85996b 100644 --- a/screen/wallets/scanQrWif.js +++ b/screen/wallets/scanQrWif.js @@ -90,9 +90,9 @@ export default class ScanQrWif extends React.Component { BlueApp.wallets.push(hd); await BlueApp.saveToDisk(); alert(loc.wallets.import.success); - this.props.navigation.popToTop(); setTimeout(() => EV(EV.enum.WALLETS_COUNT_CHANGED), 500); this.setState({ isLoading: false }); + this.props.navigation.dismiss(); return; } } @@ -117,9 +117,9 @@ export default class ScanQrWif extends React.Component { BlueApp.wallets.push(hd); await BlueApp.saveToDisk(); alert(loc.wallets.import.success); - this.props.navigation.popToTop(); setTimeout(() => EV(EV.enum.WALLETS_COUNT_CHANGED), 500); this.setState({ isLoading: false }); + this.props.navigation.dismiss(); return; } } @@ -144,9 +144,9 @@ export default class ScanQrWif extends React.Component { await hd.fetchTransactions(); await BlueApp.saveToDisk(); alert(loc.wallets.import.success); - this.props.navigation.popToTop(); setTimeout(() => EV(EV.enum.WALLETS_COUNT_CHANGED), 500); this.setState({ isLoading: false }); + this.props.navigation.dismiss(); return; } // nope @@ -179,11 +179,11 @@ export default class ScanQrWif extends React.Component { BlueApp.wallets.push(lnd); lnd.setLabel(loc.wallets.import.imported + ' ' + lnd.typeReadable); - this.props.navigation.popToTop(); alert(loc.wallets.import.success); await BlueApp.saveToDisk(); setTimeout(() => EV(EV.enum.WALLETS_COUNT_CHANGED), 500); this.setState({ isLoading: false }); + this.props.navigation.dismiss(); return; } // nope @@ -208,9 +208,9 @@ export default class ScanQrWif extends React.Component { await watchOnly.fetchBalance(); await watchOnly.fetchTransactions(); await BlueApp.saveToDisk(); - this.props.navigation.popToTop(); setTimeout(() => EV(EV.enum.WALLETS_COUNT_CHANGED), 500); this.setState({ isLoading: false }); + this.props.navigation.dismiss(); return; } // nope @@ -235,8 +235,8 @@ export default class ScanQrWif extends React.Component { await newLegacyWallet.fetchBalance(); await newLegacyWallet.fetchTransactions(); await BlueApp.saveToDisk(); - this.props.navigation.popToTop(); setTimeout(() => EV(EV.enum.WALLETS_COUNT_CHANGED), 500); + this.props.navigation.dismiss(); return; } @@ -257,7 +257,7 @@ export default class ScanQrWif extends React.Component { alert(loc.wallets.scanQrWif.imported_wif + ret.data + loc.wallets.scanQrWif.with_address + newWallet.getAddress()); } await BlueApp.saveToDisk(); - this.props.navigation.popToTop(); + this.props.navigation.dismiss(); setTimeout(() => EV(EV.enum.WALLETS_COUNT_CHANGED), 500); }; // end @@ -337,8 +337,8 @@ export default class ScanQrWif extends React.Component { ScanQrWif.propTypes = { navigation: PropTypes.shape({ + dismiss: PropTypes.func, goBack: PropTypes.func, - popToTop: PropTypes.func, navigate: PropTypes.func, }), }; From 748ec94bb4542510a7191061533e017e2012d30d Mon Sep 17 00:00:00 2001 From: Marcos Rodriguez Date: Wed, 11 Dec 2019 22:17:09 -0500 Subject: [PATCH 2/9] FIX: Hide loading indicator after push --- screen/send/details.js | 63 +++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/screen/send/details.js b/screen/send/details.js index 65f70c97..9c04a5fd 100644 --- a/screen/send/details.js +++ b/screen/send/details.js @@ -495,22 +495,20 @@ export default class SendDetails extends Component { this.setState({ isLoading: false }); return; } - - this.setState({ isLoading: false }, () => - this.props.navigation.navigate('Confirm', { - recipients: [firstTransaction], - // HD wallet's utxo is in sats, classic segwit wallet utxos are in btc - fee: this.calculateFee( - utxo, - tx, - this.state.fromWallet.type === HDSegwitP2SHWallet.type || this.state.fromWallet.type === HDLegacyP2PKHWallet.type, - ), - memo: this.state.memo, - fromWallet: this.state.fromWallet, - tx: tx, - satoshiPerByte: actualSatoshiPerByte.toFixed(2), - }), - ); + this.props.navigation.navigate('Confirm', { + recipients: [firstTransaction], + // HD wallet's utxo is in sats, classic segwit wallet utxos are in btc + fee: this.calculateFee( + utxo, + tx, + this.state.fromWallet.type === HDSegwitP2SHWallet.type || this.state.fromWallet.type === HDLegacyP2PKHWallet.type, + ), + memo: this.state.memo, + fromWallet: this.state.fromWallet, + tx: tx, + satoshiPerByte: actualSatoshiPerByte.toFixed(2), + }); + this.setState({ isLoading: false }); }); } @@ -543,14 +541,12 @@ export default class SendDetails extends Component { // 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 - - this.setState({ isLoading: false }, () => - this.props.navigation.navigate('PsbtWithHardwareWallet', { - memo: this.state.memo, - fromWallet: wallet, - psbt, - }), - ); + this.props.navigation.navigate('PsbtWithHardwareWallet', { + memo: this.state.memo, + fromWallet: wallet, + psbt, + }); + this.setState({ isLoading: false }); return; } @@ -560,16 +556,15 @@ export default class SendDetails extends Component { memo: this.state.memo, }; await BlueApp.saveToDisk(); - this.setState({ isLoading: false }, () => - this.props.navigation.navigate('Confirm', { - fee: new BigNumber(fee).dividedBy(100000000).toNumber(), - memo: this.state.memo, - fromWallet: wallet, - tx: tx.toHex(), - recipients: targets, - satoshiPerByte: requestedSatPerByte, - }), - ); + this.props.navigation.navigate('Confirm', { + fee: new BigNumber(fee).dividedBy(100000000).toNumber(), + memo: this.state.memo, + fromWallet: wallet, + tx: tx.toHex(), + recipients: targets, + satoshiPerByte: requestedSatPerByte, + }); + this.setState({ isLoading: false }); } onWalletSelect = wallet => { From ee603d1eaf67c6a840d86e197dc822d014fb83e1 Mon Sep 17 00:00:00 2001 From: Marcos Rodriguez Date: Wed, 11 Dec 2019 22:57:17 -0500 Subject: [PATCH 3/9] FIX: Single android instance. --- android/app/src/main/AndroidManifest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index a73ac221..da76e9d4 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -16,6 +16,7 @@ From 0bd7c8e97949a99be9db7bc9a6058347410f3801 Mon Sep 17 00:00:00 2001 From: Marcos Rodriguez Date: Wed, 11 Dec 2019 23:23:19 -0500 Subject: [PATCH 4/9] FIX: Dont show clipboard modal when biometrics is dismissed. --- App.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/App.js b/App.js index aa5f3435..6ad2cfb1 100644 --- a/App.js +++ b/App.js @@ -38,7 +38,7 @@ export default class App extends React.Component { clipboardContent: '', }; - async componentDidMount() { + componentDidMount() { Linking.addEventListener('url', this.handleOpenURL); AppState.addEventListener('change', this._handleAppStateChange); QuickActions.popInitialAction().then(this.popInitialAction); @@ -110,7 +110,7 @@ export default class App extends React.Component { _handleAppStateChange = async nextAppState => { if (BlueApp.getWallets().length > 0) { - if (this.state.appState.match(/inactive|background/) && nextAppState === 'active') { + if (this.state.appState.match(/background/) && nextAppState === 'active') { setTimeout(() => A(A.ENUM.APP_UNSUSPENDED), 2000); const clipboard = await Clipboard.getString(); const isAddressFromStoredWallet = BlueApp.getWallets().some(wallet => From 001b814da116240206152f64c3e952543c0e7505 Mon Sep 17 00:00:00 2001 From: Marcos Rodriguez Date: Wed, 11 Dec 2019 23:24:06 -0500 Subject: [PATCH 5/9] FIX: Ignore supported in quick actions and only listen to error. Resolves quick actions not appearing on non-3d touch devices. --- class/quickActions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/class/quickActions.js b/class/quickActions.js index 8a9abe0c..c520c011 100644 --- a/class/quickActions.js +++ b/class/quickActions.js @@ -17,8 +17,8 @@ export default class DeviceQuickActions { if (DeviceQuickActions.shared.wallets === undefined) { return; } - QuickActions.isSupported((error, supported) => { - if (supported && error === null) { + QuickActions.isSupported((error, _supported) => { + if (error === null) { let shortcutItems = []; const loc = require('../loc/'); for (const wallet of DeviceQuickActions.shared.wallets) { From 9dd9fb6b975e2628d746d0880d52452b37fb80f3 Mon Sep 17 00:00:00 2001 From: Marcos Rodriguez Date: Wed, 11 Dec 2019 23:34:04 -0500 Subject: [PATCH 6/9] FIX: Fixed WatchConnectivity undefined array log issue --- WatchConnectivity.ios.js | 16 +++++++++------- class/app-storage.js | 2 +- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/WatchConnectivity.ios.js b/WatchConnectivity.ios.js index 5efe3581..8b35efda 100644 --- a/WatchConnectivity.ios.js +++ b/WatchConnectivity.ios.js @@ -32,7 +32,7 @@ export default class WatchConnectivity { ); reply({ invoicePaymentRequest: createInvoiceRequest }); } else if (message.message === 'sendApplicationContext') { - await WatchConnectivity.shared.sendWalletsToWatch(WatchConnectivity.shared.wallets); + await WatchConnectivity.shared.sendWalletsToWatch(); } else if (message.message === 'fetchTransactions') { await WatchConnectivity.shared.fetchTransactionsFunction(); } @@ -56,14 +56,16 @@ export default class WatchConnectivity { } } - async sendWalletsToWatch(allWallets) { - if (allWallets === undefined && WatchConnectivity.shared.wallets !== undefined) { - allWallets = WatchConnectivity.shared.wallets; - } - if (allWallets && allWallets.length === 0) { + async sendWalletsToWatch() { + const allWallets = WatchConnectivity.shared.wallets; + if (!Array.isArray(allWallets)) { + console.log('No Wallets set to sync with Watch app. Exiting...'); + return; + } else if (allWallets.length === 0) { + console.log('Wallets array is set. No Wallets set to sync with Watch app. Exiting...'); return; } - + console.log('Wallets set to sync with Watch app. Continuing...'); return InteractionManager.runAfterInteractions(async () => { if (WatchConnectivity.shared.isAppInstalled) { let wallets = []; diff --git a/class/app-storage.js b/class/app-storage.js index 5b449ca9..bdba64a1 100644 --- a/class/app-storage.js +++ b/class/app-storage.js @@ -253,7 +253,7 @@ export class AppStorage { await this.fetchWalletTransactions(); await this.saveToDisk(); }; - await WatchConnectivity.shared.sendWalletsToWatch(this.wallets); + await WatchConnectivity.shared.sendWalletsToWatch(); DeviceQuickActions.setWallets(this.wallets); DeviceQuickActions.setQuickActions(); return true; From d60323961bbbb4094766234d0b2e6cd6f2aaba9d Mon Sep 17 00:00:00 2001 From: Marcos Rodriguez Date: Tue, 10 Dec 2019 23:13:40 -0500 Subject: [PATCH 7/9] ADD: Toggle for RBF Update hd-segwit-bech32-wallet.js Update details.js Update details.js --- class/hd-segwit-bech32-wallet.js | 6 +++++- screen/send/details.js | 22 +++++++++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/class/hd-segwit-bech32-wallet.js b/class/hd-segwit-bech32-wallet.js index 1dc0b894..cfbe55bf 100644 --- a/class/hd-segwit-bech32-wallet.js +++ b/class/hd-segwit-bech32-wallet.js @@ -727,7 +727,11 @@ export class HDSegwitBech32Wallet extends AbstractHDWallet { */ createTransaction(utxos, targets, feeRate, changeAddress, sequence, skipSigning = false) { if (!changeAddress) throw new Error('No change address provided'); - sequence = sequence || HDSegwitBech32Wallet.defaultRBFSequence; + if (sequence === false) { + sequence = undefined; + } else { + sequence = sequence || HDSegwitBech32Wallet.defaultRBFSequence; + } let algo = coinSelectAccumulative; if (targets.length === 1 && targets[0] && !targets[0].value) { diff --git a/screen/send/details.js b/screen/send/details.js index 9c04a5fd..31e2f68d 100644 --- a/screen/send/details.js +++ b/screen/send/details.js @@ -84,6 +84,7 @@ export default class SendDetails extends Component { showSendMax: false, isFeeSelectionModalVisible: false, isAdvancedTransactionOptionsVisible: false, + isTransactionReplaceable: fromWallet.type === HDSegwitBech32Wallet.type, recipientsScrollIndex: 0, fromAddress, fromWallet, @@ -535,7 +536,13 @@ export default class SendDetails extends Component { targets = [{ address: firstTransaction.address, amount: BitcoinUnit.MAX }]; } - let { tx, fee, psbt } = wallet.createTransaction(wallet.getUtxo(), targets, requestedSatPerByte, changeAddress); + let { tx, fee, psbt } = wallet.createTransaction( + wallet.getUtxo(), + targets, + requestedSatPerByte, + changeAddress, + this.state.isTransactionReplaceable === true ? HDSegwitBech32Wallet.defaultRBFSequence : false, + ); if (wallet.type === WatchOnlyWallet.type) { // watch-only wallets with enabled HW wallet support have different flow. we have to show PSBT to user as QR code @@ -720,6 +727,15 @@ export default class SendDetails extends Component { onPress={this.onUseAllPressed} /> )} + {this.state.fromWallet.type === HDSegwitBech32Wallet.type && ( + + )} {this.state.fromWallet.allowBatchSend() && ( <> { + this.setState({ isTransactionReplaceable: value }); + }; + renderCreateButton = () => { return ( From cdd760f6fa4b1cd9736f5b243f5a32d90d552931 Mon Sep 17 00:00:00 2001 From: Overtorment Date: Fri, 13 Dec 2019 01:05:38 +0000 Subject: [PATCH 8/9] REF: added constant --- class/hd-segwit-bech32-wallet.js | 7 ++----- screen/send/details.js | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/class/hd-segwit-bech32-wallet.js b/class/hd-segwit-bech32-wallet.js index cfbe55bf..00b3eb2d 100644 --- a/class/hd-segwit-bech32-wallet.js +++ b/class/hd-segwit-bech32-wallet.js @@ -20,6 +20,7 @@ export class HDSegwitBech32Wallet extends AbstractHDWallet { static type = 'HDsegwitBech32'; static typeReadable = 'HD SegWit (BIP84 Bech32 Native)'; static defaultRBFSequence = 2147483648; // 1 << 31, minimum for replaceable transactions as per BIP68 + static finalRBFSequence = 4294967295; // 0xFFFFFFFF constructor() { super(); @@ -727,11 +728,7 @@ export class HDSegwitBech32Wallet extends AbstractHDWallet { */ createTransaction(utxos, targets, feeRate, changeAddress, sequence, skipSigning = false) { if (!changeAddress) throw new Error('No change address provided'); - if (sequence === false) { - sequence = undefined; - } else { - sequence = sequence || HDSegwitBech32Wallet.defaultRBFSequence; - } + sequence = sequence || HDSegwitBech32Wallet.defaultRBFSequence; let algo = coinSelectAccumulative; if (targets.length === 1 && targets[0] && !targets[0].value) { diff --git a/screen/send/details.js b/screen/send/details.js index 31e2f68d..6f94ae17 100644 --- a/screen/send/details.js +++ b/screen/send/details.js @@ -541,7 +541,7 @@ export default class SendDetails extends Component { targets, requestedSatPerByte, changeAddress, - this.state.isTransactionReplaceable === true ? HDSegwitBech32Wallet.defaultRBFSequence : false, + this.state.isTransactionReplaceable ? HDSegwitBech32Wallet.defaultRBFSequence : HDSegwitBech32Wallet.finalRBFSequence, ); if (wallet.type === WatchOnlyWallet.type) { From fc3bb6f2d2b1d3e4a178bfe6b5d7c43836d61a2a Mon Sep 17 00:00:00 2001 From: Marcos Rodriguez Date: Fri, 13 Dec 2019 00:28:01 -0500 Subject: [PATCH 9/9] FIX: Scan to receive is more visible Update lndCreateInvoice.js --- screen/lnd/lndCreateInvoice.js | 42 +++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/screen/lnd/lndCreateInvoice.js b/screen/lnd/lndCreateInvoice.js index 5ae3a5e6..65415be1 100644 --- a/screen/lnd/lndCreateInvoice.js +++ b/screen/lnd/lndCreateInvoice.js @@ -1,7 +1,6 @@ /* global alert */ import React, { Component } from 'react'; import { - Dimensions, ActivityIndicator, View, TextInput, @@ -18,10 +17,10 @@ import bech32 from 'bech32'; import { BitcoinUnit } from '../../models/bitcoinUnits'; import NavigationService from '../../NavigationService'; import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; +import { Icon } from 'react-native-elements'; let BlueApp = require('../../BlueApp'); let EV = require('../../events'); let loc = require('../../loc'); -const { width } = Dimensions.get('window'); export default class LNDCreateInvoice extends Component { static navigationOptions = ({ navigation }) => ({ @@ -167,20 +166,27 @@ export default class LNDCreateInvoice extends Component { renderScanClickable = () => { return ( - - NavigationService.navigate('ScanQrAddress', { onBarScanned: this.processLnurl })} - style={{ - flex: 1, - flexDirection: 'row', - minWidth: width, - justifyContent: 'center', - alignItems: 'center', - }} - > - {loc.receive.scan_lnurl} - - + { + NavigationService.navigate('ScanQrAddress', { onBarScanned: this.processLnurl }); + Keyboard.dismiss(); + }} + style={{ + height: 36, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + backgroundColor: '#9AA0AA', + borderRadius: 4, + paddingVertical: 4, + paddingHorizontal: 8, + marginHorizontal: 4, + }} + > + + {loc.send.details.scan} + ); }; @@ -245,12 +251,12 @@ export default class LNDCreateInvoice extends Component { onSubmitEditing={Keyboard.dismiss} inputAccessoryViewID={BlueDismissKeyboardInputAccessory.InputAccessoryViewID} /> + {this.state.lnurlParams ? null : this.renderScanClickable()} {this.renderCreateButton()} - {this.state.lnurlParams ? null : this.renderScanClickable()} ); @@ -265,7 +271,7 @@ LNDCreateInvoice.propTypes = { state: PropTypes.shape({ params: PropTypes.shape({ uri: PropTypes.string, - fromWallet: PropTypes.string, + fromWallet: PropTypes.shape({}), }), }), }),