import { chains as chainParams } from './chains' ; import { hardforks as hardforkChanges } from './hardforks' ; import { Chain } from './types' ; interface hardforkOptions { /** optional, only allow supported HFs (default: false) */ onlySupported ? : boolean ; /** optional, only active HFs (default: false) */ onlyActive ? : boolean ; } /**
 * Common class to access chain and hardfork parameters
 */ export default class Common { private _hardfork : string | null ; private _supportedHardforks : Array < string > ; private _chainParams : Chain ; param baseChain param customChainParams param hardfork param supportedHardforks static forCustomChain ( baseChain , customChainParams , hardfork ? , supportedHardforks ? ) { const standardChainParams = Common . _getChainParams ( baseChain ) ; return new Common ( { ... standardChainParams , ... customChainParams , } , hardfork , supportedHardforks ) ; } private static _getChainParams ( chain ) { if ( typeof chain === 'number' ) { if ( chainParams [ 'names' ] [ chain ] ) { return chainParams [ chainParams [ 'names' ] [ chain ] ] ; } throw new Error ( `Chain with ID ${ chain } not supported` ) ; } if ( chainParams [ chain ] ) { return chainParams [ chain ] ; } throw new Error ( `Chain with name ${ chain } not supported` ) ; } constructor param chain param hardfork param supportedHardforks constructor ( chain , hardfork ? , supportedHardforks ? ) { this . _chainParams = this . setChain ( chain ) ; this . _hardfork = null ; this . _supportedHardforks = supportedHardforks === undefined ? [ ] : supportedHardforks ; if ( hardfork ) { this . setHardfork ( hardfork ) ; } } param chain returns setChain ( chain ) { if ( typeof chain === 'number' || typeof chain === 'string' ) { this . _chainParams = Common . _getChainParams ( chain ) ; } else if ( typeof chain === 'object' ) { const required = [ 'networkId' , 'genesis' , 'hardforks' , 'bootstrapNodes' ] ; for ( const param of required ) { if ( ( < any > chain ) [ param ] === undefined ) { throw new Error ( `Missing required chain parameter: ${ param }` ) ; } } this . _chainParams = chain as Chain ; } else { throw new Error ( 'Wrong input format' ) ; } return this . _chainParams ; } param hardfork setHardfork ( hardfork ) { if ( ! this . _isSupportedHardfork ( hardfork ) ) { throw new Error ( `Hardfork ${ hardfork } not set as supported in supportedHardforks` ) ; } let changed = false ; for ( const hfChanges of hardforkChanges ) { if ( hfChanges [ 0 ] === hardfork ) { this . _hardfork = hardfork ; changed = true ; } } if ( ! changed ) { throw new Error ( `Hardfork with name ${ hardfork } not supported` ) ; } } param hardfork returns _chooseHardfork ( hardfork ? , onlySupported ? ) { onlySupported = onlySupported === undefined ? true : onlySupported ; if ( ! hardfork ) { if ( ! this . _hardfork ) { throw new Error ( 'Method called with neither a hardfork set nor provided by param' ) ; } else { hardfork = this . _hardfork ; } } else if ( onlySupported && ! this . _isSupportedHardfork ( hardfork ) ) { throw new Error ( `Hardfork ${ hardfork } not set as supported in supportedHardforks` ) ; } return hardfork ; } param hardfork returns _getHardfork ( hardfork ) { const hfs = this . hardforks ( ) ; for ( const hf of hfs ) { if ( hf [ 'name' ] === hardfork ) return hf ; } throw new Error ( `Hardfork ${ hardfork } not defined for chain ${ this . chainName ( ) }` ) ; } param hardfork returns _isSupportedHardfork ( hardfork ) { if ( this . _supportedHardforks . length > 0 ) { for ( const supportedHf of this . _supportedHardforks ) { if ( hardfork === supportedHf ) return true ; } } else { return true ; } return false ; } param topic param name param hardfork param ( topic , name , hardfork ? ) { hardfork = this . _chooseHardfork ( hardfork ) ; let value ; for ( const hfChanges of hardforkChanges ) { if ( ! hfChanges [ 1 ] [ topic ] ) { throw new Error ( `Topic ${ topic } not defined` ) ; } if ( hfChanges [ 1 ] [ topic ] [ name ] !== undefined ) { value = hfChanges [ 1 ] [ topic ] [ name ] . v ; } if ( hfChanges [ 0 ] === hardfork ) break ; } if ( value === undefined ) { throw new Error ( `${ topic } value for ${ name } not found` ) ; } return value ; } param topic param name param blockNumber paramByBlock ( topic , name , blockNumber ) { const activeHfs = this . activeHardforks ( blockNumber ) ; const hardfork = activeHfs [ activeHfs . length - 1 ] [ 'name' ] ; return this . param ( topic , name , hardfork ) ; } param hardfork param blockNumber param opts returns hardforkIsActiveOnBlock ( hardfork , blockNumber , opts ? ) { opts = opts !== undefined ? opts : { } ; const onlySupported = opts . onlySupported === undefined ? false : opts . onlySupported ; hardfork = this . _chooseHardfork ( hardfork , onlySupported ) ; const hfBlock = this . hardforkBlock ( hardfork ) ; if ( hfBlock !== null && blockNumber >= hfBlock ) return true ; return false ; } param blockNumber param opts returns activeOnBlock ( blockNumber , opts ? ) { return this . hardforkIsActiveOnBlock ( null , blockNumber , opts ) ; } param hardfork1 param hardfork2 param opts returns hardforkGteHardfork ( hardfork1 , hardfork2 , opts ? ) { opts = opts !== undefined ? opts : { } ; const onlyActive = opts . onlyActive === undefined ? false : opts . onlyActive ; hardfork1 = this . _chooseHardfork ( hardfork1 , opts . onlySupported ) ; let hardforks ; if ( onlyActive ) { hardforks = this . activeHardforks ( null , opts ) ; } else { hardforks = this . hardforks ( ) ; } let posHf1 = - 1 , posHf2 = - 1 ; let index = 0 ; for ( const hf of hardforks ) { if ( hf [ 'name' ] === hardfork1 ) posHf1 = index ; if ( hf [ 'name' ] === hardfork2 ) posHf2 = index ; index += 1 ; } return posHf1 >= posHf2 ; } param hardfork param opts returns gteHardfork ( hardfork , opts ? ) { return this . hardforkGteHardfork ( null , hardfork , opts ) ; } param hardfork param opts returns hardforkIsActiveOnChain ( hardfork ? , opts ? ) { opts = opts !== undefined ? opts : { } ; const onlySupported = opts . onlySupported === undefined ? false : opts . onlySupported ; hardfork = this . _chooseHardfork ( hardfork , onlySupported ) ; for ( const hf of this . hardforks ( ) ) { if ( hf [ 'name' ] === hardfork && hf [ 'block' ] !== null ) return true ; } return false ; } param blockNumber param opts return activeHardforks ( blockNumber ? , opts ? ) { opts = opts !== undefined ? opts : { } ; const activeHardforks = [ ] ; const hfs = this . hardforks ( ) ; for ( const hf of hfs ) { if ( hf [ 'block' ] === null ) continue ; if ( blockNumber !== undefined && blockNumber !== null && blockNumber < hf [ 'block' ] ) break ; if ( opts . onlySupported && ! this . _isSupportedHardfork ( hf [ 'name' ] ) ) continue ; activeHardforks . push ( hf ) ; } return activeHardforks ; } param blockNumber param opts return activeHardfork ( blockNumber ? , opts ? ) { opts = opts !== undefined ? opts : { } ; const activeHardforks = this . activeHardforks ( blockNumber , opts ) ; if ( activeHardforks . length > 0 ) { return activeHardforks [ activeHardforks . length - 1 ] [ 'name' ] ; } else { throw new Error ( `No (supported) active hardfork found` ) ; } } param hardfork returns hardforkBlock ( hardfork ? ) { hardfork = this . _chooseHardfork ( hardfork , false ) ; return this . _getHardfork ( hardfork ) [ 'block' ] ; } param blockNumber param hardfork returns isHardforkBlock ( blockNumber , hardfork ? ) { hardfork = this . _chooseHardfork ( hardfork , false ) ; if ( this . hardforkBlock ( hardfork ) === blockNumber ) { return true ; } else { return false ; } } param hardfork returns consensus ( hardfork ? ) { hardfork = this . _chooseHardfork ( hardfork ) ; return this . _getHardfork ( hardfork ) [ 'consensus' ] ; } param { String } hardfork returns { String } finality ( hardfork ? ) { hardfork = this . _chooseHardfork ( hardfork ) ; return this . _getHardfork ( hardfork ) [ 'finality' ] ; } returns genesis ( ) { return ( < any > this . _chainParams ) [ 'genesis' ] ; } returns { Array } hardforks ( ) { return ( < any > this . _chainParams ) [ 'hardforks' ] ; } returns { Dictionary } bootstrapNodes ( ) { return ( < any > this . _chainParams ) [ 'bootstrapNodes' ] ; } returns hardfork ( ) { return this . _hardfork ; } returns chainId ( ) { return < number > ( < any > this . _chainParams ) [ 'chainId' ] ; } returns chainName ( ) { return chainParams [ 'names' ] [ this . chainId ( ) ] || ( < any > this . _chainParams ) [ 'name' ] ; } returns networkId ( ) { return ( < any > this . _chainParams ) [ 'networkId' ] ; } }