DEV Community

Swatantra goswami
Swatantra goswami

Posted on • Edited on

Bitcoin lightning network

We will use https://breez.technology/sdk/ SDK for lightning network
here is the documentation of that https://sdk-doc-spark.breez.technology/guide/install.html

NOTE Conversion rate

🔹 1 BTC = 100,000,000 satoshis // 10 cr ( 1 cr has 7 zeros)
🔹 10,000 satoshis = 0.0001 BTC
🔹 USD value = 0.0001 × current BTC price in USD
Enter fullscreen mode Exit fullscreen mode
import {
  SafeAreaView,
  Text,
  TouchableOpacity,
  View,
  TextInput,
  ScrollView,
  StyleSheet,
  Alert,
} from 'react-native';
import {
  connect,
  defaultConfig,
  Network,
  Seed,
  ReceivePaymentMethod,
  SendPaymentMethod,
} from '@breeztech/breez-sdk-spark-react-native';
import {useState, useEffect} from 'react';
import { DocumentDirectoryPath } from 'react-native-fs';

// Event Listener Class
class JsEventListener {
  constructor(callback) {
    this.callback = callback;
  }

  onEvent = event => {
    console.log(`Received event: ${JSON.stringify(event)}`);
    if (this.callback) {
      this.callback(event);
    }
  };
}

