import React, { useState, useEffect } from 'react'; import { useRoute, RouteProp } from '@react-navigation/native'; import * as bitcoin from 'bitcoinjs-lib'; import { ActivityIndicator, Keyboard, Linking, StyleSheet, TextInput, View } from 'react-native'; import * as BlueElectrum from '../../blue_modules/BlueElectrum'; import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback'; import Notifications from '../../blue_modules/notifications'; import { BlueBigCheckmark, BlueButtonLink, BlueCard, BlueFormLabel, BlueSpacing10, BlueSpacing20, BlueTextCentered, } from '../../BlueComponents'; import { HDSegwitBech32Wallet } from '../../class'; import presentAlert from '../../components/Alert'; import Button from '../../components/Button'; import SafeArea from '../../components/SafeArea'; import { useTheme } from '../../components/themes'; import { scanQrHelper } from '../../helpers/scan-qr'; import loc from '../../loc'; import { DetailViewStackParamList } from '../../navigation/DetailViewStackParamList'; const BROADCAST_RESULT = Object.freeze({ none: 'Input transaction hex', pending: 'pending', success: 'success', error: 'error', }); type RouteProps = RouteProp; const Broadcast: React.FC = () => { const { name, params } = useRoute(); const [tx, setTx] = useState(); const [txHex, setTxHex] = useState(); const { colors } = useTheme(); const [broadcastResult, setBroadcastResult] = useState(BROADCAST_RESULT.none); const stylesHooks = StyleSheet.create({ input: { borderColor: colors.formBorder, borderBottomColor: colors.formBorder, backgroundColor: colors.inputBackgroundColor, }, }); useEffect(() => { const scannedData = params?.scannedData; if (scannedData) { handleScannedData(scannedData); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [params?.scannedData]); const handleUpdateTxHex = (nextValue: string) => setTxHex(nextValue.trim()); const handleBroadcast = async () => { Keyboard.dismiss(); setBroadcastResult(BROADCAST_RESULT.pending); try { await BlueElectrum.ping(); await BlueElectrum.waitTillConnected(); const walletObj = new HDSegwitBech32Wallet(); if (txHex) { const result = await walletObj.broadcastTx(txHex); if (result) { const newTx = bitcoin.Transaction.fromHex(txHex); const txid = newTx.getId(); setTx(txid); setBroadcastResult(BROADCAST_RESULT.success); triggerHapticFeedback(HapticFeedbackTypes.NotificationSuccess); // @ts-ignore: fix later Notifications.majorTomToGroundControl([], [], [txid]); } else { setBroadcastResult(BROADCAST_RESULT.error); } } } catch (error: any) { presentAlert({ title: loc.errors.error, message: error.message }); triggerHapticFeedback(HapticFeedbackTypes.NotificationError); setBroadcastResult(BROADCAST_RESULT.error); } }; const handleScannedData = (scannedData: string) => { if (scannedData.indexOf('+') === -1 && scannedData.indexOf('=') === -1 && scannedData.indexOf('=') === -1) { // this looks like NOT base64, so maybe its transaction's hex return handleUpdateTxHex(scannedData); } try { // should be base64 encoded PSBT const validTx = bitcoin.Psbt.fromBase64(scannedData).extractTransaction(); return handleUpdateTxHex(validTx.toHex()); } catch (e) {} }; const handleQRScan = () => { scanQrHelper(name, true, undefined, false); }; let status; switch (broadcastResult) { case BROADCAST_RESULT.none: status = loc.send.broadcastNone; break; case BROADCAST_RESULT.pending: status = loc.send.broadcastPending; break; case BROADCAST_RESULT.success: status = loc.send.broadcastSuccess; break; case BROADCAST_RESULT.error: status = loc.send.broadcastError; break; default: status = broadcastResult; } return ( {BROADCAST_RESULT.success !== broadcastResult && ( {status} {BROADCAST_RESULT.pending === broadcastResult && }