import { BaseProvider , Network } from '@ethersproject/providers' ; function checkNetworks ( networks ) { let result = null ; for ( let i = 0 ; i < networks . length ; i ++ ) { const network = networks [ i ] ; if ( network == null ) { return null ; } if ( result ) { if ( ! ( result . name === network . name && result . chainId === network . chainId && ( result . ensAddress === network . ensAddress || ( result . ensAddress == null && network . ensAddress == null ) ) ) ) { throw new Error ( 'provider mismatch' ) ; } } else { result = network ; } } return result ; } export class FallbackProvider extends BaseProvider { private _providers : Array < BaseProvider > ; constructor ( providers ) { if ( providers . length === 0 ) { throw new Error ( 'no providers' ) ; } const ready = checkNetworks ( providers . map ( ( p ) => p . network ) ) ; if ( ready ) { super ( providers [ 0 ] . network ) ; } else { const ready = Promise . all ( providers . map ( ( p ) => p . getNetwork ( ) ) ) . then ( ( networks ) => { if ( ! checkNetworks ( networks ) ) { throw new Error ( 'getNetwork returned null' ) ; } return networks [ 0 ] ; } ) ; super ( ready ) ; } this . _providers = providers . slice ( 0 ) ; } async detectNetwork ( ) { const networks = await Promise . all ( this . providers . map ( ( p ) => p . getNetwork ( ) ) ) ; return checkNetworks ( networks ) as Network ; } get providers ( ) : Array < BaseProvider > { return this . _providers . slice ( 0 ) ; } perform ( method , params ) { const providers = this . providers ; return new Promise ( ( resolve , reject ) => { let firstError = null ; function next ( ) { if ( ! providers . length || providers . length === 0 ) { reject ( firstError ) ; return ; } const provider = providers . shift ( ) ; provider ! . perform ( method , params ) . then ( ( result ) => { return resolve ( result ) ; } ) . catch ( ( error ) => { if ( ! firstError ) { firstError = error ; } setTimeout ( next , 0 ) ; } ) ; } next ( ) ; } ) ; } }