export default function BreezSpark() {
   const [sdk, setSdk] = useState(null);
  const [balance, setBalance] = useState(null);
  const [events, setEvents] = useState([]);
  const [listenerId, setListenerId] = useState(null);
  const [payments, setPayments] = useState([]);

  // For receiving payments
  const [invoiceDescription, setInvoiceDescription] = useState('');
  const [invoiceAmount, setInvoiceAmount] = useState('');
  const [generatedInvoice, setGeneratedInvoice] = useState('');
  const [receiveFeeSats, setReceiveFeeSats] = useState(null);

  // For sending payments
  const [paymentRequest, setPaymentRequest] = useState('');
  const [sendAmount, setSendAmount] = useState('');
  const [preparedPayment, setPreparedPayment] = useState(null);

  async function connectToSdk() {
    try {
      const mnemonic = ''; // 9901 sats
      // const mnemonic = ''; //    10001
      let config = defaultConfig(Network.Regtest);
      config.apiKey = '';

      const baseDir = DocumentDirectoryPath.replace('file://', '');
      const workingDir = `${baseDir}breezSdkSpark`;

    //   const directoryPath = await getOrCreateDirectory('testing', workingDir);

      console.log('API Key configured:', !!config.apiKey);

      const seed = new Seed.Mnemonic({mnemonic});
      const connectedSdk = await connect({
        config,
        seed,
        storageDir: workingDir,
      });

      setSdk(connectedSdk);
      console.log('✅ Connected successfully!');

      // Start listening to events
      setupEventListener(connectedSdk);

      // Get initial balance
      await fetchBalance(connectedSdk);

      // Load payment history
      await fetchPayments(connectedSdk);
    } catch (err) {
      console.error('❌ Connection error:', err);
      Alert.alert('Connection Error', err.message);
    }
  }

  function setupEventListener(sdkInstance) {
    const eventListener = new JsEventListener(event => {
      setEvents(prev =>
        [{event, timestamp: new Date().toISOString()}, ...prev].slice(0, 10),
      );

      // Refresh balance on payment events
      if (
        event.type === 'paymentSucceeded' ||
        event.type === 'paymentReceived'
      ) {
        fetchBalance(sdkInstance);
        fetchPayments(sdkInstance);
      }
    });

    const id = sdkInstance.addEventListener(eventListener);
    setListenerId(id);
    console.log('Event listener registered:', id);
  }

  async function fetchBalance(sdkInstance = sdk) {
    if (!sdkInstance) return;

    try {
      const info = await sdkInstance.getInfo({});
      setBalance(info.balanceSats);
      console.log('Balance:', info.balanceSats);
    } catch (err) {
      console.error('Error fetching balance:', err);
      Alert.alert('Balance Error', err.message);
    }
  }

  async function fetchPayments(sdkInstance = sdk) {
    if (!sdkInstance) return;

    try {
      const response = await sdkInstance.listPayments({
        offset: undefined,
        limit: 20,
      });
      console.log("response=>",response)
      setPayments(response.payments);
      console.log('Payments loaded:', response.payments.length);
    } catch (err) {
      console.error('Error fetching payments:', err);
    }
  }

  async function generateInvoice() {
    if (!sdk) {
      Alert.alert('Error', 'SDK not connected');
      return;
    }

    try {
      const amountSats = invoiceAmount ? BigInt(invoiceAmount) : undefined;

      // NOTE vai invoice
      const response = await sdk.receivePayment({
        paymentMethod: new ReceivePaymentMethod.Bolt11Invoice({
          description: invoiceDescription || 'Payment',
          amountSats,
        }),
      });
      console.log("response=>", response)
      // NOTE vai btc address ub regtest
      // const response = await sdk.receivePayment({
      //   paymentMethod: new ReceivePaymentMethod.BitcoinAddress()
      // })

      console.log(`Payment Request: ${paymentRequest}`)
      setGeneratedInvoice(response.paymentRequest);
      setReceiveFeeSats(response.fee);
      console.log('Invoice generated:', response.paymentRequest);
      console.log('Receive fees:', response.fee);

      Alert.alert('Invoice Generated', 'Check the invoice field below');
    } catch (err) {
      console.error('Error generating invoice:', err);
      Alert.alert('Invoice Error', err.message);
    }
  }

  async function preparePayment() {
    if (!sdk || !paymentRequest) {
      Alert.alert('Error', 'SDK not connected or no payment request');
      return;
    }

    try {
      const amountSats = sendAmount ? BigInt(sendAmount) : undefined;

      const prepareResponse = await sdk.prepareSendPayment({
        paymentRequest,
        amountSats,
      });

      setPreparedPayment(prepareResponse);

      if (
        prepareResponse.paymentMethod instanceof SendPaymentMethod.Bolt11Invoice
      ) {
        const lightningFee =
          prepareResponse.paymentMethod.inner.lightningFeeSats;
        const sparkFee =
          prepareResponse.paymentMethod.inner.sparkTransferFeeSats;

        Alert.alert(
          'Payment Prepared',
          `Lightning Fees: ${lightningFee} sats\nSpark Fees: ${
            sparkFee || 'N/A'
          } sats`,
          [
            {text: 'Cancel', style: 'cancel'},
            {text: 'Send Payment', onPress: () => sendPayment(prepareResponse)},
          ],
        );
      }
    } catch (err) {
      console.error('Error preparing payment:', err);
      Alert.alert('Prepare Error', err.message);
    }
  }

  async function sendPayment(prepareResponse) {
    if (!sdk) return;

    try {
      const response = await sdk.sendPayment({
        prepareResponse,
      });

      console.log('Payment sent:', response);
      Alert.alert('Success', 'Payment sent successfully!');

      // Clear form and refresh
      setPaymentRequest('');
      setSendAmount('');
      setPreparedPayment(null);
      await fetchBalance();
      await fetchPayments();
    } catch (err) {
      console.error('Error sending payment:', err);
      Alert.alert('Send Error', err.message);
    }
  }

  useEffect(() => {
    return () => {
      if (sdk && listenerId) {
        sdk.removeEventListener(listenerId);
      }
    };
  }, [sdk, listenerId]);

  console.log("receiveFeeSats=>", receiveFeeSats)
  return (
    <SafeAreaView style={styles.container}>
      <ScrollView style={styles.scrollView}>
        {/* Connection Section */}
        <View style={styles.section}>
          <TouchableOpacity
            onPress={connectToSdk}
            style={[styles.button, sdk && styles.buttonConnected]}
            disabled={!!sdk}>
            <Text style={styles.buttonText}>
              {sdk ? '✅ Connected' : 'Connect to Breez SDK'}
            </Text>
          </TouchableOpacity>

          {balance !== null && (
            <View style={styles.balanceContainer}>
              <Text style={styles.balanceLabel}>Balance:</Text>
              <Text style={styles.balanceAmount}>
                {balance.toString()} sats
              </Text>
              <TouchableOpacity
                onPress={() => fetchBalance()}
                style={styles.refreshButton}>
                <Text>🔄 Refresh</Text>
              </TouchableOpacity>
            </View>
          )}
        </View>

        {/* Receive Payment Section */}
        {sdk && (
          <View style={styles.section}>
            <Text style={styles.sectionTitle}>Receive Payment</Text>
            <TextInput
              style={styles.input}
              placeholder="Invoice description"
              placeholderTextColor="#9CA3AF" 
              value={invoiceDescription}
              onChangeText={setInvoiceDescription}
            />
            <TextInput
              style={styles.input}
              placeholder="Amount (sats) - optional"
              placeholderTextColor="#9CA3AF" 
              value={invoiceAmount}
              onChangeText={setInvoiceAmount}
              keyboardType="number-pad"
            />
            <TouchableOpacity onPress={generateInvoice} style={styles.button}>
              <Text style={styles.buttonText}>Generate Invoice</Text>
            </TouchableOpacity>

            {generatedInvoice && (
              <View style={styles.invoiceContainer}>
                <Text style={styles.label}>Invoice:</Text>
                <Text style={styles.invoice} selectable>
                  {generatedInvoice}
                </Text>
                {/* {receiveFeeSats !== null && (
                  <Text style={styles.feeText}>
                    Fee: {receiveFeeSats.toString()} sats
                  </Text>
                )} */}
              </View>
            )}
          </View>
        )}

        {/* Send Payment Section */}
        {sdk && (
          <View style={styles.section}>
            <Text style={styles.sectionTitle}>Send Payment</Text>
            <TextInput
              style={[styles.input, styles.textArea]}
              placeholder="Paste Lightning invoice (bolt11)"
              placeholderTextColor="#9CA3AF" 
              value={paymentRequest}
              onChangeText={setPaymentRequest}
              multiline
            />
            <TextInput
              style={styles.input}
              placeholder="Amount (sats) - optional"
              placeholderTextColor="#9CA3AF" // gray, change as needed
              value={sendAmount}
              onChangeText={setSendAmount}
              keyboardType="number-pad"

            />
            <TouchableOpacity onPress={preparePayment} style={styles.button}>
              <Text style={styles.buttonText}>Prepare & Send Payment</Text>
            </TouchableOpacity>
          </View>
        )}

        {/* Events Section */}
        {events.length > 0 && (
          <View style={styles.section}>
            <Text style={styles.sectionTitle}>
              Recent Events ({events.length})
            </Text>
            {events.map((item, idx) => (
              <View key={idx} style={styles.eventItem}>
                <Text style={styles.eventTime}>{item.timestamp}</Text>
                <Text style={styles.eventText}>
                  {JSON.stringify(item.event, null, 2)}
                </Text>
              </View>
            ))}
          </View>
        )}

        {/* Payments History */}
        {payments.length > 0 && (
          <View style={styles.section}>
            <Text style={styles.sectionTitle}>
              Payment History ({payments.length})
            </Text>
            {payments.slice(0, 5).map((payment, idx) => (
              <View key={idx} style={styles.paymentItem}>
                <Text style={styles.paymentAmount}>
                  {payment.amountSats?.toString() || 'N/A'} sats
                </Text>
                <Text style={styles.paymentStatus}>{payment.status}</Text>
              </View>
            ))}
          </View>
        )}
      </ScrollView>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f5f5f5',
  },
  scrollView: {
    flex: 1,
    padding: 16,
  },
  section: {
    backgroundColor: 'white',
    borderRadius: 12,
    padding: 16,
    marginBottom: 16,
    shadowColor: '#000',
    shadowOffset: {width: 0, height: 2},
    shadowOpacity: 0.1,
    shadowRadius: 4,
    elevation: 3,
  },
  sectionTitle: {
    fontSize: 18,
    fontWeight: 'bold',
    marginBottom: 12,
    color: '#333',
  },
  button: {
    backgroundColor: '#007AFF',
    padding: 16,
    borderRadius: 8,
    alignItems: 'center',
  },
  buttonConnected: {
    backgroundColor: '#34C759',
  },
  buttonText: {
    color: 'white',
    fontSize: 16,
    fontWeight: '600',
  },
  balanceContainer: {
    marginTop: 16,
    padding: 16,
    backgroundColor: '#f8f8f8',
    borderRadius: 8,
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
  },
  balanceLabel: {
    fontSize: 16,
    color: '#666',
  },
  balanceAmount: {
    fontSize: 20,
    fontWeight: 'bold',
    color: '#007AFF',
    flex: 1,
    marginLeft: 8,
  },
  refreshButton: {
    padding: 8,
  },
  input: {
    borderWidth: 1,
    borderColor: '#ddd',
    borderRadius: 8,
    padding: 12,
    marginBottom: 12,
    fontSize: 16,
  },
  textArea: {
    height: 80,
    textAlignVertical: 'top',
  },
  invoiceContainer: {
    marginTop: 12,
    padding: 12,
    backgroundColor: '#f8f8f8',
    borderRadius: 8,
  },
  label: {
    fontSize: 14,
    fontWeight: '600',
    marginBottom: 8,
    color: '#666',
  },
  invoice: {
    fontSize: 12,
    color: '#333',
    fontFamily: 'monospace',
  },
  feeText: {
    marginTop: 8,
    fontSize: 14,
    color: '#666',
  },
  eventItem: {
    padding: 12,
    backgroundColor: '#f8f8f8',
    borderRadius: 8,
    marginBottom: 8,
  },
  eventTime: {
    fontSize: 12,
    color: '#666',
    marginBottom: 4,
  },
  eventText: {
    fontSize: 12,
    fontFamily: 'monospace',
    color: '#333',
  },
  paymentItem: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    padding: 12,
    backgroundColor: '#f8f8f8',
    borderRadius: 8,
    marginBottom: 8,
  },
  paymentAmount: {
    fontSize: 16,
    fontWeight: '600',
    color: '#333',
  },
  paymentStatus: {
    fontSize: 14,
    color: '#666',
  },
});
Enter fullscreen mode Exit fullscreen mode

