BlueWallet/screen/transactions/RBF.js

185 lines
5.1 KiB
JavaScript
Raw Normal View History

2018-01-30 22:42:38 +00:00
import React, { Component } from 'react';
2018-03-18 02:48:23 +00:00
import { ActivityIndicator, View } from 'react-native';
2018-10-31 20:14:28 +00:00
import {
BlueSpacing20,
BlueButton,
SafeBlueArea,
BlueCard,
BlueText,
BlueFormInput,
BlueSpacing,
BlueNavigationStyle,
} from '../../BlueComponents';
2018-03-18 02:48:23 +00:00
import PropTypes from 'prop-types';
2019-01-05 20:23:51 +00:00
import { SegwitBech32Wallet } from '../../class';
2018-03-18 02:48:23 +00:00
/** @type {AppStorage} */
let BlueApp = require('../../BlueApp');
2018-01-30 22:42:38 +00:00
export default class RBF extends Component {
2018-10-31 20:14:28 +00:00
static navigationOptions = () => ({
...BlueNavigationStyle(null, false),
title: 'RBF',
});
2018-01-30 22:42:38 +00:00
constructor(props) {
super(props);
2018-03-17 22:39:21 +02:00
let txid;
2018-07-07 14:04:32 +01:00
if (props.navigation.state.params) txid = props.navigation.state.params.txid;
2018-01-30 22:42:38 +00:00
2018-03-17 22:39:21 +02:00
let sourceWallet;
let sourceTx;
2018-01-30 22:42:38 +00:00
for (let w of BlueApp.getWallets()) {
for (let t of w.getTransactions()) {
if (t.hash === txid) {
// found our source wallet
2018-03-17 22:39:21 +02:00
sourceWallet = w;
sourceTx = t;
console.log(t);
2018-01-30 22:42:38 +00:00
}
}
}
2018-03-17 22:39:21 +02:00
let destinationAddress;
2019-01-05 20:23:51 +00:00
2018-01-30 22:42:38 +00:00
for (let o of sourceTx.outputs) {
2019-01-05 20:23:51 +00:00
if (!o.addresses && o.script) {
// probably bech32 output, so we need to decode address
o.addresses = [SegwitBech32Wallet.scriptPubKeyToAddress(o.script)];
}
if (o.addresses && o.addresses[0] === sourceWallet.getAddress()) {
2018-03-17 22:39:21 +02:00
// change
2018-01-30 22:42:38 +00:00
// nop
2018-03-17 22:39:21 +02:00
} else {
// DESTINATION address
2019-01-05 20:23:51 +00:00
destinationAddress = (o.addresses && o.addresses[0]) || '';
2018-03-17 22:39:21 +02:00
console.log('dest = ', destinationAddress);
2018-01-30 22:42:38 +00:00
}
}
if (!destinationAddress || sourceWallet.type === 'legacy') {
// for now I'm too lazy to add RBF support for legacy addresses
2018-01-30 22:42:38 +00:00
this.state = {
isLoading: false,
nonReplaceable: true,
2018-03-17 22:39:21 +02:00
};
return;
2018-01-30 22:42:38 +00:00
}
this.state = {
isLoading: true,
txid,
sourceTx,
sourceWallet,
2018-03-17 22:39:21 +02:00
newDestinationAddress: destinationAddress,
feeDelta: '',
};
2018-01-30 22:42:38 +00:00
}
async componentDidMount() {
2018-03-17 22:39:21 +02:00
let startTime = Date.now();
console.log('transactions/RBF - componentDidMount');
2018-01-30 22:42:38 +00:00
this.setState({
isLoading: false,
2018-03-17 22:39:21 +02:00
});
let endTime = Date.now();
console.log('componentDidMount took', (endTime - startTime) / 1000, 'sec');
2018-01-30 22:42:38 +00:00
}
createTransaction() {
this.props.navigation.navigate('CreateRBF', {
feeDelta: this.state.feeDelta,
newDestinationAddress: this.state.newDestinationAddress,
txid: this.state.txid,
sourceTx: this.state.sourceTx,
sourceWallet: this.state.sourceWallet,
2018-03-17 22:39:21 +02:00
});
2018-01-30 22:42:38 +00:00
}
render() {
if (this.state.isLoading) {
return (
2018-03-17 22:39:21 +02:00
<View style={{ flex: 1, paddingTop: 20 }}>
2018-01-30 22:42:38 +00:00
<ActivityIndicator />
</View>
);
}
if (this.state.nonReplaceable) {
return (
2018-03-17 22:39:21 +02:00
<SafeBlueArea style={{ flex: 1, paddingTop: 20 }}>
<BlueSpacing20 />
<BlueSpacing20 />
<BlueSpacing20 />
<BlueSpacing20 />
<BlueSpacing20 />
2018-01-30 22:42:38 +00:00
<BlueText h4>This transaction is not replaceable</BlueText>
2018-07-07 14:04:32 +01:00
<BlueButton onPress={() => this.props.navigation.goBack()} title="Back" />
2018-01-30 22:42:38 +00:00
</SafeBlueArea>
);
}
if (!this.state.sourceWallet.getAddress) {
return (
2018-03-17 22:39:21 +02:00
<SafeBlueArea style={{ flex: 1, paddingTop: 20 }}>
2018-07-07 14:04:32 +01:00
<BlueText>System error: Source wallet not found (this should never happen)</BlueText>
<BlueButton onPress={() => this.props.navigation.goBack()} title="Back" />
2018-01-30 22:42:38 +00:00
</SafeBlueArea>
);
}
return (
2018-03-17 22:39:21 +02:00
<SafeBlueArea style={{ flex: 1, paddingTop: 20 }}>
<BlueSpacing />
2018-07-07 14:04:32 +01:00
<BlueCard title={'Replace By Fee'} style={{ alignItems: 'center', flex: 1 }}>
<BlueText>RBF allows you to increase fee on already sent but not confirmed transaction, thus speeding up mining</BlueText>
2018-03-17 22:39:21 +02:00
<BlueSpacing20 />
<BlueText>
From wallet '{this.state.sourceWallet.getLabel()}' ({this.state.sourceWallet.getAddress()})
</BlueText>
<BlueSpacing20 />
2018-01-30 22:42:38 +00:00
<BlueFormInput
2018-07-07 14:04:32 +01:00
onChangeText={text => this.setState({ newDestinationAddress: text })}
2018-03-17 22:39:21 +02:00
placeholder={'receiver address here'}
value={this.state.newDestinationAddress}
2018-01-30 22:42:38 +00:00
/>
2018-03-17 22:39:21 +02:00
<BlueFormInput
onChangeText={text => this.setState({ feeDelta: text })}
keyboardType={'numeric'}
placeholder={'fee to add (in BTC)'}
value={this.state.feeDelta + ''}
2018-01-30 22:42:38 +00:00
/>
</BlueCard>
2018-03-17 22:39:21 +02:00
<View style={{ flex: 1, flexDirection: 'row', paddingTop: 20 }}>
<View style={{ flex: 0.33 }}>
2018-07-07 14:04:32 +01:00
<BlueButton onPress={() => this.props.navigation.goBack()} title="Cancel" />
2018-01-30 22:42:38 +00:00
</View>
2018-03-17 22:39:21 +02:00
<View style={{ flex: 0.33 }} />
<View style={{ flex: 0.33 }}>
2018-07-07 14:04:32 +01:00
<BlueButton onPress={() => this.createTransaction()} title="Create" />
2018-01-30 22:42:38 +00:00
</View>
</View>
</SafeBlueArea>
);
}
}
2018-03-18 02:48:23 +00:00
RBF.propTypes = {
navigation: PropTypes.shape({
goBack: PropTypes.function,
navigate: PropTypes.func,
state: PropTypes.shape({
params: PropTypes.shape({
txid: PropTypes.string,
}),
}),
}),
};