@@ -70,6 +70,7 @@ import {
7070import * as bitcoin from 'bitcoinjs-lib' ;
7171import networks from './utils/networks' ;
7272import { EmitterSubscription } from 'react-native' ;
73+ import decodeRawTx from '@synonymdev/raw-transaction-decoder' ;
7374
7475const MAX_PENDING_PAY_AGE = 1000 * 60 * 60 ; // 1 hour
7576
@@ -125,6 +126,7 @@ class LightningManager {
125126 address : '' ,
126127 publicKey : '' ,
127128 } ) ;
129+ addresses : string [ ] = [ ] ;
128130 getScriptPubKeyHistory : TGetScriptPubKeyHistory = async ( ) : Promise <
129131 TGetScriptPubKeyHistoryResponse [ ]
130132 > => [ ] ;
@@ -360,7 +362,15 @@ class LightningManager {
360362 this . getBestBlock = getBestBlock ;
361363 this . account = account ;
362364 this . network = network ;
363- this . getAddress = getAddress ;
365+ this . addresses = await this . readAddressesFromFile ( ) ;
366+ this . getAddress = async ( ) => {
367+ const addressObj = await getAddress ( ) ;
368+ const address = addressObj ?. address ;
369+ if ( address ) {
370+ this . saveAddressToFile ( address ) . then ( ) ;
371+ }
372+ return addressObj ;
373+ } ;
364374 this . getScriptPubKeyHistory = getScriptPubKeyHistory ;
365375 this . getFees = getFees ;
366376 this . broadcastTransaction = broadcastTransaction ;
@@ -797,6 +807,39 @@ class LightningManager {
797807 return ok ( 'Watch transactions checked' ) ;
798808 } ;
799809
810+ saveAddressToFile = async ( address : string ) : Promise < Result < boolean > > => {
811+ if ( ! address ) {
812+ return err ( 'No address provided' ) ;
813+ }
814+ if ( this . addresses . includes ( address ) ) {
815+ return ok ( true ) ;
816+ }
817+ this . addresses . push ( address ) ;
818+ const accountPath = appendPath ( this . baseStoragePath , this . account . name ) ;
819+ const writeRes = await ldk . writeToFile ( {
820+ fileName : ELdkFiles . addresses ,
821+ path : accountPath ,
822+ content : JSON . stringify ( this . addresses ) ,
823+ remotePersist : true ,
824+ } ) ;
825+ if ( writeRes . isErr ( ) ) {
826+ return err ( writeRes . error . message ) ;
827+ }
828+ return ok ( true ) ;
829+ } ;
830+
831+ readAddressesFromFile = async ( ) : Promise < string [ ] > => {
832+ const accountPath = appendPath ( this . baseStoragePath , this . account . name ) ;
833+ const writeRes = await ldk . readFromFile ( {
834+ fileName : ELdkFiles . addresses ,
835+ path : accountPath ,
836+ } ) ;
837+ if ( writeRes . isOk ( ) ) {
838+ return parseData ( writeRes . value . content , [ ] ) ;
839+ }
840+ return [ ] ;
841+ } ;
842+
800843 /**
801844 * Saves confirmed watch outputs to storage.
802845 * @param {string } confirmedWatchOutput
@@ -871,25 +914,89 @@ class LightningManager {
871914 transactionData ?. vout [ index ] . hex ,
872915 ) ;
873916
874- if ( txs . length < 1 ) {
917+ if ( txs . length <= 1 ) {
875918 continue ;
876919 }
877920
878- // TODO: Implement index fix
879- const tx = txs [ 1 ] ;
880- if ( ! tx ?. txid ) {
881- continue ;
921+ // Used for older versions that have not previously tracked addresses.
922+ const fallbackIndex = 1 ;
923+ const fallbackTx = txs [ fallbackIndex ] ;
924+ let useFallback = true ;
925+
926+ const txsLength = txs . length - 1 ;
927+ let transactionId : string | undefined ;
928+ let txData : TTransactionData | undefined ;
929+ let fallbackTxData : TTransactionData | undefined ;
930+ for ( let i = txsLength ; i >= 0 ; i -- ) {
931+ await sleep ( 100 ) ;
932+
933+ const tx = txs [ i ] ;
934+ if ( ! tx ?. txid ) {
935+ continue ;
936+ }
937+
938+ const txDataRes = await this . getTransactionData ( tx . txid ) ;
939+ if ( ! txDataRes || ! txDataRes ?. height || ! txDataRes ?. transaction ) {
940+ if ( ! txDataRes ) {
941+ console . error ( 'No txDataRes' ) ;
942+ }
943+ continue ;
944+ }
945+
946+ if ( i === fallbackIndex ) {
947+ // Set fallbackTxData data to prevent calling getTransactionData again.
948+ fallbackTxData = txDataRes ;
949+ }
950+
951+ const decodedTxRes = decodeRawTx ( txDataRes ?. transaction ) ;
952+ if ( decodedTxRes . isErr ( ) ) {
953+ console . error (
954+ 'Error decoding transaction' ,
955+ decodedTxRes . error . message ,
956+ ) ;
957+ continue ;
958+ }
959+
960+ const decodedTx = decodedTxRes . value ;
961+ const decodedOutputs = decodedTx ?. outputs ?? [ ] ;
962+ let decodedAddresses : string [ ] = [ ] ;
963+ decodedOutputs . map ( ( o ) => {
964+ if ( o ?. scriptPubKey ?. addresses ) {
965+ decodedAddresses = decodedAddresses . concat (
966+ o . scriptPubKey . addresses ,
967+ ) ;
968+ }
969+ } ) ;
970+
971+ for ( const address of decodedAddresses ) {
972+ if ( this . addresses . includes ( address ) ) {
973+ transactionId = tx . txid ;
974+ txData = txDataRes ;
975+ useFallback = false ;
976+ break ;
977+ }
978+ }
979+ if ( transactionId && txData ) {
980+ break ;
981+ }
882982 }
883- const txData = await this . getTransactionData ( tx . txid ) ;
884- if ( ! txData ) {
885- //Watch Output was never confirmed so there's no need to unconfirm it.
886- continue ;
983+
984+ if ( useFallback ) {
985+ transactionId = fallbackTx ?. txid ;
986+ if ( ! transactionId ) {
987+ continue ;
988+ }
989+ txData =
990+ fallbackTxData ?? ( await this . getTransactionData ( transactionId ) ) ;
887991 }
888- if ( ! txData ?. height ) {
992+
993+ if ( ! transactionId || ! txData ?. height ) {
994+ // Transaction has either not entered the mempool yet or has zero confirmations. Try again later.
889995 continue ;
890996 }
997+
891998 const pos = await this . getTransactionPosition ( {
892- tx_hash : tx . txid ,
999+ tx_hash : transactionId ,
8931000 height : txData . height ,
8941001 } ) ;
8951002 if ( pos >= 0 ) {
@@ -901,7 +1008,7 @@ class LightningManager {
9011008 if ( setTxConfirmedRes . isOk ( ) ) {
9021009 await this . saveUnconfirmedTx ( {
9031010 ...txData ,
904- txid : tx . txid ,
1011+ txid : transactionId ,
9051012 script_pubkey,
9061013 } ) ;
9071014 await this . saveConfirmedWatchOutput ( script_pubkey ) ;
0 commit comments