Use Two Screen

import {
  SafeAreaView,
  Text,
  TouchableOpacity,
  View,
  TextInput,
  ScrollView,
  StyleSheet,
  Alert,
} from 'react-native';
import {
  connect,
  defaultConfig,
  Network,
  Seed,
  ReceivePaymentMethod,
  SendPaymentMethod,
} from '@breeztech/breez-sdk-spark-react-native';
import React, {useState, useEffect} from 'react';
import {DocumentDirectoryPath} from 'react-native-fs';

import {SceneMap, TabBar, TabView} from 'react-native-tab-view';
import {SCREEN_WIDTH} from '@gorhom/bottom-sheet';

const ROUTES = [
  {key: 'add_coins', title: 'Coins '},
  {key: 'add_coins_group', title: 'Coins Group '},
];

// Event Listener Class
class JsEventListener {
  constructor(callback) {
    this.callback = callback;
  }

  onEvent = event => {
    console.log(`Received event: ${JSON.stringify(event)}`);
    if (this.callback) {
      this.callback(event);
    }
  };
}

const RenderTabBar = props => {
  const {styles} = props;

  // Create options for each route
  const tabOptions = ROUTES.reduce((acc, route) => {
    acc[route.key] = {
      label: ({focused}) => (
        <Text style={[styles.tabLabel, focused && styles.tabLabelFocused]}>
          {route.title}
        </Text>
      ),
    };
    return acc;
  }, {});

  return (
    <TabBar
      {...props}
      indicatorStyle={styles.indicator}
      style={styles.tabBar}
      options={tabOptions}
    />
  );
};

