import { Opcode } from "../../../src/engine" ; import { Deferred } from "../../../src/utils/deferred" ; import { MiniNode } from "./mininode" ; export class MessageRouter { private readonly nodesMap : Map < string , MiniNode > ; private readonly deferrals : Map < string , Deferred < any > > ; private readonly pendingPromises : Set < Promise < void > > ; constructor ( nodes ) { this . nodesMap = new Map ( ) ; this . deferrals = new Map ( ) ; this . pendingPromises = new Set ( ) ; for ( const node of nodes ) { this . nodesMap . set ( node . xpub , node ) ; node . protocolRunner . register ( Opcode . IO_SEND , ( args ) => { const [ message ] = args ; this . appendToPendingPromisesIfNotNull ( this . routeMessage ( message ) ) ; } ) ; node . protocolRunner . register ( Opcode . IO_SEND_AND_WAIT , async ( args ) => { const [ message ] = args ; message . fromXpub = node . xpub ; this . deferrals . set ( node . xpub , new Deferred ( ) ) ; this . appendToPendingPromisesIfNotNull ( this . routeMessage ( message ) ) ; const ret = await this . deferrals . get ( node . xpub ) ! . promise ; this . deferrals . delete ( node . xpub ) ; return ret ; } ) ; } } private appendToPendingPromisesIfNotNull ( v ) { if ( v === null ) return ; this . pendingPromises . add ( v ) ; } private routeMessage ( message ) { const { toXpub } = message ; if ( toXpub === undefined ) { throw Error ( "No toXpub found on message" ) ; } const deferred = this . deferrals . get ( toXpub ) ; if ( deferred === undefined ) { const toNode = this . nodesMap . get ( toXpub ) ; if ( toNode === undefined ) { throw Error ( `No node with xpub = ${ toXpub } found` ) ; } return toNode . dispatchMessage ( message ) ; } deferred . resolve ( message ) ; return null ; } public async waitForAllPendingPromises ( ) { await Promise . all ( this . pendingPromises ) ; if ( this . deferrals . size !== 0 ) { throw Error ( "Pending IO_SEND_AND_WAIT deferrals detected" ) ; } } }