mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2024-11-19 18:00:17 +01:00
Merge pull request #1949 from BlueWallet/fix-freeze-send-screen
FIX: rare freezes on send screen (closes #1945)
This commit is contained in:
commit
9fc605893d
@ -177,18 +177,8 @@ const SendDetailsRoot = () => (
|
||||
component={PsbtWithHardwareWallet}
|
||||
options={PsbtWithHardwareWallet.navigationOptions}
|
||||
/>
|
||||
<SendDetailsStack.Screen name="CreateTransaction" component={SendCreate} options={SendCreate.navigationOptions} />
|
||||
<SendDetailsStack.Screen name="PsbtMultisig" component={PsbtMultisig} options={PsbtMultisig.navigationOptions} />
|
||||
<SendDetailsStack.Screen
|
||||
name="CreateTransaction"
|
||||
component={SendCreate}
|
||||
options={{
|
||||
headerStyle: {
|
||||
backgroundColor: '#FFFFFF',
|
||||
borderBottomWidth: 0,
|
||||
},
|
||||
headerTintColor: '#0c2550',
|
||||
}}
|
||||
/>
|
||||
<SendDetailsStack.Screen name="Success" component={Success} options={Success.navigationOptions} />
|
||||
<SendDetailsStack.Screen name="SelectWallet" component={SelectWallet} options={SelectWallet.navigationOptions} />
|
||||
</SendDetailsStack.Navigator>
|
||||
|
@ -680,8 +680,9 @@ export class AbstractHDElectrumWallet extends AbstractHDWallet {
|
||||
|
||||
addressess = [...new Set(addressess)]; // deduplicate just for any case
|
||||
|
||||
const fetchedUtxo = await BlueElectrum.multiGetUtxoByAddress(addressess);
|
||||
this._utxo = [];
|
||||
for (const arr of Object.values(await BlueElectrum.multiGetUtxoByAddress(addressess))) {
|
||||
for (const arr of Object.values(fetchedUtxo)) {
|
||||
this._utxo = this._utxo.concat(arr);
|
||||
}
|
||||
|
||||
@ -739,8 +740,6 @@ export class AbstractHDElectrumWallet extends AbstractHDWallet {
|
||||
}
|
||||
if (ownedAddressesHashmap[address]) {
|
||||
const value = new BigNumber(output.value).multipliedBy(100000000).toNumber();
|
||||
const wif = returnSpentUtxoAsWell ? false : this._getWifForAddress(address);
|
||||
// ^^^ faster, as we probably dont need WIFs for spent UTXO
|
||||
utxos.push({
|
||||
txid: tx.txid,
|
||||
txId: tx.txid,
|
||||
@ -749,7 +748,7 @@ export class AbstractHDElectrumWallet extends AbstractHDWallet {
|
||||
value,
|
||||
amount: value,
|
||||
confirmations: tx.confirmations,
|
||||
wif,
|
||||
wif: false,
|
||||
height: BlueElectrum.estimateCurrentBlockheight() - tx.confirmations,
|
||||
});
|
||||
}
|
||||
@ -769,7 +768,11 @@ export class AbstractHDElectrumWallet extends AbstractHDWallet {
|
||||
}
|
||||
}
|
||||
|
||||
if (!spent) ret.push(utxo);
|
||||
if (!spent) {
|
||||
// filling WIFs only for legit unspent UTXO, as it is a slow operation
|
||||
utxo.wif = this._getWifForAddress(utxo.address);
|
||||
ret.push(utxo);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -26,6 +26,10 @@ export class AbstractHDWallet extends LegacyWallet {
|
||||
return this.next_free_address_index;
|
||||
}
|
||||
|
||||
getNextFreeChangeAddressIndex() {
|
||||
return this.next_free_change_address_index;
|
||||
}
|
||||
|
||||
prepareForSerialization() {
|
||||
// deleting structures that cant be serialized
|
||||
delete this._node0;
|
||||
@ -93,7 +97,7 @@ export class AbstractHDWallet extends LegacyWallet {
|
||||
if (!freeAddress) {
|
||||
// could not find in cycle above, give up
|
||||
freeAddress = this._getExternalAddressByIndex(this.next_free_address_index + c); // we didnt check this one, maybe its free
|
||||
this.next_free_address_index += c + 1; // now points to the one _after_
|
||||
this.next_free_address_index += c; // now points to this one
|
||||
}
|
||||
this._address = freeAddress;
|
||||
return freeAddress;
|
||||
@ -130,8 +134,8 @@ export class AbstractHDWallet extends LegacyWallet {
|
||||
|
||||
if (!freeAddress) {
|
||||
// could not find in cycle above, give up
|
||||
freeAddress = this._getExternalAddressByIndex(this.next_free_address_index + c); // we didnt check this one, maybe its free
|
||||
this.next_free_address_index += c + 1; // now points to the one _after_
|
||||
freeAddress = this._getInternalAddressByIndex(this.next_free_change_address_index + c); // we didnt check this one, maybe its free
|
||||
this.next_free_change_address_index += c; // now points to this one
|
||||
}
|
||||
this._address = freeAddress;
|
||||
return freeAddress;
|
||||
|
@ -219,6 +219,10 @@ export class AbstractWallet {
|
||||
return new Promise(resolve => resolve(this.getAddress()));
|
||||
}
|
||||
|
||||
async getChangeAddressAsync() {
|
||||
return new Promise(resolve => resolve(this.getAddress()));
|
||||
}
|
||||
|
||||
useWithHardwareWalletEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
@ -401,10 +401,4 @@ export class LegacyWallet extends AbstractWallet {
|
||||
allowSendMax() {
|
||||
return true;
|
||||
}
|
||||
|
||||
async getChangeAddressAsync() {
|
||||
return new Promise(resolve => {
|
||||
resolve(this.getAddress());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -125,11 +125,21 @@ export class WatchOnlyWallet extends LegacyWallet {
|
||||
throw new Error('Not initialized');
|
||||
}
|
||||
|
||||
_getInternalAddressByIndex(index) {
|
||||
if (this._hdWalletInstance) return this._hdWalletInstance._getInternalAddressByIndex(index);
|
||||
throw new Error('Not initialized');
|
||||
}
|
||||
|
||||
getNextFreeAddressIndex() {
|
||||
if (this._hdWalletInstance) return this._hdWalletInstance.next_free_address_index;
|
||||
throw new Error('Not initialized');
|
||||
}
|
||||
|
||||
getNextFreeChangeAddressIndex() {
|
||||
if (this._hdWalletInstance) return this._hdWalletInstance.next_free_change_address_index;
|
||||
throw new Error('Not initialized');
|
||||
}
|
||||
|
||||
async getChangeAddressAsync() {
|
||||
if (this._hdWalletInstance) return this._hdWalletInstance.getChangeAddressAsync();
|
||||
throw new Error('Not initialized');
|
||||
|
@ -20,7 +20,7 @@ export class NetworkTransactionFee {
|
||||
export default class NetworkTransactionFees {
|
||||
static recommendedFees() {
|
||||
// eslint-disable-next-line no-async-promise-executor
|
||||
return new Promise(async (resolve, reject) => {
|
||||
return new Promise(async resolve => {
|
||||
try {
|
||||
const response = await BlueElectrum.estimateFees();
|
||||
if (typeof response === 'object') {
|
||||
@ -28,12 +28,12 @@ export default class NetworkTransactionFees {
|
||||
resolve(networkFee);
|
||||
} else {
|
||||
const networkFee = new NetworkTransactionFee(1, 1, 1);
|
||||
reject(networkFee);
|
||||
resolve(networkFee);
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn(err);
|
||||
const networkFee = new NetworkTransactionFee(1, 1, 1);
|
||||
reject(networkFee);
|
||||
resolve(networkFee);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -253,8 +253,8 @@ SendCreate.navigationOptions = ({ navigation, route }) => {
|
||||
}
|
||||
|
||||
return {
|
||||
...BlueNavigationStyle,
|
||||
title: loc.send.create.details,
|
||||
...BlueNavigationStyle(),
|
||||
title: loc.send.create_details,
|
||||
headerRight,
|
||||
};
|
||||
};
|
||||
|
@ -44,6 +44,7 @@ import DocumentPicker from 'react-native-document-picker';
|
||||
import DeeplinkSchemaMatch from '../../class/deeplink-schema-match';
|
||||
import loc from '../../loc';
|
||||
import { BlueCurrentTheme } from '../../components/themes';
|
||||
import { AbstractHDElectrumWallet } from '../../class/wallets/abstract-hd-electrum-wallet';
|
||||
const currency = require('../../blue_modules/currency');
|
||||
const BlueApp: AppStorage = require('../../BlueApp');
|
||||
const prompt = require('../../blue_modules/prompt');
|
||||
@ -362,10 +363,10 @@ export default class SendDetails extends Component {
|
||||
}
|
||||
} catch (_) {}
|
||||
|
||||
await this.reCalcTx();
|
||||
this.reCalcTx();
|
||||
|
||||
try {
|
||||
const recommendedFees = await NetworkTransactionFees.recommendedFees();
|
||||
const recommendedFees = await Promise.race([NetworkTransactionFees.recommendedFees(), BlueApp.sleep(2000)]);
|
||||
if (recommendedFees && 'fastestFee' in recommendedFees) {
|
||||
await AsyncStorage.setItem(NetworkTransactionFee.StorageKey, JSON.stringify(recommendedFees));
|
||||
this.setState({
|
||||
@ -373,7 +374,7 @@ export default class SendDetails extends Component {
|
||||
networkTransactionFees: recommendedFees,
|
||||
});
|
||||
}
|
||||
} catch (_) {}
|
||||
} catch (_) {} // either sleep expired or recommendedFees threw an exception
|
||||
|
||||
if (this.props.route.params.uri) {
|
||||
try {
|
||||
@ -386,9 +387,15 @@ export default class SendDetails extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
await this.state.fromWallet.fetchUtxo();
|
||||
try {
|
||||
await Promise.race([this.state.fromWallet.fetchUtxo(), BlueApp.sleep(6000)]);
|
||||
} catch (_) {
|
||||
// either sleep expired or fetchUtxo threw an exception
|
||||
}
|
||||
|
||||
this.setState({ isLoading: false });
|
||||
await this.reCalcTx();
|
||||
|
||||
this.reCalcTx();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
@ -467,13 +474,63 @@ export default class SendDetails extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
getChangeAddressFast() {
|
||||
if (this.state.changeAddress) return this.state.changeAddress; // cache
|
||||
|
||||
/** @type {AbstractHDElectrumWallet|WatchOnlyWallet} */
|
||||
const wallet = this.state.fromWallet;
|
||||
let changeAddress;
|
||||
if (WatchOnlyWallet.type === wallet.type && !wallet.isHd()) {
|
||||
// plain watchonly - just get the address
|
||||
changeAddress = wallet.getAddress();
|
||||
} else if (WatchOnlyWallet.type === wallet.type || wallet instanceof AbstractHDElectrumWallet) {
|
||||
changeAddress = wallet._getInternalAddressByIndex(wallet.getNextFreeChangeAddressIndex());
|
||||
} else {
|
||||
// legacy wallets
|
||||
changeAddress = wallet.getAddress();
|
||||
}
|
||||
|
||||
return changeAddress;
|
||||
}
|
||||
|
||||
async getChangeAddressAsync() {
|
||||
if (this.state.changeAddress) return this.state.changeAddress; // cache
|
||||
|
||||
/** @type {AbstractHDElectrumWallet|WatchOnlyWallet} */
|
||||
const wallet = this.state.fromWallet;
|
||||
let changeAddress;
|
||||
if (WatchOnlyWallet.type === wallet.type && !wallet.isHd()) {
|
||||
// plain watchonly - just get the address
|
||||
changeAddress = wallet.getAddress();
|
||||
} else {
|
||||
// otherwise, lets call widely-used getChangeAddressAsync()
|
||||
try {
|
||||
changeAddress = await Promise.race([BlueApp.sleep(2000), wallet.getChangeAddressAsync()]);
|
||||
} catch (_) {}
|
||||
|
||||
if (!changeAddress) {
|
||||
// either sleep expired or getChangeAddressAsync threw an exception
|
||||
if (wallet instanceof AbstractHDElectrumWallet) {
|
||||
changeAddress = wallet._getInternalAddressByIndex(wallet.getNextFreeChangeAddressIndex());
|
||||
} else {
|
||||
// legacy wallets
|
||||
changeAddress = wallet.getAddress();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (changeAddress) this.setState({ changeAddress }); // cache
|
||||
|
||||
return changeAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recalculating fee options by creating skeleton of future tx.
|
||||
*/
|
||||
reCalcTx = async (all = false) => {
|
||||
reCalcTx = (all = false) => {
|
||||
const wallet = this.state.fromWallet;
|
||||
const fees = this.state.networkTransactionFees;
|
||||
const changeAddress = await wallet.getChangeAddressAsync();
|
||||
const changeAddress = this.getChangeAddressFast();
|
||||
const requestedSatPerByte = Number(this.state.fee);
|
||||
const feePrecalc = { ...this.state.feePrecalc };
|
||||
|
||||
@ -547,7 +604,7 @@ export default class SendDetails extends Component {
|
||||
async createPsbtTransaction() {
|
||||
/** @type {HDSegwitBech32Wallet} */
|
||||
const wallet = this.state.fromWallet;
|
||||
const changeAddress = await wallet.getChangeAddressAsync();
|
||||
const changeAddress = await this.getChangeAddressAsync();
|
||||
const requestedSatPerByte = Number(this.state.fee);
|
||||
console.log({ requestedSatPerByte, utxo: wallet.getUtxo() });
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user