function BreezSpark1() {
  const [sdk, setSdk] = useState(null);
  const [balance, setBalance] = useState(null);
  const [events, setEvents] = useState([]);
  const [listenerId, setListenerId] = useState(null);
  const [payments, setPayments] = useState([]);

  // For receiving payments
  const [invoiceDescription, setInvoiceDescription] = useState('');
  const [invoiceAmount, setInvoiceAmount] = useState('');
  const [generatedInvoice, setGeneratedInvoice] = useState('');
  const [receiveFeeSats, setReceiveFeeSats] = useState(null);

  // For sending payments
  const [paymentRequest, setPaymentRequest] = useState('');
  const [sendAmount, setSendAmount] = useState('');
  const [preparedPayment, setPreparedPayment] = useState(null);

  async function connectToSdk() {
    try {
      const mnemonic = ''; // 9901 sats
      // const mnemonic = ''; //    10001
      let config = defaultConfig(Network.Regtest);
      config.apiKey = '';

      const baseDir = DocumentDirectoryPath.replace('file://', '');
      const workingDir = `${baseDir}breezSdkSpark`;

      //   const directoryPath = await getOrCreateDirectory('testing', workingDir);

      console.log('API Key configured:', !!config.apiKey);

      const seed = new Seed.Mnemonic({mnemonic});
      const connectedSdk = await connect({
        config,
        seed,
        storageDir: workingDir,
      });

      setSdk(connectedSdk);
      console.log('✅ Connected successfully!');

      // Start listening to events
      setupEventListener(connectedSdk);

      // Get initial balance
      await fetchBalance(connectedSdk);

      // Load payment history
      await fetchPayments(connectedSdk);
    } catch (err) {
      console.error('❌ Connection error:', err);
      Alert.alert('Connection Error', err.message);
    }
  }

  function setupEventListener(sdkInstance) {
    const eventListener = new JsEventListener(event => {
      setEvents(prev =>
        [{event, timestamp: new Date().toISOString()}, ...prev].slice(0, 10),
      );

      // Refresh balance on payment events
      if (
        event.type === 'paymentSucceeded' ||
        event.type === 'paymentReceived'
      ) {
        fetchBalance(sdkInstance);
        fetchPayments(sdkInstance);
      }
    });

    const id = sdkInstance.addEventListener(eventListener);
    setListenerId(id);
    console.log('Event listener registered:', id);
  }

  async function fetchBalance(sdkInstance = sdk) {
    if (!sdkInstance) return;

    try {
      const info = await sdkInstance.getInfo({});
      setBalance(info.balanceSats);
      console.log('Balance:', info.balanceSats);
    } catch (err) {
      console.error('Error fetching balance:', err);
      Alert.alert('Balance Error', err.message);
    }
  }

  async function fetchPayments(sdkInstance = sdk) {
    if (!sdkInstance) return;

    try {
      const response = await sdkInstance.listPayments({
        offset: undefined,
        limit: 20,
      });
      console.log('response=>', response);
      setPayments(response.payments);
      console.log('Payments loaded:', response.payments.length);
    } catch (err) {
      console.error('Error fetching payments:', err);
    }
  }

  async function generateInvoice() {
    if (!sdk) {
      Alert.alert('Error', 'SDK not connected');
      return;
    }

    try {
      const amountSats = invoiceAmount ? BigInt(invoiceAmount) : undefined;

      // NOTE vai invoice
      const response = await sdk.receivePayment({
        paymentMethod: new ReceivePaymentMethod.Bolt11Invoice({
          description: invoiceDescription || 'Payment',
          amountSats,
        }),
      });
      console.log('response=>', response);
      // NOTE vai btc address ub regtest
      // const response = await sdk.receivePayment({
      //   paymentMethod: new ReceivePaymentMethod.BitcoinAddress()
      // })

      console.log(`Payment Request: ${paymentRequest}`);
      setGeneratedInvoice(response.paymentRequest);
      setReceiveFeeSats(response.fee);
      console.log('Invoice generated:', response.paymentRequest);
      console.log('Receive fees:', response.fee);

      Alert.alert('Invoice Generated', 'Check the invoice field below');
    } catch (err) {
      console.error('Error generating invoice:', err);
      Alert.alert('Invoice Error', err.message);
    }
  }

  async function preparePayment() {
    if (!sdk || !paymentRequest) {
      Alert.alert('Error', 'SDK not connected or no payment request');
      return;
    }

    try {
      const amountSats = sendAmount ? BigInt(sendAmount) : undefined;
      console.log('paymentRequest: ', paymentRequest);
      console.log('amountSats: ', amountSats);
      const prepareResponse = await sdk.prepareSendPayment({
        paymentRequest,
        amountSats,
      });

      setPreparedPayment(prepareResponse);
      console.log('prepareResponse=>', prepareResponse);
      if (
        prepareResponse.paymentMethod instanceof SendPaymentMethod.Bolt11Invoice
      ) {
        const lightningFee =
          prepareResponse.paymentMethod.inner.lightningFeeSats;
        const sparkFee =
          prepareResponse.paymentMethod.inner.sparkTransferFeeSats;
        console.log('lightningFee=:', lightningFee);
        console.log('sparkFee=:', sparkFee);
        Alert.alert(
          'Payment Prepared',
          `Lightning Fees: ${lightningFee} sats\nSpark Fees: ${
            sparkFee || 'N/A'
          } sats`,
          [
            {text: 'Cancel', style: 'cancel'},
            {text: 'Send Payment', onPress: () => sendPayment(prepareResponse)},
          ],
        );
      }
    } catch (err) {
      console.error('Error preparing payment:', err);
      Alert.alert('Prepare Error', err.message);
    }
  }

  async function sendPayment(prepareResponse) {
    if (!sdk) return;

    try {
      const response = await sdk.sendPayment({
        prepareResponse,
      });

      console.log('Payment sent:', response);
      Alert.alert('Success', 'Payment sent successfully!');

      // Clear form and refresh
      setPaymentRequest('');
      setSendAmount('');
      setPreparedPayment(null);
      await fetchBalance();
      await fetchPayments();
    } catch (err) {
      console.error('Error sending payment:', err);
      Alert.alert('Send Error', err.message);
    }
  }

  useEffect(() => {
    return () => {
      if (sdk && listenerId) {
        sdk.removeEventListener(listenerId);
      }
    };
  }, [sdk, listenerId]);

  console.log('receiveFeeSats=>', receiveFeeSats);
  return (
    <SafeAreaView style={styles.container}>
      <ScrollView style={styles.scrollView}>
        {/* Connection Section */}
        <View style={styles.section}>
          <TouchableOpacity
            onPress={connectToSdk}
            style={[styles.button, sdk && styles.buttonConnected]}
            disabled={!!sdk}>
            <Text style={styles.buttonText}>
              {sdk ? '✅ Connected' : 'Connect to Breez SDK with mnemonic'}
              {'\n'}
              {'\n'}
              {
                'mix budget despair always cancel actress inspire curtain large grape thing snack'
              }
            </Text>
          </TouchableOpacity>

          {balance !== null && (
            <View style={styles.balanceContainer}>
              <Text style={styles.balanceLabel}>Balance:</Text>
              <Text style={styles.balanceAmount}>
                {balance.toString()} sats
              </Text>
              <TouchableOpacity
                onPress={() => fetchBalance()}
                style={styles.refreshButton}>
                <Text>🔄 Refresh</Text>
              </TouchableOpacity>
            </View>
          )}
        </View>

        {/* Receive Payment Section */}
        {sdk && (
          <View style={styles.section}>
            <Text style={styles.sectionTitle}>Receive Payment</Text>
            <TextInput
              style={styles.input}
              placeholder="Invoice description"
              placeholderTextColor="#9CA3AF"
              value={invoiceDescription}
              onChangeText={setInvoiceDescription}
            />
            <TextInput
              style={styles.input}
              placeholder="Amount (sats) - optional"
              placeholderTextColor="#9CA3AF"
              value={invoiceAmount}
              onChangeText={setInvoiceAmount}
              keyboardType="number-pad"
            />
            <TouchableOpacity onPress={generateInvoice} style={styles.button}>
              <Text style={styles.buttonText}>Generate Invoice</Text>
            </TouchableOpacity>

            {generatedInvoice && (
              <View style={styles.invoiceContainer}>
                <Text style={styles.label}>Invoice:</Text>
                <Text style={styles.invoice} selectable>
                  {generatedInvoice}
                </Text>
                {/* {receiveFeeSats !== null && (
                  <Text style={styles.feeText}>
                    Fee: {receiveFeeSats.toString()} sats
                  </Text>
                )} */}
              </View>
            )}
          </View>
        )}

        {/* Send Payment Section */}
        {sdk && (
          <View style={styles.section}>
            <Text style={styles.sectionTitle}>Send Payment</Text>
            <TextInput
              style={[styles.input, styles.textArea]}
              placeholder="Paste Lightning invoice (bolt11)"
              placeholderTextColor="#9CA3AF"
              value={paymentRequest}
              onChangeText={setPaymentRequest}
              multiline
            />
            <TextInput
              style={styles.input}
              placeholder="Amount (sats) - optional"
              placeholderTextColor="#9CA3AF" // gray, change as needed
              value={sendAmount}
              onChangeText={setSendAmount}
              keyboardType="number-pad"
            />
            <TouchableOpacity onPress={preparePayment} style={styles.button}>
              <Text style={styles.buttonText}>Prepare & Send Payment</Text>
            </TouchableOpacity>
          </View>
        )}

        {/* Events Section */}
        {events.length > 0 && (
          <View style={styles.section}>
            <Text style={styles.sectionTitle}>
              Recent Events ({events.length})
            </Text>
            {events.map((item, idx) => (
              <View key={idx} style={styles.eventItem}>
                <Text style={styles.eventTime}>{item.timestamp}</Text>
                <Text style={styles.eventText}>
                  {JSON.stringify(item.event, null, 2)}
                </Text>
              </View>
            ))}
          </View>
        )}

        {/* Payments History */}
        {payments.length > 0 && (
          <View style={styles.section}>
            <Text style={styles.sectionTitle}>
              Payment History ({payments.length})
            </Text>
            {payments.slice(0, 5).map((payment, idx) => (
              <View key={idx} style={styles.paymentItem}>
                <Text style={styles.paymentAmount}>
                  {payment.amountSats?.toString() || 'N/A'} sats
                </Text>
                <Text style={styles.paymentStatus}>{payment.status}</Text>
              </View>
            ))}
          </View>
        )}
      </ScrollView>
    </SafeAreaView>
  );
}
function BreezSpark2() {
  const [sdk, setSdk] = useState(null);
  const [balance, setBalance] = useState(null);
  const [events, setEvents] = useState([]);
  const [listenerId, setListenerId] = useState(null);
  const [payments, setPayments] = useState([]);

  // For receiving payments
  const [invoiceDescription, setInvoiceDescription] = useState('');
  const [invoiceAmount, setInvoiceAmount] = useState('');
  const [generatedInvoice, setGeneratedInvoice] = useState('');
  const [receiveFeeSats, setReceiveFeeSats] = useState(null);

  // For sending payments
  const [paymentRequest, setPaymentRequest] = useState('');
  const [sendAmount, setSendAmount] = useState('');
  const [preparedPayment, setPreparedPayment] = useState(null);

  async function connectToSdk() {
    try {
      const mnemonic =''; // 9901 sats
      // const mnemonic = ''; //    10001
      let config = defaultConfig(Network.Regtest);
      config.apiKey ='';

      const baseDir = DocumentDirectoryPath.replace('file://', '');
      const workingDir = `${baseDir}breezSdkSpark`;

      //   const directoryPath = await getOrCreateDirectory('testing', workingDir);

      console.log('API Key configured:', !!config.apiKey);

      const seed = new Seed.Mnemonic({mnemonic});
      const connectedSdk = await connect({
        config,
        seed,
        storageDir: workingDir,
      });

      setSdk(connectedSdk);
      console.log('✅ Connected successfully!');

      // Start listening to events
      setupEventListener(connectedSdk);

      // Get initial balance
      await fetchBalance(connectedSdk);

      // Load payment history
      await fetchPayments(connectedSdk);
    } catch (err) {
      console.error('❌ Connection error:', err);
      Alert.alert('Connection Error', err.message);
    }
  }

  function setupEventListener(sdkInstance) {
    const eventListener = new JsEventListener(event => {
      setEvents(prev =>
        [{event, timestamp: new Date().toISOString()}, ...prev].slice(0, 10),
      );

      // Refresh balance on payment events
      if (
        event.type === 'paymentSucceeded' ||
        event.type === 'paymentReceived'
      ) {
        fetchBalance(sdkInstance);
        fetchPayments(sdkInstance);
      }
    });

    const id = sdkInstance.addEventListener(eventListener);
    setListenerId(id);
    console.log('Event listener registered:', id);
  }

  async function fetchBalance(sdkInstance = sdk) {
    if (!sdkInstance) return;

    try {
      const info = await sdkInstance.getInfo({});
      setBalance(info.balanceSats);
      console.log('Balance:', info.balanceSats);
    } catch (err) {
      console.error('Error fetching balance:', err);
      Alert.alert('Balance Error', err.message);
    }
  }

  async function fetchPayments(sdkInstance = sdk) {
    if (!sdkInstance) return;

    try {
      const response = await sdkInstance.listPayments({
        offset: undefined,
        limit: 20,
      });
      console.log('response=>', response);
      setPayments(response.payments);
      console.log('Payments loaded:', response.payments.length);
    } catch (err) {
      console.error('Error fetching payments:', err);
    }
  }

  async function generateInvoice() {
    if (!sdk) {
      Alert.alert('Error', 'SDK not connected');
      return;
    }

    try {
      const amountSats = invoiceAmount ? BigInt(invoiceAmount) : undefined;

      // NOTE vai invoice
      const response = await sdk.receivePayment({
        paymentMethod: new ReceivePaymentMethod.Bolt11Invoice({
          description: invoiceDescription || 'Payment',
          amountSats,
        }),
      });
      console.log('response=>', response);
      // NOTE vai btc address ub regtest
      // const response = await sdk.receivePayment({
      //   paymentMethod: new ReceivePaymentMethod.BitcoinAddress()
      // })

      console.log(`Payment Request: ${paymentRequest}`);
      setGeneratedInvoice(response.paymentRequest);
      setReceiveFeeSats(response.fee);
      console.log('Invoice generated:', response.paymentRequest);
      console.log('Receive fees:', response.fee);

      Alert.alert('Invoice Generated', 'Check the invoice field below');
    } catch (err) {
      console.error('Error generating invoice:', err);
      Alert.alert('Invoice Error', err.message);
    }
  }

  async function preparePayment() {
    if (!sdk || !paymentRequest) {
      Alert.alert('Error', 'SDK not connected or no payment request');
      return;
    }

    try {
      const amountSats = sendAmount ? BigInt(sendAmount) : undefined;
      console.log('paymentRequest: ', paymentRequest);
      console.log('amountSats: ', amountSats);
      const prepareResponse = await sdk.prepareSendPayment({
        paymentRequest,
        amountSats,
      });

      setPreparedPayment(prepareResponse);

      if (
        prepareResponse.paymentMethod instanceof SendPaymentMethod.Bolt11Invoice
      ) {
        const lightningFee =
          prepareResponse.paymentMethod.inner.lightningFeeSats;
        const sparkFee =
          prepareResponse.paymentMethod.inner.sparkTransferFeeSats;
        console.log('lightningFee=:', lightningFee);
        console.log('sparkFee=:', sparkFee);
        // Alert.alert(
        //   'Payment Prepared',
        //   `Lightning Fees: ${lightningFee} sats\nSpark Fees: ${
        //     sparkFee || 'N/A'
        //   } sats`,
        //   [
        //     {text: 'Cancel', style: 'cancel'},
        //     {text: 'Send Payment', onPress: () => sendPayment(prepareResponse)},
        //   ],
        // );
      }
    } catch (err) {
      console.error('Error preparing payment:', err);
      Alert.alert('Prepare Error', err.message);
    }
  }

  async function sendPayment(prepareResponse) {
    if (!sdk) return;

    try {
      const response = await sdk.sendPayment({
        prepareResponse,
      });

      console.log('Payment sent:', response);
      Alert.alert('Success', 'Payment sent successfully!');

      // Clear form and refresh
      setPaymentRequest('');
      setSendAmount('');
      setPreparedPayment(null);
      await fetchBalance();
      await fetchPayments();
    } catch (err) {
      console.error('Error sending payment:', err);
      Alert.alert('Send Error', err.message);
    }
  }

  useEffect(() => {
    return () => {
      if (sdk && listenerId) {
        sdk.removeEventListener(listenerId);
      }
    };
  }, [sdk, listenerId]);

  console.log('receiveFeeSats=>', receiveFeeSats);
  return (
    <SafeAreaView style={styles.container}>
      <ScrollView style={styles.scrollView}>
        {/* Connection Section */}
        <View style={styles.section}>
          <TouchableOpacity
            onPress={connectToSdk}
            style={[styles.button, sdk && styles.buttonConnected]}
            disabled={!!sdk}>
            <Text style={styles.buttonText}>
              {sdk ? '✅ Connected' : 'Connect to Breez SDK'}
              {'\n'}
              {
                'soon provide struggle fitness dream emotion test cook wrestle price extra vapor'
              }
            </Text>
          </TouchableOpacity>

          {balance !== null && (
            <View style={styles.balanceContainer}>
              <Text style={styles.balanceLabel}>Balance:</Text>
              <Text style={styles.balanceAmount}>
                {balance.toString()} sats
              </Text>
              <TouchableOpacity
                onPress={() => fetchBalance()}
                style={styles.refreshButton}>
                <Text>🔄 Refresh</Text>
              </TouchableOpacity>
            </View>
          )}
        </View>

        {/* Receive Payment Section */}
        {sdk && (
          <View style={styles.section}>
            <Text style={styles.sectionTitle}>Receive Payment</Text>
            <TextInput
              style={styles.input}
              placeholder="Invoice description"
              placeholderTextColor="#9CA3AF"
              value={invoiceDescription}
              onChangeText={setInvoiceDescription}
            />
            <TextInput
              style={styles.input}
              placeholder="Amount (sats) - optional"
              placeholderTextColor="#9CA3AF"
              value={invoiceAmount}
              onChangeText={setInvoiceAmount}
              keyboardType="number-pad"
            />
            <TouchableOpacity onPress={generateInvoice} style={styles.button}>
              <Text style={styles.buttonText}>Generate Invoice</Text>
            </TouchableOpacity>

            {generatedInvoice && (
              <View style={styles.invoiceContainer}>
                <Text style={styles.label}>Invoice:</Text>
                <Text style={styles.invoice} selectable>
                  {generatedInvoice}
                </Text>
                {/* {receiveFeeSats !== null && (
                  <Text style={styles.feeText}>
                    Fee: {receiveFeeSats.toString()} sats
                  </Text>
                )} */}
              </View>
            )}
          </View>
        )}

        {/* Send Payment Section */}
        {sdk && (
          <View style={styles.section}>
            <Text style={styles.sectionTitle}>Send Payment</Text>
            <TextInput
              style={[styles.input, styles.textArea]}
              placeholder="Paste Lightning invoice (bolt11)"
              placeholderTextColor="#9CA3AF"
              value={paymentRequest}
              onChangeText={setPaymentRequest}
              multiline
            />
            <TextInput
              style={styles.input}
              placeholder="Amount (sats) - optional"
              placeholderTextColor="#9CA3AF" // gray, change as needed
              value={sendAmount}
              onChangeText={setSendAmount}
              keyboardType="number-pad"
            />
            <TouchableOpacity onPress={preparePayment} style={styles.button}>
              <Text style={styles.buttonText}>Prepare & Send Payment</Text>
            </TouchableOpacity>
          </View>
        )}

        {/* Events Section */}
        {events.length > 0 && (
          <View style={styles.section}>
            <Text style={styles.sectionTitle}>
              Recent Events ({events.length})
            </Text>
            {events.map((item, idx) => (
              <View key={idx} style={styles.eventItem}>
                <Text style={styles.eventTime}>{item.timestamp}</Text>
                <Text style={styles.eventText}>
                  {JSON.stringify(item.event, null, 2)}
                </Text>
              </View>
            ))}
          </View>
        )}

        {/* Payments History */}
        {payments.length > 0 && (
          <View style={styles.section}>
            <Text style={styles.sectionTitle}>
              Payment History ({payments.length})
            </Text>
            {payments.slice(0, 5).map((payment, idx) => (
              <View key={idx} style={styles.paymentItem}>
                <Text style={styles.paymentAmount}>
                  {payment.amountSats?.toString() || 'N/A'} sats
                </Text>
                <Text style={styles.paymentStatus}>{payment.status}</Text>
              </View>
            ))}
          </View>
        )}
      </ScrollView>
    </SafeAreaView>
  );
}
const renderScene = SceneMap({
  add_coins: BreezSpark1,
  add_coins_group: BreezSpark2,
});

