@@ -22,11 +22,18 @@ const {
2222
2323interface AliasCache {
2424 lastUpdated : number ;
25+ /** mapping from remove pubkey to alias */
2526 aliases : Record < string , string > ;
2627}
2728
29+ interface FeeCache {
30+ lastUpdated : number ;
31+ /** mapping form channel id to fee rate */
32+ feeRates : Record < string , number > ;
33+ }
34+
2835/** cache alias data for 24 hours */
29- const ALIAS_CACHE_TIMEOUT = 24 * 60 * 60 * 1000 ;
36+ const CACHE_TIMEOUT = 24 * 60 * 60 * 1000 ;
3037
3138export default class ChannelStore {
3239 private _store : Store ;
@@ -103,6 +110,8 @@ export default class ChannelStore {
103110 this . _store . log . info ( 'updated channelStore.channels' , toJS ( this . channels ) ) ;
104111 // fetch the aliases for each of the channels
105112 this . fetchAliases ( ) ;
113+ // fetch the remote fee rates for each of the channels
114+ this . fetchFeeRates ( ) ;
106115 } ) ;
107116 } catch ( error ) {
108117 this . _store . uiStore . handleError ( error , 'Unable to fetch Channels' ) ;
@@ -129,7 +138,7 @@ export default class ChannelStore {
129138
130139 // look up cached data in storage
131140 let cachedAliases = this . _store . storage . get < AliasCache > ( 'aliases' ) ;
132- if ( cachedAliases && cachedAliases . lastUpdated > Date . now ( ) - ALIAS_CACHE_TIMEOUT ) {
141+ if ( cachedAliases && cachedAliases . lastUpdated > Date . now ( ) - CACHE_TIMEOUT ) {
133142 // there is cached data and it has not expired
134143 aliases = cachedAliases . aliases ;
135144 // exclude pubkeys which we have aliases for already
@@ -162,11 +171,75 @@ export default class ChannelStore {
162171 runInAction ( 'fetchAliasesContinuation' , ( ) => {
163172 // set the alias on each channel in the store
164173 values ( this . channels ) . forEach ( c => {
165- if ( aliases [ c . remotePubkey ] ) {
166- c . alias = aliases [ c . remotePubkey ] ;
174+ const alias = aliases [ c . remotePubkey ] ;
175+ if ( alias ) {
176+ c . alias = alias ;
177+ this . _store . log . info ( `updated channel ${ c . chanId } with alias ${ alias } ` ) ;
178+ }
179+ } ) ;
180+ } ) ;
181+ }
182+
183+ /**
184+ * queries the LND api to fetch the fees for all of the peers we have
185+ * channels opened with
186+ */
187+ @action . bound
188+ async fetchFeeRates ( ) {
189+ this . _store . log . info ( 'fetching fees for channels' ) ;
190+ // create an array of all channel ids
191+ let chanIds = values ( this . channels )
192+ . map ( c => c . chanId )
193+ . filter ( ( r , i , a ) => a . indexOf ( r ) === i ) ; // remove duplicates
194+
195+ // create a map of chan id to fee rate
196+ let feeRates : Record < string , number > = { } ;
197+
198+ // look up cached data in storage
199+ let cachedFees = this . _store . storage . get < FeeCache > ( 'fee-rates' ) ;
200+ if ( cachedFees && cachedFees . lastUpdated > Date . now ( ) - CACHE_TIMEOUT ) {
201+ // there is cached data and it has not expired
202+ feeRates = cachedFees . feeRates ;
203+ // exclude chanIds which we have feeRates for already
204+ chanIds = chanIds . filter ( id => ! feeRates [ id ] ) ;
205+ this . _store . log . info ( `found feeRates in cache. ${ chanIds . length } missing` , chanIds ) ;
206+ }
207+
208+ // if there are any chanIds that we do not have a cached fee rate for
209+ if ( chanIds . length ) {
210+ // call getNodeInfo for each chan id and wait for all the requests to complete
211+ const chanInfos = await Promise . all (
212+ chanIds . map ( id => this . _store . api . lnd . getChannelInfo ( id ) ) ,
213+ ) ;
214+
215+ // add fetched feeRates to the mapping
216+ feeRates = chanInfos . reduce ( ( acc , info ) => {
217+ const { channelId, node1Pub, node1Policy, node2Policy } = info ;
218+ const localPubkey = this . _store . nodeStore . pubkey ;
219+ const policy = node1Pub === localPubkey ? node2Policy : node1Policy ;
220+ if ( policy ) {
221+ acc [ channelId ] = + Big ( policy . feeRateMilliMsat ) . div ( 1000000 ) . mul ( 100 ) ;
222+ }
223+ return acc ;
224+ } , feeRates ) ;
225+
226+ // save updated feeRates to the cache in storage
227+ cachedFees = {
228+ lastUpdated : Date . now ( ) ,
229+ feeRates,
230+ } ;
231+ this . _store . storage . set ( 'fee-rates' , cachedFees ) ;
232+ this . _store . log . info ( `updated cache with ${ chanIds . length } new feeRates` ) ;
233+ }
234+
235+ runInAction ( 'fetchFeesContinuation' , ( ) => {
236+ // set the fee on each channel in the store
237+ values ( this . channels ) . forEach ( c => {
238+ if ( feeRates [ c . chanId ] ) {
239+ c . remoteFeeRate = feeRates [ c . chanId ] ;
167240 }
168241 } ) ;
169- this . _store . log . info ( 'updated channels with aliases ' , toJS ( this . channels ) ) ;
242+ this . _store . log . info ( 'updated channels with feeRates ' , toJS ( this . channels ) ) ;
170243 } ) ;
171244 }
172245
@@ -206,6 +279,8 @@ export default class ChannelStore {
206279 this . _store . nodeStore . fetchBalancesThrottled ( ) ;
207280 // fetch the alias for the added channel
208281 this . fetchAliases ( ) ;
282+ // fetch the remote fee rates for the added channel
283+ this . fetchFeeRates ( ) ;
209284 }
210285 }
211286
0 commit comments