mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-02-23 23:27:26 +01:00
Merge pull request #6442 from BlueWallet/txstatus
REF: TransactionStatus to TSX
This commit is contained in:
commit
b11dc8d515
2 changed files with 172 additions and 81 deletions
|
@ -49,7 +49,7 @@ import CPFP from './screen/transactions/CPFP';
|
||||||
import RBFBumpFee from './screen/transactions/RBFBumpFee';
|
import RBFBumpFee from './screen/transactions/RBFBumpFee';
|
||||||
import RBFCancel from './screen/transactions/RBFCancel';
|
import RBFCancel from './screen/transactions/RBFCancel';
|
||||||
import TransactionDetails from './screen/transactions/details';
|
import TransactionDetails from './screen/transactions/details';
|
||||||
import TransactionStatus from './screen/transactions/transactionStatus';
|
import TransactionStatus from './screen/transactions/TransactionStatus';
|
||||||
|
|
||||||
import AztecoRedeem from './screen/receive/aztecoRedeem';
|
import AztecoRedeem from './screen/receive/aztecoRedeem';
|
||||||
import ReceiveDetails from './screen/receive/details';
|
import ReceiveDetails from './screen/receive/details';
|
||||||
|
@ -107,7 +107,21 @@ const WalletsRoot = () => {
|
||||||
<WalletsStack.Screen name="WalletDetails" component={WalletDetails} options={WalletDetails.navigationOptions(theme)} />
|
<WalletsStack.Screen name="WalletDetails" component={WalletDetails} options={WalletDetails.navigationOptions(theme)} />
|
||||||
<WalletsStack.Screen name="LdkViewLogs" component={LdkViewLogs} options={LdkViewLogs.navigationOptions(theme)} />
|
<WalletsStack.Screen name="LdkViewLogs" component={LdkViewLogs} options={LdkViewLogs.navigationOptions(theme)} />
|
||||||
<WalletsStack.Screen name="TransactionDetails" component={TransactionDetails} options={TransactionDetails.navigationOptions(theme)} />
|
<WalletsStack.Screen name="TransactionDetails" component={TransactionDetails} options={TransactionDetails.navigationOptions(theme)} />
|
||||||
<WalletsStack.Screen name="TransactionStatus" component={TransactionStatus} options={TransactionStatus.navigationOptions(theme)} />
|
<WalletsStack.Screen
|
||||||
|
name="TransactionStatus"
|
||||||
|
component={TransactionStatus}
|
||||||
|
initialParams={{
|
||||||
|
hash: undefined,
|
||||||
|
walletID: undefined,
|
||||||
|
}}
|
||||||
|
options={navigationStyle({
|
||||||
|
title: '',
|
||||||
|
statusBarStyle: 'auto',
|
||||||
|
headerStyle: {
|
||||||
|
backgroundColor: theme.colors.customHeader,
|
||||||
|
},
|
||||||
|
})(theme)}
|
||||||
|
/>
|
||||||
<WalletsStack.Screen name="CPFP" component={CPFP} options={CPFP.navigationOptions(theme)} />
|
<WalletsStack.Screen name="CPFP" component={CPFP} options={CPFP.navigationOptions(theme)} />
|
||||||
<WalletsStack.Screen name="RBFBumpFee" component={RBFBumpFee} options={RBFBumpFee.navigationOptions(theme)} />
|
<WalletsStack.Screen name="RBFBumpFee" component={RBFBumpFee} options={RBFBumpFee.navigationOptions(theme)} />
|
||||||
<WalletsStack.Screen name="RBFCancel" component={RBFCancel} options={RBFCancel.navigationOptions(theme)} />
|
<WalletsStack.Screen name="RBFCancel" component={RBFCancel} options={RBFCancel.navigationOptions(theme)} />
|
||||||
|
|
|
@ -1,44 +1,98 @@
|
||||||
import React, { useContext, useEffect, useLayoutEffect, useRef, useState } from 'react';
|
import React, { useEffect, useLayoutEffect, useReducer, useRef } from 'react';
|
||||||
import { View, ActivityIndicator, Text, TouchableOpacity, StyleSheet, BackHandler } from 'react-native';
|
import { View, ActivityIndicator, Text, TouchableOpacity, StyleSheet, BackHandler } from 'react-native';
|
||||||
import { Icon } from 'react-native-elements';
|
import { Icon } from 'react-native-elements';
|
||||||
import { useNavigation, useRoute } from '@react-navigation/native';
|
import { RouteProp, useNavigation, useRoute } from '@react-navigation/native';
|
||||||
|
|
||||||
import { BlueCard, BlueLoading, BlueSpacing10, BlueSpacing20, BlueText } from '../../BlueComponents';
|
import { BlueCard, BlueLoading, BlueSpacing10, BlueSpacing20, BlueText } from '../../BlueComponents';
|
||||||
import TransactionIncomingIcon from '../../components/icons/TransactionIncomingIcon';
|
import TransactionIncomingIcon from '../../components/icons/TransactionIncomingIcon';
|
||||||
import TransactionOutgoingIcon from '../../components/icons/TransactionOutgoingIcon';
|
import TransactionOutgoingIcon from '../../components/icons/TransactionOutgoingIcon';
|
||||||
import TransactionPendingIcon from '../../components/icons/TransactionPendingIcon';
|
import TransactionPendingIcon from '../../components/icons/TransactionPendingIcon';
|
||||||
import navigationStyle from '../../components/navigationStyle';
|
|
||||||
import HandOffComponent from '../../components/HandOffComponent';
|
import HandOffComponent from '../../components/HandOffComponent';
|
||||||
import { HDSegwitBech32Transaction } from '../../class';
|
import { HDSegwitBech32Transaction, HDSegwitBech32Wallet } from '../../class';
|
||||||
import { BitcoinUnit } from '../../models/bitcoinUnits';
|
import { BitcoinUnit } from '../../models/bitcoinUnits';
|
||||||
import loc, { formatBalanceWithoutSuffix } from '../../loc';
|
import loc, { formatBalanceWithoutSuffix } from '../../loc';
|
||||||
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
import { useStorage } from '../../blue_modules/storage-context';
|
||||||
import * as BlueElectrum from '../../blue_modules/BlueElectrum';
|
import * as BlueElectrum from '../../blue_modules/BlueElectrum';
|
||||||
import { useTheme } from '../../components/themes';
|
import { useTheme } from '../../components/themes';
|
||||||
import Button from '../../components/Button';
|
import Button from '../../components/Button';
|
||||||
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
||||||
import SafeArea from '../../components/SafeArea';
|
import SafeArea from '../../components/SafeArea';
|
||||||
|
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
|
||||||
|
import { Transaction } from '../../class/wallets/types';
|
||||||
|
|
||||||
const buttonStatus = Object.freeze({
|
enum ButtonStatus {
|
||||||
possible: 1,
|
Possible,
|
||||||
unknown: 2,
|
Unknown,
|
||||||
notPossible: 3,
|
NotPossible,
|
||||||
});
|
}
|
||||||
|
|
||||||
|
interface TransactionStatusProps {
|
||||||
|
route: RouteProp<{ params: { hash?: string; walletID?: string } }, 'params'>;
|
||||||
|
navigation: NativeStackNavigationProp<any>;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ActionType {
|
||||||
|
SetCPFPPossible,
|
||||||
|
SetRBFBumpFeePossible,
|
||||||
|
SetRBFCancelPossible,
|
||||||
|
SetTransaction,
|
||||||
|
SetLoading,
|
||||||
|
SetEta,
|
||||||
|
SetIntervalMs,
|
||||||
|
SetAllButtonStatus,
|
||||||
|
}
|
||||||
|
|
||||||
|
interface State {
|
||||||
|
isCPFPPossible: ButtonStatus;
|
||||||
|
isRBFBumpFeePossible: ButtonStatus;
|
||||||
|
isRBFCancelPossible: ButtonStatus;
|
||||||
|
tx: any;
|
||||||
|
isLoading: boolean;
|
||||||
|
eta: string;
|
||||||
|
intervalMs: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialState: State = {
|
||||||
|
isCPFPPossible: ButtonStatus.Unknown,
|
||||||
|
isRBFBumpFeePossible: ButtonStatus.Unknown,
|
||||||
|
isRBFCancelPossible: ButtonStatus.Unknown,
|
||||||
|
tx: undefined,
|
||||||
|
isLoading: true,
|
||||||
|
eta: '',
|
||||||
|
intervalMs: 1000,
|
||||||
|
};
|
||||||
|
|
||||||
|
const reducer = (state: State, action: { type: ActionType; payload?: any }): State => {
|
||||||
|
switch (action.type) {
|
||||||
|
case ActionType.SetCPFPPossible:
|
||||||
|
return { ...state, isCPFPPossible: action.payload };
|
||||||
|
case ActionType.SetRBFBumpFeePossible:
|
||||||
|
return { ...state, isRBFBumpFeePossible: action.payload };
|
||||||
|
case ActionType.SetRBFCancelPossible:
|
||||||
|
return { ...state, isRBFCancelPossible: action.payload };
|
||||||
|
case ActionType.SetTransaction:
|
||||||
|
return { ...state, tx: action.payload };
|
||||||
|
case ActionType.SetLoading:
|
||||||
|
return { ...state, isLoading: action.payload };
|
||||||
|
case ActionType.SetEta:
|
||||||
|
return { ...state, eta: action.payload };
|
||||||
|
case ActionType.SetIntervalMs:
|
||||||
|
return { ...state, intervalMs: action.payload };
|
||||||
|
case ActionType.SetAllButtonStatus:
|
||||||
|
return { ...state, isCPFPPossible: action.payload, isRBFBumpFeePossible: action.payload, isRBFCancelPossible: action.payload };
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const TransactionsStatus = () => {
|
const TransactionsStatus = () => {
|
||||||
const { setSelectedWalletID, wallets, txMetadata, fetchAndSaveWalletTransactions } = useContext(BlueStorageContext);
|
const [state, dispatch] = useReducer(reducer, initialState);
|
||||||
const { hash, walletID } = useRoute().params;
|
const { isCPFPPossible, isRBFBumpFeePossible, isRBFCancelPossible, tx, isLoading, eta, intervalMs } = state;
|
||||||
const { navigate, setOptions, goBack } = useNavigation();
|
const { setSelectedWalletID, wallets, txMetadata, fetchAndSaveWalletTransactions } = useStorage();
|
||||||
|
const { hash, walletID } = useRoute<TransactionStatusProps['route']>().params;
|
||||||
|
const { navigate, setOptions, goBack } = useNavigation<TransactionStatusProps['navigation']>();
|
||||||
const { colors } = useTheme();
|
const { colors } = useTheme();
|
||||||
const wallet = useRef(wallets.find(w => w.getID() === walletID));
|
const wallet = useRef(wallets.find(w => w.getID() === walletID));
|
||||||
const [isCPFPPossible, setIsCPFPPossible] = useState();
|
const fetchTxInterval = useRef<NodeJS.Timeout>();
|
||||||
const [isRBFBumpFeePossible, setIsRBFBumpFeePossible] = useState();
|
|
||||||
const [isRBFCancelPossible, setIsRBFCancelPossible] = useState();
|
|
||||||
const [tx, setTX] = useState();
|
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
|
||||||
const fetchTxInterval = useRef();
|
|
||||||
const [intervalMs, setIntervalMs] = useState(1000);
|
|
||||||
const [eta, setEta] = useState('');
|
|
||||||
const stylesHook = StyleSheet.create({
|
const stylesHook = StyleSheet.create({
|
||||||
value: {
|
value: {
|
||||||
color: colors.alternativeTextColor2,
|
color: colors.alternativeTextColor2,
|
||||||
|
@ -57,11 +111,41 @@ const TransactionsStatus = () => {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
// Dispatch Calls
|
||||||
setIsCPFPPossible(buttonStatus.unknown);
|
|
||||||
setIsRBFBumpFeePossible(buttonStatus.unknown);
|
const setTX = (value: any) => {
|
||||||
setIsRBFCancelPossible(buttonStatus.unknown);
|
dispatch({ type: ActionType.SetTransaction, payload: value });
|
||||||
}, []);
|
};
|
||||||
|
|
||||||
|
const setIntervalMs = (ms: number) => {
|
||||||
|
dispatch({ type: ActionType.SetIntervalMs, payload: ms });
|
||||||
|
};
|
||||||
|
|
||||||
|
const setEta = (value: string) => {
|
||||||
|
dispatch({ type: ActionType.SetEta, payload: value });
|
||||||
|
};
|
||||||
|
|
||||||
|
const setAllButtonStatus = (status: ButtonStatus) => {
|
||||||
|
dispatch({ type: ActionType.SetAllButtonStatus, payload: status });
|
||||||
|
};
|
||||||
|
|
||||||
|
const setIsLoading = (value: boolean) => {
|
||||||
|
dispatch({ type: ActionType.SetLoading, payload: value });
|
||||||
|
};
|
||||||
|
|
||||||
|
const setIsCPFPPossible = (status: ButtonStatus) => {
|
||||||
|
dispatch({ type: ActionType.SetCPFPPossible, payload: status });
|
||||||
|
};
|
||||||
|
|
||||||
|
const setIsRBFBumpFeePossible = (status: ButtonStatus) => {
|
||||||
|
dispatch({ type: ActionType.SetRBFBumpFeePossible, payload: status });
|
||||||
|
};
|
||||||
|
|
||||||
|
const setIsRBFCancelPossible = (status: ButtonStatus) => {
|
||||||
|
dispatch({ type: ActionType.SetRBFCancelPossible, payload: status });
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
setOptions({
|
setOptions({
|
||||||
|
@ -81,10 +165,11 @@ const TransactionsStatus = () => {
|
||||||
}, [colors, tx]);
|
}, [colors, tx]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
for (const newTx of wallet.current.getTransactions()) {
|
if (wallet.current) {
|
||||||
if (newTx.hash === hash) {
|
const transactions = wallet.current.getTransactions();
|
||||||
|
const newTx = transactions.find((t: Transaction) => t.hash === hash);
|
||||||
|
if (newTx) {
|
||||||
setTX(newTx);
|
setTX(newTx);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,18 +201,22 @@ const TransactionsStatus = () => {
|
||||||
console.log('checking tx', hash, 'for confirmations...');
|
console.log('checking tx', hash, 'for confirmations...');
|
||||||
const transactions = await BlueElectrum.multiGetTransactionByTxid([hash], true, 10);
|
const transactions = await BlueElectrum.multiGetTransactionByTxid([hash], true, 10);
|
||||||
const txFromElectrum = transactions[hash];
|
const txFromElectrum = transactions[hash];
|
||||||
|
if (!txFromElectrum) return;
|
||||||
|
|
||||||
console.log('got txFromElectrum=', txFromElectrum);
|
console.log('got txFromElectrum=', txFromElectrum);
|
||||||
|
|
||||||
const address = (txFromElectrum?.vout[0]?.scriptPubKey?.addresses || []).pop();
|
const address = (txFromElectrum?.vout[0]?.scriptPubKey?.addresses || []).pop();
|
||||||
|
if (!address) return;
|
||||||
|
|
||||||
if (txFromElectrum && !txFromElectrum.confirmations && txFromElectrum.vsize && address) {
|
if (!txFromElectrum.confirmations && txFromElectrum.vsize) {
|
||||||
const txsM = await BlueElectrum.getMempoolTransactionsByAddress(address);
|
const txsM = await BlueElectrum.getMempoolTransactionsByAddress(address);
|
||||||
let txFromMempool;
|
let txFromMempool;
|
||||||
// searhcing for a correct tx in case this address has several pending txs:
|
// searching for a correct tx in case this address has several pending txs:
|
||||||
for (const tempTxM of txsM) {
|
for (const tempTxM of txsM) {
|
||||||
if (tempTxM.tx_hash === hash) txFromMempool = tempTxM;
|
if (tempTxM.tx_hash === hash) txFromMempool = tempTxM;
|
||||||
}
|
}
|
||||||
if (!txFromMempool) return;
|
if (!txFromMempool) return;
|
||||||
|
|
||||||
console.log('txFromMempool=', txFromMempool);
|
console.log('txFromMempool=', txFromMempool);
|
||||||
|
|
||||||
const satPerVbyte = Math.round(txFromMempool.fee / txFromElectrum.vsize);
|
const satPerVbyte = Math.round(txFromMempool.fee / txFromElectrum.vsize);
|
||||||
|
@ -142,11 +231,11 @@ const TransactionsStatus = () => {
|
||||||
if (satPerVbyte < fees.medium) {
|
if (satPerVbyte < fees.medium) {
|
||||||
setEta(loc.formatString(loc.transactions.eta_1d));
|
setEta(loc.formatString(loc.transactions.eta_1d));
|
||||||
}
|
}
|
||||||
} else if (txFromElectrum.confirmations > 0) {
|
} else if (txFromElectrum.confirmations && txFromElectrum.confirmations > 0) {
|
||||||
// now, handling a case when tx became confirmed!
|
// now, handling a case when tx became confirmed!
|
||||||
triggerHapticFeedback(HapticFeedbackTypes.NotificationSuccess);
|
triggerHapticFeedback(HapticFeedbackTypes.NotificationSuccess);
|
||||||
setEta('');
|
setEta('');
|
||||||
setTX(prevState => {
|
setTX((prevState: any) => {
|
||||||
return Object.assign({}, prevState, { confirmations: txFromElectrum.confirmations });
|
return Object.assign({}, prevState, { confirmations: txFromElectrum.confirmations });
|
||||||
});
|
});
|
||||||
clearInterval(fetchTxInterval.current);
|
clearInterval(fetchTxInterval.current);
|
||||||
|
@ -160,7 +249,7 @@ const TransactionsStatus = () => {
|
||||||
}, [hash, intervalMs, tx, fetchAndSaveWalletTransactions]);
|
}, [hash, intervalMs, tx, fetchAndSaveWalletTransactions]);
|
||||||
|
|
||||||
const handleBackButton = () => {
|
const handleBackButton = () => {
|
||||||
goBack(null);
|
goBack();
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -175,21 +264,19 @@ const TransactionsStatus = () => {
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const initialState = async () => {
|
const initialButtonsState = async () => {
|
||||||
try {
|
try {
|
||||||
await checkPossibilityOfCPFP();
|
await checkPossibilityOfCPFP();
|
||||||
await checkPossibilityOfRBFBumpFee();
|
await checkPossibilityOfRBFBumpFee();
|
||||||
await checkPossibilityOfRBFCancel();
|
await checkPossibilityOfRBFCancel();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setIsCPFPPossible(buttonStatus.notPossible);
|
setAllButtonStatus(ButtonStatus.NotPossible);
|
||||||
setIsRBFBumpFeePossible(buttonStatus.notPossible);
|
|
||||||
setIsRBFCancelPossible(buttonStatus.notPossible);
|
|
||||||
}
|
}
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
initialState();
|
initialButtonsState();
|
||||||
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [tx, wallets]);
|
}, [tx, wallets]);
|
||||||
|
@ -207,51 +294,54 @@ const TransactionsStatus = () => {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const checkPossibilityOfCPFP = async () => {
|
const checkPossibilityOfCPFP = async () => {
|
||||||
if (!wallet.current.allowRBF()) {
|
if (!wallet.current?.allowRBF()) {
|
||||||
return setIsCPFPPossible(buttonStatus.notPossible);
|
return setIsCPFPPossible(ButtonStatus.NotPossible);
|
||||||
}
|
}
|
||||||
|
|
||||||
const cpfbTx = new HDSegwitBech32Transaction(null, tx.hash, wallet.current);
|
if (wallet.current) {
|
||||||
if ((await cpfbTx.isToUsTransaction()) && (await cpfbTx.getRemoteConfirmationsNum()) === 0) {
|
const cpfbTx = new HDSegwitBech32Transaction(null, tx.hash, wallet.current as HDSegwitBech32Wallet);
|
||||||
return setIsCPFPPossible(buttonStatus.possible);
|
if ((await cpfbTx.isToUsTransaction()) && (await cpfbTx.getRemoteConfirmationsNum()) === 0) {
|
||||||
} else {
|
return setIsCPFPPossible(ButtonStatus.Possible);
|
||||||
return setIsCPFPPossible(buttonStatus.notPossible);
|
} else {
|
||||||
|
return setIsCPFPPossible(ButtonStatus.NotPossible);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return setIsCPFPPossible(ButtonStatus.NotPossible);
|
||||||
};
|
};
|
||||||
|
|
||||||
const checkPossibilityOfRBFBumpFee = async () => {
|
const checkPossibilityOfRBFBumpFee = async () => {
|
||||||
if (!wallet.current.allowRBF()) {
|
if (!wallet.current?.allowRBF()) {
|
||||||
return setIsRBFBumpFeePossible(buttonStatus.notPossible);
|
return setIsRBFBumpFeePossible(ButtonStatus.NotPossible);
|
||||||
}
|
}
|
||||||
|
|
||||||
const rbfTx = new HDSegwitBech32Transaction(null, tx.hash, wallet.current);
|
const rbfTx = new HDSegwitBech32Transaction(null, tx.hash, wallet.current as HDSegwitBech32Wallet);
|
||||||
if (
|
if (
|
||||||
(await rbfTx.isOurTransaction()) &&
|
(await rbfTx.isOurTransaction()) &&
|
||||||
(await rbfTx.getRemoteConfirmationsNum()) === 0 &&
|
(await rbfTx.getRemoteConfirmationsNum()) === 0 &&
|
||||||
(await rbfTx.isSequenceReplaceable()) &&
|
(await rbfTx.isSequenceReplaceable()) &&
|
||||||
(await rbfTx.canBumpTx())
|
(await rbfTx.canBumpTx())
|
||||||
) {
|
) {
|
||||||
return setIsRBFBumpFeePossible(buttonStatus.possible);
|
return setIsRBFBumpFeePossible(ButtonStatus.Possible);
|
||||||
} else {
|
} else {
|
||||||
return setIsRBFBumpFeePossible(buttonStatus.notPossible);
|
return setIsRBFBumpFeePossible(ButtonStatus.NotPossible);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const checkPossibilityOfRBFCancel = async () => {
|
const checkPossibilityOfRBFCancel = async () => {
|
||||||
if (!wallet.current.allowRBF()) {
|
if (!wallet.current?.allowRBF()) {
|
||||||
return setIsRBFCancelPossible(buttonStatus.notPossible);
|
return setIsRBFCancelPossible(ButtonStatus.NotPossible);
|
||||||
}
|
}
|
||||||
|
|
||||||
const rbfTx = new HDSegwitBech32Transaction(null, tx.hash, wallet.current);
|
const rbfTx = new HDSegwitBech32Transaction(null, tx.hash, wallet.current as HDSegwitBech32Wallet);
|
||||||
if (
|
if (
|
||||||
(await rbfTx.isOurTransaction()) &&
|
(await rbfTx.isOurTransaction()) &&
|
||||||
(await rbfTx.getRemoteConfirmationsNum()) === 0 &&
|
(await rbfTx.getRemoteConfirmationsNum()) === 0 &&
|
||||||
(await rbfTx.isSequenceReplaceable()) &&
|
(await rbfTx.isSequenceReplaceable()) &&
|
||||||
(await rbfTx.canCancelTx())
|
(await rbfTx.canCancelTx())
|
||||||
) {
|
) {
|
||||||
return setIsRBFCancelPossible(buttonStatus.possible);
|
return setIsRBFCancelPossible(ButtonStatus.Possible);
|
||||||
} else {
|
} else {
|
||||||
return setIsRBFCancelPossible(buttonStatus.notPossible);
|
return setIsRBFCancelPossible(ButtonStatus.NotPossible);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -280,14 +370,14 @@ const TransactionsStatus = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderCPFP = () => {
|
const renderCPFP = () => {
|
||||||
if (isCPFPPossible === buttonStatus.unknown) {
|
if (isCPFPPossible === ButtonStatus.Unknown) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ActivityIndicator />
|
<ActivityIndicator />
|
||||||
<BlueSpacing20 />
|
<BlueSpacing20 />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
} else if (isCPFPPossible === buttonStatus.possible) {
|
} else if (isCPFPPossible === ButtonStatus.Possible) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Button onPress={navigateToCPFP} title={loc.transactions.status_bump} />
|
<Button onPress={navigateToCPFP} title={loc.transactions.status_bump} />
|
||||||
|
@ -298,13 +388,13 @@ const TransactionsStatus = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderRBFCancel = () => {
|
const renderRBFCancel = () => {
|
||||||
if (isRBFCancelPossible === buttonStatus.unknown) {
|
if (isRBFCancelPossible === ButtonStatus.Unknown) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ActivityIndicator />
|
<ActivityIndicator />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
} else if (isRBFCancelPossible === buttonStatus.possible) {
|
} else if (isRBFCancelPossible === ButtonStatus.Possible) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TouchableOpacity accessibilityRole="button" style={styles.cancel}>
|
<TouchableOpacity accessibilityRole="button" style={styles.cancel}>
|
||||||
|
@ -319,14 +409,14 @@ const TransactionsStatus = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderRBFBumpFee = () => {
|
const renderRBFBumpFee = () => {
|
||||||
if (isRBFBumpFeePossible === buttonStatus.unknown) {
|
if (isRBFBumpFeePossible === ButtonStatus.Unknown) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ActivityIndicator />
|
<ActivityIndicator />
|
||||||
<BlueSpacing20 />
|
<BlueSpacing20 />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
} else if (isRBFBumpFeePossible === buttonStatus.possible) {
|
} else if (isRBFBumpFeePossible === ButtonStatus.Possible) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Button onPress={navigateToRBFBumpFee} title={loc.transactions.status_bump} />
|
<Button onPress={navigateToRBFBumpFee} title={loc.transactions.status_bump} />
|
||||||
|
@ -351,7 +441,7 @@ const TransactionsStatus = () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isLoading || !tx) {
|
if (isLoading || !tx || wallet.current === undefined) {
|
||||||
return (
|
return (
|
||||||
<SafeArea>
|
<SafeArea>
|
||||||
<BlueLoading />
|
<BlueLoading />
|
||||||
|
@ -371,7 +461,7 @@ const TransactionsStatus = () => {
|
||||||
<View style={styles.center}>
|
<View style={styles.center}>
|
||||||
<Text style={[styles.value, stylesHook.value]} selectable>
|
<Text style={[styles.value, stylesHook.value]} selectable>
|
||||||
{formatBalanceWithoutSuffix(tx.value, wallet.current.preferredBalanceUnit, true)}{' '}
|
{formatBalanceWithoutSuffix(tx.value, wallet.current.preferredBalanceUnit, true)}{' '}
|
||||||
{wallet.current.preferredBalanceUnit !== BitcoinUnit.LOCAL_CURRENCY && (
|
{wallet.current?.preferredBalanceUnit !== BitcoinUnit.LOCAL_CURRENCY && (
|
||||||
<Text style={[styles.valueUnit, stylesHook.valueUnit]}>{loc.units[wallet.current.preferredBalanceUnit]}</Text>
|
<Text style={[styles.valueUnit, stylesHook.valueUnit]}>{loc.units[wallet.current.preferredBalanceUnit]}</Text>
|
||||||
)}
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
|
@ -412,7 +502,7 @@ const TransactionsStatus = () => {
|
||||||
<View style={styles.fee}>
|
<View style={styles.fee}>
|
||||||
<BlueText style={styles.feeText}>
|
<BlueText style={styles.feeText}>
|
||||||
{loc.send.create_fee.toLowerCase()} {formatBalanceWithoutSuffix(tx.fee, wallet.current.preferredBalanceUnit, true)}{' '}
|
{loc.send.create_fee.toLowerCase()} {formatBalanceWithoutSuffix(tx.fee, wallet.current.preferredBalanceUnit, true)}{' '}
|
||||||
{wallet.current.preferredBalanceUnit !== BitcoinUnit.LOCAL_CURRENCY && wallet.current.preferredBalanceUnit}
|
{wallet.current?.preferredBalanceUnit !== BitcoinUnit.LOCAL_CURRENCY && wallet.current?.preferredBalanceUnit}
|
||||||
</BlueText>
|
</BlueText>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
@ -540,16 +630,3 @@ const styles = StyleSheet.create({
|
||||||
fontWeight: '600',
|
fontWeight: '600',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
TransactionsStatus.navigationOptions = navigationStyle(
|
|
||||||
{
|
|
||||||
headerTitle: '',
|
|
||||||
statusBarStyle: 'auto',
|
|
||||||
},
|
|
||||||
(options, { theme }) => ({
|
|
||||||
...options,
|
|
||||||
headerStyle: {
|
|
||||||
backgroundColor: theme.colors.customHeader,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
);
|
|
Loading…
Add table
Reference in a new issue