BlueWallet/screen/transactions/details.js

294 lines
8.7 KiB
JavaScript
Raw Normal View History

2020-06-10 18:24:47 -04:00
/* global alert */
2020-11-29 22:59:20 -05:00
import React, { useContext, useEffect, useState } from 'react';
import { View, ScrollView, TouchableOpacity, Text, TextInput, Linking, StatusBar, StyleSheet, Keyboard } from 'react-native';
2020-12-04 13:39:47 +00:00
import {
SafeBlueArea,
BlueCard,
BlueText,
BlueLoading,
BlueSpacing20,
BlueCopyToClipboardButton,
BlueNavigationStyle,
} from '../../BlueComponents';
2020-12-04 12:50:23 +03:00
import HandoffSettings from '../../class/handoff';
2020-12-04 13:39:47 +00:00
import Handoff from 'react-native-handoff';
2020-07-20 16:38:46 +03:00
import loc from '../../loc';
import { BlueStorageContext } from '../../blue_modules/storage-context';
2020-12-04 13:39:47 +00:00
import { useNavigation, useRoute, useTheme } from '@react-navigation/native';
const dayjs = require('dayjs');
2018-09-11 19:17:24 +01:00
function onlyUnique(value, index, self) {
return self.indexOf(value) === index;
}
function arrDiff(a1, a2) {
const ret = [];
for (const v of a2) {
2018-09-11 19:17:24 +01:00
if (a1.indexOf(v) === -1) {
ret.push(v);
}
}
return ret;
}
2020-11-29 22:59:20 -05:00
const TransactionsDetails = () => {
const { setOptions } = useNavigation();
const { hash } = useRoute().params;
const { saveToDisk, txMetadata, wallets, getTransactions } = useContext(BlueStorageContext);
const [isHandOffUseEnabled, setIsHandOffUseEnabled] = useState(false);
const [from, setFrom] = useState();
const [to, setTo] = useState();
const [isLoading, setIsLoading] = useState(true);
const [tx, setTX] = useState();
const [memo, setMemo] = useState();
const { colors } = useTheme();
const stylesHooks = StyleSheet.create({
rowCaption: {
color: colors.foregroundColor,
},
txId: {
color: colors.foregroundColor,
},
txLink: {
color: colors.alternativeTextColor2,
},
saveText: {
color: colors.alternativeTextColor2,
},
memoTextInput: {
borderColor: colors.formBorder,
borderBottomColor: colors.formBorder,
backgroundColor: colors.inputBackgroundColor,
},
});
useEffect(() => {
setOptions({
headerRight: () => (
<TouchableOpacity disabled={isLoading} style={styles.save} onPress={handleOnSaveButtonTapped}>
<Text style={stylesHooks.saveText}>{loc.wallets.details_save}</Text>
</TouchableOpacity>
),
headerStyle: {
borderBottomWidth: 0,
elevation: 0,
shadowOpacity: 0,
shadowOffset: { height: 0, width: 0 },
backgroundColor: colors.customHeader,
},
});
// eslint-disable-next-line react-hooks/exhaustive-deps
2020-11-29 23:03:55 -05:00
}, [colors, isLoading, memo]);
2020-11-29 22:59:20 -05:00
useEffect(() => {
2018-03-17 22:39:21 +02:00
let foundTx = {};
let from = [];
let to = [];
for (const tx of getTransactions(null, Infinity, true)) {
2018-01-30 22:42:38 +00:00
if (tx.hash === hash) {
foundTx = tx;
for (const input of foundTx.inputs) {
2018-03-17 22:39:21 +02:00
from = from.concat(input.addresses);
2018-01-30 22:42:38 +00:00
}
for (const output of foundTx.outputs) {
if (output.addresses) to = to.concat(output.addresses);
2019-06-11 00:18:40 +01:00
if (output.scriptPubKey && output.scriptPubKey.addresses) to = to.concat(output.scriptPubKey.addresses);
2018-01-30 22:42:38 +00:00
}
}
}
2020-11-29 22:59:20 -05:00
for (const w of wallets) {
for (const t of w.getTransactions()) {
2018-10-31 20:14:28 +00:00
if (t.hash === hash) {
console.log('tx', hash, 'belongs to', w.getLabel());
}
}
}
2020-11-29 22:59:20 -05:00
if (txMetadata[foundTx.hash]) {
if (txMetadata[foundTx.hash].memo) {
setMemo(txMetadata[foundTx.hash].memo);
2020-06-10 18:24:47 -04:00
}
}
2018-01-30 22:42:38 +00:00
2020-11-29 22:59:20 -05:00
setTX(foundTx);
setFrom(from);
setTo(to);
setIsLoading(false);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [hash, wallets]);
2020-11-29 22:59:20 -05:00
useEffect(() => {
HandoffSettings.isHandoffUseEnabled().then(setIsHandOffUseEnabled);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
2020-11-29 22:59:20 -05:00
const handleOnSaveButtonTapped = () => {
Keyboard.dismiss();
2020-11-29 22:59:20 -05:00
txMetadata[tx.hash] = { memo };
saveToDisk().then(_success => alert(loc.transactions.transaction_note_saved));
2020-06-10 18:24:47 -04:00
};
2020-11-29 23:03:55 -05:00
const handleOnOpenTransactionOnBlockExporerTapped = () => {
const url = `https://blockstream.info/tx/${tx.hash}`;
Linking.canOpenURL(url).then(supported => {
if (supported) {
Linking.openURL(url);
}
});
};
2020-11-29 22:59:20 -05:00
if (isLoading || !tx) {
return <BlueLoading />;
}
2020-06-10 18:24:47 -04:00
2020-11-29 22:59:20 -05:00
return (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.root}>
{isHandOffUseEnabled && (
<Handoff title={`Bitcoin Transaction ${tx.hash}`} type="io.bluewallet.bluewallet" url={`https://blockstream.info/tx/${tx.hash}`} />
)}
<StatusBar barStyle="default" />
<ScrollView style={styles.scroll}>
<BlueCard>
<View>
<TextInput
placeholder={loc.send.details_note_placeholder}
value={memo}
placeholderTextColor="#81868e"
style={[styles.memoTextInput, stylesHooks.memoTextInput]}
onChangeText={setMemo}
/>
<BlueSpacing20 />
</View>
2018-01-30 22:42:38 +00:00
2020-11-29 22:59:20 -05:00
{from && (
<>
<View style={styles.rowHeader}>
<BlueText style={[styles.rowCaption, stylesHooks.rowCaption]}>{loc.transactions.details_from}</BlueText>
<BlueCopyToClipboardButton stringToCopy={from.filter(onlyUnique).join(', ')} />
</View>
<BlueText style={styles.rowValue}>{from.filter(onlyUnique).join(', ')}</BlueText>
</>
)}
2018-01-30 22:42:38 +00:00
2020-11-29 22:59:20 -05:00
{to && (
<>
<View style={styles.rowHeader}>
<BlueText style={[styles.rowCaption, stylesHooks.rowCaption]}>{loc.transactions.details_to}</BlueText>
<BlueCopyToClipboardButton stringToCopy={to.filter(onlyUnique).join(', ')} />
</View>
<BlueText style={styles.rowValue}>{arrDiff(from, to.filter(onlyUnique)).join(', ')}</BlueText>
</>
)}
2020-11-29 22:59:20 -05:00
{tx.fee && (
<>
<BlueText style={[styles.rowCaption, stylesHooks.rowCaption]}>{loc.send.create_fee}</BlueText>
<BlueText style={styles.rowValue}>{tx.fee + ' sats'}</BlueText>
</>
)}
2020-11-29 22:59:20 -05:00
{tx.hash && (
<>
<View style={styles.rowHeader}>
<BlueText style={[styles.txId, stylesHooks.txId]}>Txid</BlueText>
<BlueCopyToClipboardButton stringToCopy={tx.hash} />
</View>
<BlueText style={styles.txHash}>{tx.hash}</BlueText>
2020-11-29 23:03:55 -05:00
<TouchableOpacity onPress={handleOnOpenTransactionOnBlockExporerTapped}>
2020-11-29 22:59:20 -05:00
<BlueText style={[styles.txLink, stylesHooks.txLink]}>{loc.transactions.details_show_in_block_explorer}</BlueText>
</TouchableOpacity>
</>
)}
2018-12-18 20:46:06 -05:00
2020-11-29 22:59:20 -05:00
{tx.received && (
<>
<BlueText style={[styles.rowCaption, stylesHooks.rowCaption]}>{loc.transactions.details_received}</BlueText>
<BlueText style={styles.rowValue}>{dayjs(tx.received).format('MM/DD/YYYY h:mm A')}</BlueText>
</>
)}
2018-12-18 20:46:06 -05:00
2020-11-29 22:59:20 -05:00
{tx.block_height > 0 && (
<>
<BlueText style={[styles.rowCaption, stylesHooks.rowCaption]}>{loc.transactions.details_block}</BlueText>
<BlueText style={styles.rowValue}>{tx.block_height}</BlueText>
</>
)}
2020-11-29 22:59:20 -05:00
{tx.inputs && (
<>
<BlueText style={[styles.rowCaption, stylesHooks.rowCaption]}>{loc.transactions.details_inputs}</BlueText>
<BlueText style={styles.rowValue}>{tx.inputs.length}</BlueText>
</>
)}
2020-11-29 22:59:20 -05:00
{tx.outputs.length > 0 && (
<>
<BlueText style={[styles.rowCaption, stylesHooks.rowCaption]}>{loc.transactions.details_outputs}</BlueText>
<BlueText style={styles.rowValue}>{tx.outputs.length}</BlueText>
</>
)}
</BlueCard>
</ScrollView>
</SafeBlueArea>
);
};
2020-11-29 22:59:20 -05:00
const styles = StyleSheet.create({
root: {
flex: 1,
},
scroll: {
flex: 1,
},
rowHeader: {
flex: 1,
flexDirection: 'row',
marginBottom: 4,
justifyContent: 'space-between',
},
rowCaption: {
fontSize: 16,
fontWeight: '500',
marginBottom: 4,
},
rowValue: {
marginBottom: 26,
color: 'grey',
},
txId: {
fontSize: 16,
fontWeight: '500',
},
txHash: {
marginBottom: 8,
color: 'grey',
},
txLink: {
marginBottom: 26,
},
save: {
marginHorizontal: 16,
justifyContent: 'center',
alignItems: 'center',
},
memoTextInput: {
flexDirection: 'row',
borderWidth: 1,
borderBottomWidth: 0.5,
minHeight: 44,
height: 44,
alignItems: 'center',
marginVertical: 8,
borderRadius: 4,
paddingHorizontal: 8,
color: '#81868e',
},
});
2018-03-18 02:48:23 +00:00
2020-11-29 22:59:20 -05:00
export default TransactionsDetails;
2020-07-15 13:32:59 -04:00
2020-12-04 13:39:47 +00:00
TransactionsDetails.navigationOptions = () => ({
...BlueNavigationStyle(),
2020-07-20 16:38:46 +03:00
title: loc.transactions.details_title,
2020-07-15 13:32:59 -04:00
});