import { ToExtension , ToApplication , } from "@substrate/connect-extension-protocol" ; import { debug } from "../utils/debug" ; const CONTENT_SCRIPT_ORIGIN = "content-script" ; const EXTENSION_PROVIDER_ORIGIN = "extension-provider" ; const sendMessage = ( msg ) : void => { window . postMessage ( msg , "*" ) ; } ; export class ExtensionMessageRouter { #ports : Record < string , chrome . runtime . Port > = { } ; returns get connections ( ) : string [ ] { return Object . keys ( this . #ports ) ; } /** listen starts listening for messages sent by an app.  */ listen ( ) { window . addEventListener ( "message" , this . #handleMessage ) ; } /** stop stops listening for messages sent by apps.  */ stop ( ) { window . removeEventListener ( "message" , this . #handleMessage ) ; } #establishNewConnection = ( chainId , chainName ) : void => { const port = chrome . runtime . connect ( { name : `${ window . location . href }::${ chainName }` , } ) ; debug ( `CONNECTED ${ chainName } PORT` , port ) ; port . onMessage . addListener ( ( data ) : void => { const { type , payload } = data ; debug ( `RECEIVED MESSAGE FROM ${ chainName } PORT` , data ) ; sendMessage ( { type , payload , chainId , origin : CONTENT_SCRIPT_ORIGIN , } ) ; } ) ; port . onDisconnect . addListener ( ( ) => { sendMessage ( { origin : "content-script" , chainId , type : "error" , payload : "Lost communication with substrate-connect extension" , } ) ; delete this . #ports [ chainId ] ; } ) ; this . #ports [ chainId ] = port ; debug ( `CONNECTED TO ${ chainName } PORT` ) ; } ; #forwardRpcMessage = ( { chainId , type , payload , parachainPayload , } ) : void => { const port = this . #ports [ chainId ] ; if ( ! port ) { console . warn ( `App requested to send message to ${ chainId } - no port found` ) ; return ; } const msg = { type , payload , parachainPayload } ; debug ( `SENDING RPC MESSAGE TO ${ chainId } PORT` , msg ) ; port . postMessage ( msg ) ; } ; #handleMessage = ( msg ) : void => { const data = msg . data ; const { origin , type } = data ; if ( ! origin || origin !== EXTENSION_PROVIDER_ORIGIN ) { return ; } debug ( `RECEIVED MESSAGE FROM ${ EXTENSION_PROVIDER_ORIGIN }` , data ) ; if ( type !== "rpc" && type !== "add-chain" && type !== "add-well-known-chain" ) { console . warn ( "Malformed message - unrecognised message.type" , data ) ; return ; } if ( type === "add-well-known-chain" ) { this . #establishNewConnection ( data . chainId , data . payload ) ; } if ( type === "add-chain" ) { let name = "unknown name" ; try { name = JSON . parse ( data . payload ) . name || name ; } catch ( _ ) { sendMessage ( { origin : "content-script" , chainId : data . chainId , type : "error" , payload : "Error parsing relayChain spec" , } ) ; console . warn ( "Error parsing relayChain spec" , data ) ; return ; } this . #establishNewConnection ( data . chainId , name ) ; } return this . #forwardRpcMessage ( data ) ; } ; }