import { request as http , setFetch as rSetFetch } from './http' ; import * as check from '../utils/highlevel-checks' ; import { semverCompare } from '../utils/semver-compare' ; import { buildOne } from '../lowlevel/send' ; import { parseConfigure } from '../lowlevel/protobuf/messages' ; import { receiveOne } from '../lowlevel/receive' ; import { DEFAULT_URL , DEFAULT_VERSION_URL } from '../config' ; import type { INamespace } from 'protobufjs/light' ; import type { AcquireInput , TrezorDeviceInfoWithSession } from '../types' ; type IncompleteRequestOptions = { body ? : Array < any > | Object | string ; url : string ; } ; export default class BridgeTransport { name = `BridgeTransport` ; version = `` ; isOutdated ? : boolean ; url : string ; newestVersionUrl : string ; bridgeVersion ? : string ; debug = false ; configured = false ; _messages : ReturnType < typeof parseConfigure > | undefined ; stopped = false ; constructor ( url ? , newestVersionUrl ? ) { this . url = url == null ? DEFAULT_URL : url ; this . newestVersionUrl = newestVersionUrl == null ? DEFAULT_VERSION_URL : newestVersionUrl ; } async _post ( options ) { if ( this . stopped ) { return Promise . reject ( `Transport stopped.` ) ; } return http ( { ... options , method : `POST` , url : this . url + options . url , skipContentTypeHeader : true , } ) ; } async init ( debug ) { this . debug = ! ! debug ; await this . _silentInit ( ) ; } async _silentInit ( ) { const infoS = await http ( { url : this . url , method : `POST` , } ) ; const info = check . info ( infoS ) ; this . version = info . version ; const newVersion = typeof this . bridgeVersion === `string` ? this . bridgeVersion : check . version ( await http ( { url : `${ this . newestVersionUrl }?${ Date . now ( ) }` , method : `GET` , } ) ) ; this . isOutdated = semverCompare ( this . version , newVersion ) < 0 ; } async configure ( signedData ) { const messages = parseConfigure ( signedData ) ; this . configured = true ; this . _messages = messages ; } async listen ( old ? ) { if ( old == null ) { throw new Error ( `Bridge v2 does not support listen without previous.` ) ; } const devicesS = await this . _post ( { url : `/listen` , body : old , } ) ; const devices = check . devices ( devicesS ) ; return devices ; } async enumerate ( ) { const devicesS = await this . _post ( { url : `/enumerate` } ) ; const devices = check . devices ( devicesS ) ; return devices ; } async _acquireMixed ( input , debugLink ) { const previousStr = input . previous == null ? `null` : input . previous ; const url = `${ debugLink ? `/debug` : `` }/acquire/${ input . path }/${ previousStr }` ; return this . _post ( { url } ) ; } async acquire ( input , debugLink ) { const acquireS = await this . _acquireMixed ( input , debugLink ) ; return check . acquire ( acquireS ) ; } async release ( session , onclose , debugLink ) { const res = this . _post ( { url : `${ debugLink ? `/debug` : `` }/release/${ session }` , } ) ; if ( onclose ) { return ; } await res ; } async call ( session , name , data , debugLink ) { if ( this . _messages == null ) { throw new Error ( `Transport not configured.` ) ; } const messages = this . _messages ; const o = buildOne ( messages , name , data ) ; const outData = o . toString ( `hex` ) ; const resData = await this . _post ( { url : `${ debugLink ? `/debug` : `` }/call/${ session }` , body : outData , } ) ; if ( typeof resData !== `string` ) { throw new Error ( `Returning data is not string.` ) ; } const jsonData = receiveOne ( messages , resData ) ; return check . call ( jsonData ) ; } async post ( session , name , data , debugLink ) { if ( this . _messages == null ) { throw new Error ( `Transport not configured.` ) ; } const messages = this . _messages ; const outData = buildOne ( messages , name , data ) . toString ( `hex` ) ; await this . _post ( { url : `${ debugLink ? `/debug` : `` }/post/${ session }` , body : outData , } ) ; } async read ( session , debugLink ) { if ( this . _messages == null ) { throw new Error ( `Transport not configured.` ) ; } const messages = this . _messages ; const resData = await this . _post ( { url : `${ debugLink ? `/debug` : `` }/read/${ session }` , } ) ; if ( typeof resData !== `string` ) { throw new Error ( `Returning data is not string.` ) ; } const jsonData = receiveOne ( messages , resData ) ; return check . call ( jsonData ) ; } static setFetch ( fetch , isNode ? ) { rSetFetch ( fetch , isNode ) ; } requestDevice ( ) { return Promise . reject ( ) ; } requestNeeded = false ; setBridgeLatestUrl ( url ) { this . newestVersionUrl = url ; } setBridgeLatestVersion ( version ) { this . bridgeVersion = version ; } stop ( ) { this . stopped = true ; } }