export default function BreezSpark() {
  const [routes] = React.useState(ROUTES);
  const [index, setIndex] = React.useState(0);
  return (
    <View style={{flex: 1, marginTop: 50}}>
      <TabView
        navigationState={{index, routes}}
        renderScene={renderScene}
        onIndexChange={setIndex}
        initialLayout={{width: SCREEN_WIDTH}}
        renderTabBar={props => <RenderTabBar {...props} styles={styles} />}
        lazy={true}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f5f5f5',
  },
  scrollView: {
    flex: 1,
    padding: 16,
  },
  section: {
    backgroundColor: 'white',
    borderRadius: 12,
    padding: 16,
    marginBottom: 16,
    shadowColor: '#000',
    shadowOffset: {width: 0, height: 2},
    shadowOpacity: 0.1,
    shadowRadius: 4,
    elevation: 3,
  },
  sectionTitle: {
    fontSize: 18,
    fontWeight: 'bold',
    marginBottom: 12,
    color: '#333',
  },
  button: {
    backgroundColor: '#007AFF',
    padding: 16,
    borderRadius: 8,
    alignItems: 'center',
  },
  buttonConnected: {
    backgroundColor: '#34C759',
  },
  buttonText: {
    color: 'white',
    fontSize: 16,
    fontWeight: '600',
  },
  balanceContainer: {
    marginTop: 16,
    padding: 16,
    backgroundColor: '#f8f8f8',
    borderRadius: 8,
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
  },
  balanceLabel: {
    fontSize: 16,
    color: '#666',
  },
  balanceAmount: {
    fontSize: 20,
    fontWeight: 'bold',
    color: '#007AFF',
    flex: 1,
    marginLeft: 8,
  },
  refreshButton: {
    padding: 8,
  },
  input: {
    borderWidth: 1,
    borderColor: '#ddd',
    borderRadius: 8,
    padding: 12,
    marginBottom: 12,
    fontSize: 16,
  },
  textArea: {
    height: 80,
    textAlignVertical: 'top',
  },
  invoiceContainer: {
    marginTop: 12,
    padding: 12,
    backgroundColor: '#f8f8f8',
    borderRadius: 8,
  },
  label: {
    fontSize: 14,
    fontWeight: '600',
    marginBottom: 8,
    color: '#666',
  },
  invoice: {
    fontSize: 12,
    color: '#333',
    fontFamily: 'monospace',
  },
  feeText: {
    marginTop: 8,
    fontSize: 14,
    color: '#666',
  },
  eventItem: {
    padding: 12,
    backgroundColor: '#f8f8f8',
    borderRadius: 8,
    marginBottom: 8,
  },
  eventTime: {
    fontSize: 12,
    color: '#666',
    marginBottom: 4,
  },
  eventText: {
    fontSize: 12,
    fontFamily: 'monospace',
    color: '#333',
  },
  paymentItem: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    padding: 12,
    backgroundColor: '#f8f8f8',
    borderRadius: 8,
    marginBottom: 8,
  },
  paymentAmount: {
    fontSize: 16,
    fontWeight: '600',
    color: '#333',
  },
  paymentStatus: {
    fontSize: 14,
    color: '#666',
  },
});

