import { ShortChannelId } from "@node-lightning/core" ; import { ILogger } from "@node-lightning/logger" ; import { QueryShortChannelIdsMessage } from "../messages/QueryShortChannelIdsMessage" ; import { ReplyShortChannelIdsEndMessage } from "../messages/ReplyShortChannelIdsEndMessage" ; import { IMessageSender } from "../Peer" ; import { GossipError , GossipErrorCode } from "./GossipError" ; export enum ChannelsQueryState { Idle , Active , Complete , Failed } /**
 * This class manages the state machine for executing query_short_channel_ids
 * and will resolve as either complete or with an error. This class can accept
 * an arbitrarily large number of short channel ids and will chunk the requests
 * appropriately.
 */ export class ChannelsQuery { public chunkSize = 2000 ; private _queue : ShortChannelId [ ] = [ ] ; private _state : ChannelsQueryState ; private _error : GossipError ; private _resolve : ( ) => void ; private _reject : ( error : GossipError ) => void ; constructor ( readonly chainHash , readonly peer , readonly logger ) { this . _state = ChannelsQueryState . Idle ; } public get state ( ) : ChannelsQueryState { return this . _state ; } public get error ( ) : Error { return this . _error ; } public handleReplyShortChannelIdsEnd ( msg ) { this . logger . debug ( "received reply_short_channel_ids_end - complete: %d" , msg . complete ) ; if ( ! msg . complete ) { const error = new GossipError ( GossipErrorCode . ReplyChannelsNoInfo , msg ) ; this . _transitionFailed ( error ) ; return ; } if ( this . _queue . length > 0 ) { this . _sendQuery ( ) ; } else { this . _transitionSuccess ( ) ; return ; } } param scids public query ( ... scids ) { return new Promise ( ( resolve , reject ) => { for ( const scid of scids ) { this . _queue . push ( scid ) ; } this . _state = ChannelsQueryState . Active ; this . _sendQuery ( ) ; this . _resolve = resolve ; this . _reject = reject ; } ) ; } private _transitionSuccess ( ) { if ( this . _state !== ChannelsQueryState . Active ) return ; this . _state = ChannelsQueryState . Complete ; this . _resolve ( ) ; } private _transitionFailed ( error ) { if ( this . _state !== ChannelsQueryState . Active ) return ; this . _state = ChannelsQueryState . Failed ; this . _error = error ; this . _reject ( error ) ; } private _sendQuery ( ) { const scids = this . _queue . splice ( 0 , this . chunkSize ) ; const msg = new QueryShortChannelIdsMessage ( ) ; msg . chainHash = this . chainHash ; msg . shortChannelIds = scids ; this . logger . debug ( "sending query_short_channel_ids - scid_count:" , scids . length ) ; this . peer . sendMessage ( msg ) ; } }