Enter fullscreen mode Exit fullscreen mode

BTC lightning with transaction confirmation


import {Alert} from 'react-native';
import {
  connect,
  defaultConfig,
  Network,
  Seed,
  ReceivePaymentMethod,
  SendPaymentMethod,
  SendPaymentMethod_Tags,
} from '@breeztech/breez-sdk-spark-react-native';
import {config, IS_SANDBOX} from 'dok-wallet-blockchain-networks/config/config';

import {DocumentDirectoryPath} from 'react-native-fs';
import BigNumber from 'bignumber.js';
import {rejects} from 'assert';
class JsEventListener {
  constructor(callback) {
    this.callback = callback;
  }

  onEvent = event => {
    // console.log(`Received event: ${JSON.stringify(event)}`);
    if (this.callback) {
      this.callback(event);
    }
  };
}

let sdkInstance = null;
let connectingPromise = null;
let prepareSendResponse;
let receiverFees;
export const BitcoinLightningChain = ({mnemonic}) => {
  async function connectToSdk() {
    // ✅ Already connected
    if (sdkInstance) {
      return sdkInstance;
    }

    // ✅ Connection already in progress
    if (connectingPromise) {
      return connectingPromise;
    }

    connectingPromise = (async () => {
      try {
        let config = defaultConfig(Network.Regtest);
        config.apiKey = process.env.BREEZ_API_KEY;

        const baseDir = DocumentDirectoryPath.replace('file://', '');
        const workingDir = `${baseDir}breezSdkSpark`;

        const seed = new Seed.Mnemonic({mnemonic});

        console.log('🔌 Connecting to Breez SDK...');
        sdkInstance = await connect({
          config,
          seed,
          storageDir: workingDir,
        });

        console.log('✅ Breez SDK connected');
        return sdkInstance;
      } catch (err) {
        console.error('❌ Connection error:', err);
        sdkInstance = null;
        connectingPromise = null;
        throw err;
      }
    })();

    return connectingPromise;
  }

  async function getBalance() {
    const sdk = await connectToSdk();

    const info = await sdk.getInfo({});
    console.log('Balance:', info.balanceSats);
    return info.balanceSats;
  }

  async function isValidAddress({address}) {
    return true;
  }
  // NOTE: fetch payments
  async function fetchPayments() {
    const sdk = await connectToSdk();
    if (!sdk) return;

    try {
      const response = await sdk.listPayments({
        offset: undefined,
        limit: 20,
      });
      console.log('Payments loaded:', response.payments.length);
      return {
        paymentDetails: response.payments,
      };
    } catch (err) {
      console.error('Error fetching payments:', err);
      Alert.alert('payment fetch Error', err.message);
    }
  }

  // NOTE: generate invoice
  async function generateInvoiceViaBolt11() {
    const sdk = await connectToSdk();
    if (!sdk) {
      Alert.alert('Error', 'SDK not connected');
      return;
    }
    // if (invoiceGenerated) return;
    // invoiceGenerated = true;

    try {
      // const amountSats = invoiceAmount ? BigInt(invoiceAmount) : undefined;

      const response = await sdk.receivePayment({
        paymentMethod: new ReceivePaymentMethod.Bolt11Invoice({
          // description: invoiceDescription || 'Payment',
          description: 'Payment',
          // amountSats,
        }),
      });

      // console.log('Invoice generated:', response.paymentRequest);
      // console.log('Receive fees:', response.fee);
      // Alert.alert('Invoice Generated', 'Check the invoice field below');
      return {
        address: response.paymentRequest,
        receiveFeeSats: response.fee,
      };
    } catch (err) {
      console.error('Error generating invoice:', err);
      Alert.alert('Invoice Error', err.message);
    }
  }

  // NOTE: generate invoice via bitcoin address
  async function generateInvoiceViaBitcoinAddress() {
    const sdk = await connectToSdk();
    if (!sdk) {
      Alert.alert('Error', 'SDK not connected');
      return;
    }

    try {
      // const amountSats = invoiceAmount ? BigInt(invoiceAmount) : undefined;

      // NOTE vai btc address ub regtest
      const response = await sdk.receivePayment({
        paymentMethod: new ReceivePaymentMethod.BitcoinAddress(),
      });

      console.log('Invoice generated:', response.paymentRequest);
      console.log('Receive fees:', response.fee);
      receiverFees = response.fee;
      return {
        address: response.paymentRequest,
        receiveFeeSats: response.fee,
      };
    } catch (err) {
      console.error('Error generating invoice:', err);
      Alert.alert('Invoice Error', err.message);
    }
  }

  // NOTE: prepare payment and send payment
  async function prepareAndSendPayment(paymentRequest, amountSats) {
    const sdk = await connectToSdk();
    if (!sdk || !paymentRequest) {
      Alert.alert('Error', 'SDK not connected or no payment request');
      return;
    }

    try {
      const prepareResponse = await sdk.prepareSendPayment({
        paymentRequest,
        amountSats,
      });

      prepareSendResponse = prepareResponse;
      if (
        prepareResponse.paymentMethod instanceof SendPaymentMethod.Bolt11Invoice
      ) {
        const lightningFee =
          prepareResponse.paymentMethod.inner.lightningFeeSats;
        const sparkFee =
          prepareResponse.paymentMethod.inner.sparkTransferFeeSats;

        return {
          lightningFee: lightningFee,
          sparkFee: sparkFee,
        };
      }
      return {};
    } catch (err) {
      console.error('Error preparing payment:', err);
      Alert.alert('Prepare Error', err.message);
    }
  }

  function btcToSatoshi(btc) {
    if (btc === null || btc === undefined) return 0;
    return BigInt(Math.round(Number(btc) * 100_000_000));
  }
  function satoshiToBtc(sats) {
    if (sats === null || sats === undefined) return 0;

    // Handle BigInt or number or string safely
    const satsNumber = typeof sats === 'bigint' ? Number(sats) : Number(sats);

    return satsNumber / 100_000_000;
  }
  // {
  //     "fee": "0.00059502",
  //     "estimateGas": 141,
  //     "feesOptions": [
  //         {
  //             "title": "Recommended",
  //             "gasPrice": 422
  //         },
  //         {
  //             "title": "Normal",
  //             "gasPrice": 358
  //         }
  //     ]
  // }
  async function getEstimateFee({
    fromAddress,
    toAddress,
    amount,
    privateKey,
    chain_name,
    deriveAddresses,
    balance,
    extendedPrivateKey,
    feeMultiplier,
    estimateGas: virtualSize,
    feesType,
    selectedUTXOs,
  }) {
    try {
      const amountSats = btcToSatoshi(amount);

      const {lightningFee} = await prepareAndSendPayment(toAddress, amountSats);
      const fee = satoshiToBtc(lightningFee);
      return {
        fee: fee,
        estimateGas: 0,
        feesOptions: [],
      };
    } catch (error) {
      console.error('Error in bitcoin gas fee', error);
      throw error;
    }
  }
  async function send({
    to,
    from,
    amount,
    privateKey,
    transactionFee,
    chain_name,
    deriveAddresses,
    balance,
    extendedPrivateKey,
    selectedUTXOs,
  }) {
    try {
      const amountToSend = new BigNumber(amount);
      const sdk = await connectToSdk();
      if (!sdk || !prepareSendResponse) {
        Alert.alert('Error', 'SDK not connected or no payment request');
        return;
      }
      // If the fees are acceptable, continue to send the token payment
      if (
        prepareSendResponse.paymentMethod?.tag ===
        SendPaymentMethod_Tags.SparkAddress
      ) {
        console.log(
          `Token ID: ${prepareSendResponse.paymentMethod.inner.tokenIdentifier}`,
        );
        console.log(
          `Fees: ${prepareSendResponse.paymentMethod.inner.fee} token base units`,
        );
      }
      if (
        prepareSendResponse.paymentMethod?.tag ===
        SendPaymentMethod_Tags.SparkInvoice
      ) {
        console.log(
          `Token ID: ${prepareSendResponse.paymentMethod.inner.tokenIdentifier}`,
        );
        console.log(
          `Fees: ${prepareSendResponse.paymentMethod.inner.fee} token base units`,
        );
      }

      // Send the token payment
      const sendResponse = await sdk.sendPayment({
        prepareResponse: prepareSendResponse,
        options: undefined,
        idempotencyKey: undefined,
      });
      const payment = sendResponse.payment;
      console.log('payment=>', payment);
      return payment.details.inner.paymentHash;
    } catch (error) {
      console.error('Error in bitcoin gas fee', error);
      throw error;
    }
  }
  async function waitForConfirmation({transaction}) {
    const transactionID = transaction;
    console.log('transactionID:', transactionID);

    const sdk = await connectToSdk();

    if (!sdk) {
      Alert.alert('Error', 'SDK not connected');
      return;
    }

    return new Promise(async (resolve, reject) => {
      let listenerId = null;
      let timeoutId = null;
      let resolved = false;

      try {
        const eventListener = new JsEventListener(async event => {
          console.log('event:', event);

          if (resolved) return;

          if (event.tag === 'PaymentSucceeded') {
            resolved = true;

            // 🧹 cleanup
            if (listenerId !== null) {
              sdk.removeEventListener(listenerId);
            }
            if (timeoutId) {
              clearTimeout(timeoutId);
            }

            resolve(true);
          }
        });

        listenerId = await sdk.addEventListener(eventListener);
        console.log('Event listener registered:', listenerId);

        // ⏱️ 90 seconds timeout
        timeoutId = setTimeout(() => {
          if (resolved) return;

          resolved = true;

          console.log('⏱️ Payment confirmation timeout (90s)');

          // 🧹 cleanup
          if (listenerId !== null) {
            sdk.removeEventListener(listenerId);
          }

          resolve('pending');
        }, 90_000); // 90 seconds
      } catch (error) {
        console.error('Error in waitForConfirmation:', error);

        // 🧹 cleanup
        if (listenerId !== null) {
          sdk.removeEventListener(listenerId);
        }
        if (timeoutId) {
          clearTimeout(timeoutId);
        }

        reject(error);
      }
    });
  }

  // async function setupEventListener() {
  //   const sdk = await connectToSdk();
  //   if (!sdk || !prepareSendResponse) {
  //     Alert.alert('Error', 'SDK not connected or no payment request');
  //     return;
  //   }
  //   const eventListener = new JsEventListener(event => {
  //     // Refresh balance on payment events
  //     if (
  //       event.type === 'paymentSucceeded' ||
  //       event.type === 'paymentReceived'
  //     ) {
  //       // fetchBalance(sdkInstance);
  //       // fetchPayments(sdkInstance);
  //       console.log("=========PAYMENT SUCCESSFULL===========")
  //     }
  //   });

  //   const id = sdkInstance.addEventListener(eventListener);
  //   // setListenerId(id);
  //   console.log('Event listener registered:', id);
  // }

  return {
    connectToSdk,
    getBalance,
    isValidAddress,
    fetchPayments,
    generateInvoiceViaBolt11,
    generateInvoiceViaBitcoinAddress,
    prepareAndSendPayment,
    getEstimateFee,
    send,
    waitForConfirmation,
  };
};

Enter fullscreen mode Exit fullscreen mode

Top comments (0)