2022-09-05 16:57:11 -04:00
"use strict" ;
2022-11-30 15:44:23 -05:00
/ * *
2023-06-01 17:52:58 -04:00
* A * * Network * * encapsulates the various properties required to
* interact with a specific chain .
2022-11-30 15:44:23 -05:00
*
* @ _subsection : api / providers : Networks [ networks ]
* /
2022-09-05 16:57:11 -04:00
Object . defineProperty ( exports , "__esModule" , { value : true } ) ;
exports . Network = void 0 ;
2022-09-27 03:45:27 -04:00
const index _js _1 = require ( "../transaction/index.js" ) ;
const index _js _2 = require ( "../utils/index.js" ) ;
2022-09-05 16:57:11 -04:00
const plugins _network _js _1 = require ( "./plugins-network.js" ) ;
/ * * * *
// Networks which operation against an L2 can use this plugin to
// specify how to access L1, for the purpose of resolving ENS,
// for example.
export class LayerOneConnectionPlugin extends NetworkPlugin {
readonly provider ! : Provider ;
// @TODO: Rename to ChainAccess and allow for connecting to any chain
constructor ( provider : Provider ) {
super ( "org.ethers.plugins.layer-one-connection" ) ;
defineProperties < LayerOneConnectionPlugin > ( this , { provider } ) ;
}
clone ( ) : LayerOneConnectionPlugin {
return new LayerOneConnectionPlugin ( this . provider ) ;
}
}
* /
const Networks = new Map ( ) ;
2023-06-01 17:52:58 -04:00
/ * *
* A * * Network * * provides access to a chain ' s properties and allows
* for plug - ins to extend functionality .
* /
2022-09-05 16:57:11 -04:00
class Network {
2022-11-30 15:44:23 -05:00
# name ;
# chainId ;
# plugins ;
2023-06-01 17:52:58 -04:00
/ * *
* Creates a new * * Network * * for % % name % % and % % chainId % % .
* /
2022-11-30 15:44:23 -05:00
constructor ( name , chainId ) {
this . # name = name ;
this . # chainId = ( 0 , index _js _2 . getBigInt ) ( chainId ) ;
this . # plugins = new Map ( ) ;
2022-09-05 16:57:11 -04:00
}
2023-06-01 17:52:58 -04:00
/ * *
* Returns a JSON - compatible representation of a Network .
* /
2022-09-05 16:57:11 -04:00
toJSON ( ) {
2023-04-25 20:04:48 +09:00
return { name : this . name , chainId : String ( this . chainId ) } ;
2022-09-05 16:57:11 -04:00
}
2023-04-25 20:04:48 +09:00
/ * *
* The network common name .
*
* This is the canonical name , as networks migh have multiple
* names .
* /
2022-11-30 15:44:23 -05:00
get name ( ) { return this . # name ; }
set name ( value ) { this . # name = value ; }
2023-04-25 20:04:48 +09:00
/ * *
* The network chain ID .
* /
2022-11-30 15:44:23 -05:00
get chainId ( ) { return this . # chainId ; }
set chainId ( value ) { this . # chainId = ( 0 , index _js _2 . getBigInt ) ( value , "chainId" ) ; }
2023-04-25 20:04:48 +09:00
/ * *
* Returns true if % % other % % matches this network . Any chain ID
* must match , and if no chain ID is present , the name must match .
*
* This method does not currently check for additional properties ,
* such as ENS address or plug - in compatibility .
* /
matches ( other ) {
if ( other == null ) {
return false ;
}
if ( typeof ( other ) === "string" ) {
try {
return ( this . chainId === ( 0 , index _js _2 . getBigInt ) ( other ) ) ;
}
catch ( error ) { }
return ( this . name === other ) ;
}
if ( typeof ( other ) === "number" || typeof ( other ) === "bigint" ) {
try {
return ( this . chainId === ( 0 , index _js _2 . getBigInt ) ( other ) ) ;
}
catch ( error ) { }
return false ;
}
if ( typeof ( other ) === "object" ) {
if ( other . chainId != null ) {
try {
return ( this . chainId === ( 0 , index _js _2 . getBigInt ) ( other . chainId ) ) ;
}
catch ( error ) { }
return false ;
}
if ( other . name != null ) {
return ( this . name === other . name ) ;
}
return false ;
}
return false ;
}
/ * *
* Returns the list of plugins currently attached to this Network .
* /
2022-09-05 16:57:11 -04:00
get plugins ( ) {
2022-11-30 15:44:23 -05:00
return Array . from ( this . # plugins . values ( ) ) ;
2022-09-05 16:57:11 -04:00
}
2023-04-25 20:04:48 +09:00
/ * *
* Attach a new % % plugin % % to this Network . The network name
* must be unique , excluding any fragment .
* /
2022-09-05 16:57:11 -04:00
attachPlugin ( plugin ) {
2022-11-30 15:44:23 -05:00
if ( this . # plugins . get ( plugin . name ) ) {
2022-09-05 16:57:11 -04:00
throw new Error ( ` cannot replace existing plugin: ${ plugin . name } ` ) ;
}
2022-11-30 15:44:23 -05:00
this . # plugins . set ( plugin . name , plugin . clone ( ) ) ;
2022-09-05 16:57:11 -04:00
return this ;
}
2023-04-25 20:04:48 +09:00
/ * *
* Return the plugin , if any , matching % % name % % exactly . Plugins
* with fragments will not be returned unless % % name % % includes
* a fragment .
* /
2022-09-05 16:57:11 -04:00
getPlugin ( name ) {
2022-11-30 15:44:23 -05:00
return ( this . # plugins . get ( name ) ) || null ;
2022-09-05 16:57:11 -04:00
}
2023-04-25 20:04:48 +09:00
/ * *
* Gets a list of all plugins that match % % name % % , with otr without
* a fragment .
* /
2022-09-05 16:57:11 -04:00
getPlugins ( basename ) {
return ( this . plugins . filter ( ( p ) => ( p . name . split ( "#" ) [ 0 ] === basename ) ) ) ;
}
2023-04-25 20:04:48 +09:00
/ * *
* Create a copy of this Network .
* /
2022-09-05 16:57:11 -04:00
clone ( ) {
2022-09-27 03:45:27 -04:00
const clone = new Network ( this . name , this . chainId ) ;
2022-09-05 16:57:11 -04:00
this . plugins . forEach ( ( plugin ) => {
clone . attachPlugin ( plugin . clone ( ) ) ;
} ) ;
return clone ;
}
2023-04-25 20:04:48 +09:00
/ * *
* Compute the intrinsic gas required for a transaction .
*
* A GasCostPlugin can be attached to override the default
* values .
* /
2022-09-05 16:57:11 -04:00
computeIntrinsicGas ( tx ) {
2023-02-02 04:05:47 -05:00
const costs = this . getPlugin ( "org.ethers.plugins.network.GasCost" ) || ( new plugins _network _js _1 . GasCostPlugin ( ) ) ;
2022-09-05 16:57:11 -04:00
let gas = costs . txBase ;
if ( tx . to == null ) {
gas += costs . txCreate ;
}
if ( tx . data ) {
for ( let i = 2 ; i < tx . data . length ; i += 2 ) {
if ( tx . data . substring ( i , i + 2 ) === "00" ) {
gas += costs . txDataZero ;
}
else {
gas += costs . txDataNonzero ;
}
}
}
if ( tx . accessList ) {
2022-09-27 03:45:27 -04:00
const accessList = ( 0 , index _js _1 . accessListify ) ( tx . accessList ) ;
2022-09-05 16:57:11 -04:00
for ( const addr in accessList ) {
gas += costs . txAccessListAddress + costs . txAccessListStorageKey * accessList [ addr ] . storageKeys . length ;
}
}
return gas ;
}
2022-09-15 22:58:45 -04:00
/ * *
* Returns a new Network for the % % network % % name or chainId .
* /
2022-09-05 16:57:11 -04:00
static from ( network ) {
2022-10-20 05:03:32 -04:00
injectCommonNetworks ( ) ;
2022-09-05 16:57:11 -04:00
// Default network
if ( network == null ) {
2022-09-29 22:57:27 -04:00
return Network . from ( "mainnet" ) ;
2022-09-05 16:57:11 -04:00
}
// Canonical name or chain ID
if ( typeof ( network ) === "number" ) {
network = BigInt ( network ) ;
}
if ( typeof ( network ) === "string" || typeof ( network ) === "bigint" ) {
const networkFunc = Networks . get ( network ) ;
if ( networkFunc ) {
return networkFunc ( ) ;
}
if ( typeof ( network ) === "bigint" ) {
return new Network ( "unknown" , network ) ;
}
2022-11-09 02:57:02 -05:00
( 0 , index _js _2 . assertArgument ) ( false , "unknown network" , "network" , network ) ;
2022-09-05 16:57:11 -04:00
}
// Clonable with network-like abilities
if ( typeof ( network . clone ) === "function" ) {
const clone = network . clone ( ) ;
//if (typeof(network.name) !== "string" || typeof(network.chainId) !== "number") {
//}
return clone ;
}
// Networkish
if ( typeof ( network ) === "object" ) {
2022-11-09 02:57:02 -05:00
( 0 , index _js _2 . assertArgument ) ( typeof ( network . name ) === "string" && typeof ( network . chainId ) === "number" , "invalid network object name or chainId" , "network" , network ) ;
2022-09-05 16:57:11 -04:00
const custom = new Network ( ( network . name ) , ( network . chainId ) ) ;
if ( network . ensAddress || network . ensNetwork != null ) {
custom . attachPlugin ( new plugins _network _js _1 . EnsPlugin ( network . ensAddress , network . ensNetwork ) ) ;
}
//if ((<any>network).layerOneConnection) {
// custom.attachPlugin(new LayerOneConnectionPlugin((<any>network).layerOneConnection));
//}
return custom ;
}
2022-11-09 02:57:02 -05:00
( 0 , index _js _2 . assertArgument ) ( false , "invalid network" , "network" , network ) ;
2022-09-05 16:57:11 -04:00
}
2022-09-15 22:58:45 -04:00
/ * *
* Register % % nameOrChainId % % with a function which returns
* an instance of a Network representing that chain .
* /
2022-09-05 16:57:11 -04:00
static register ( nameOrChainId , networkFunc ) {
if ( typeof ( nameOrChainId ) === "number" ) {
nameOrChainId = BigInt ( nameOrChainId ) ;
}
const existing = Networks . get ( nameOrChainId ) ;
if ( existing ) {
2022-11-09 02:57:02 -05:00
( 0 , index _js _2 . assertArgument ) ( false , ` conflicting network for ${ JSON . stringify ( existing . name ) } ` , "nameOrChainId" , nameOrChainId ) ;
2022-09-05 16:57:11 -04:00
}
Networks . set ( nameOrChainId , networkFunc ) ;
}
}
exports . Network = Network ;
2023-07-29 02:37:03 -04:00
// We don't want to bring in formatUnits because it is backed by
// FixedNumber and we want to keep Networks tiny. The values
// included by the Gas Stations are also IEEE 754 with lots of
// rounding issues and exceed the strict checks formatUnits has.
function parseUnits ( _value , decimals ) {
const value = String ( _value ) ;
if ( ! value . match ( /^[0-9.]+$/ ) ) {
throw new Error ( ` invalid gwei value: ${ _value } ` ) ;
}
// Break into [ whole, fraction ]
const comps = value . split ( "." ) ;
if ( comps . length === 1 ) {
comps . push ( "" ) ;
}
// More than 1 decimal point or too many fractional positions
if ( comps . length !== 2 ) {
throw new Error ( ` invalid gwei value: ${ _value } ` ) ;
}
// Pad the fraction to 9 decimalplaces
while ( comps [ 1 ] . length < decimals ) {
comps [ 1 ] += "0" ;
}
// Too many decimals and some non-zero ending, take the ceiling
2023-08-02 23:42:17 -04:00
if ( comps [ 1 ] . length > 9 ) {
let frac = BigInt ( comps [ 1 ] . substring ( 0 , 9 ) ) ;
if ( ! comps [ 1 ] . substring ( 9 ) . match ( /^0+$/ ) ) {
frac ++ ;
}
comps [ 1 ] = frac . toString ( ) ;
2023-07-29 02:37:03 -04:00
}
return BigInt ( comps [ 0 ] + comps [ 1 ] ) ;
}
2023-08-02 23:42:17 -04:00
// Used by Polygon to use a gas station for fee data
2023-07-29 02:37:03 -04:00
function getGasStationPlugin ( url ) {
return new plugins _network _js _1 . FetchUrlFeeDataNetworkPlugin ( url , async ( fetchFeeData , provider , request ) => {
// Prevent Cloudflare from blocking our request in node.js
request . setHeader ( "User-Agent" , "ethers" ) ;
let response ;
try {
2023-08-15 00:58:04 -04:00
const [ _response , _feeData ] = await Promise . all ( [
request . send ( ) , fetchFeeData ( )
] ) ;
response = _response ;
2023-07-29 02:37:03 -04:00
const payload = response . bodyJson . standard ;
const feeData = {
2023-08-15 00:58:04 -04:00
gasPrice : _feeData . gasPrice ,
2023-07-29 02:37:03 -04:00
maxFeePerGas : parseUnits ( payload . maxFee , 9 ) ,
maxPriorityFeePerGas : parseUnits ( payload . maxPriorityFee , 9 ) ,
} ;
return feeData ;
}
catch ( error ) {
( 0 , index _js _2 . assert ) ( false , ` error encountered with polygon gas station ( ${ JSON . stringify ( request . url ) } ) ` , "SERVER_ERROR" , { request , response , error } ) ;
}
} ) ;
}
2022-10-20 05:03:32 -04:00
// See: https://chainlist.org
let injected = false ;
function injectCommonNetworks ( ) {
if ( injected ) {
return ;
}
injected = true ;
/// Register popular Ethereum networks
function registerEth ( name , chainId , options ) {
const func = function ( ) {
const network = new Network ( name , chainId ) ;
// We use 0 to disable ENS
if ( options . ensNetwork != null ) {
network . attachPlugin ( new plugins _network _js _1 . EnsPlugin ( null , options . ensNetwork ) ) ;
}
network . attachPlugin ( new plugins _network _js _1 . GasCostPlugin ( ) ) ;
2023-07-29 02:37:03 -04:00
( options . plugins || [ ] ) . forEach ( ( plugin ) => {
network . attachPlugin ( plugin ) ;
} ) ;
2022-10-20 05:03:32 -04:00
return network ;
} ;
// Register the network by name and chain ID
Network . register ( name , func ) ;
Network . register ( chainId , func ) ;
if ( options . altNames ) {
options . altNames . forEach ( ( name ) => {
Network . register ( name , func ) ;
} ) ;
}
}
registerEth ( "mainnet" , 1 , { ensNetwork : 1 , altNames : [ "homestead" ] } ) ;
registerEth ( "ropsten" , 3 , { ensNetwork : 3 } ) ;
registerEth ( "rinkeby" , 4 , { ensNetwork : 4 } ) ;
registerEth ( "goerli" , 5 , { ensNetwork : 5 } ) ;
registerEth ( "kovan" , 42 , { ensNetwork : 42 } ) ;
2023-11-01 16:17:49 -04:00
registerEth ( "sepolia" , 11155111 , { ensNetwork : 11155111 } ) ;
2024-02-02 03:25:03 -05:00
registerEth ( "holesky" , 17000 , { ensNetwork : 17000 } ) ;
2022-10-20 05:03:32 -04:00
registerEth ( "classic" , 61 , { } ) ;
registerEth ( "classicKotti" , 6 , { } ) ;
2023-02-22 21:53:56 -05:00
registerEth ( "arbitrum" , 42161 , {
ensNetwork : 1 ,
} ) ;
2023-07-29 02:37:03 -04:00
registerEth ( "arbitrum-goerli" , 421613 , { } ) ;
2024-01-15 23:07:48 -05:00
registerEth ( "arbitrum-sepolia" , 421614 , { } ) ;
2023-11-27 06:11:49 -05:00
registerEth ( "base" , 8453 , { ensNetwork : 1 } ) ;
registerEth ( "base-goerli" , 84531 , { } ) ;
registerEth ( "base-sepolia" , 84532 , { } ) ;
2023-07-29 02:37:03 -04:00
registerEth ( "bnb" , 56 , { ensNetwork : 1 } ) ;
registerEth ( "bnbt" , 97 , { } ) ;
registerEth ( "linea" , 59144 , { ensNetwork : 1 } ) ;
registerEth ( "linea-goerli" , 59140 , { } ) ;
2022-10-20 05:03:32 -04:00
registerEth ( "matic" , 137 , {
ensNetwork : 1 ,
2023-07-29 02:37:03 -04:00
plugins : [
getGasStationPlugin ( "https:/\/gasstation.polygon.technology/v2" )
]
2022-10-20 05:03:32 -04:00
} ) ;
2023-02-23 06:31:09 -05:00
registerEth ( "matic-mumbai" , 80001 , {
altNames : [ "maticMumbai" , "maticmum" ] ,
2023-07-29 02:37:03 -04:00
plugins : [
getGasStationPlugin ( "https:/\/gasstation-testnet.polygon.technology/v2" )
]
2022-10-20 05:03:32 -04:00
} ) ;
2023-07-29 02:37:03 -04:00
registerEth ( "optimism" , 10 , {
2022-10-20 05:03:32 -04:00
ensNetwork : 1 ,
2023-11-27 06:11:49 -05:00
plugins : [ ]
2022-10-20 05:03:32 -04:00
} ) ;
2023-07-29 02:37:03 -04:00
registerEth ( "optimism-goerli" , 420 , { } ) ;
2024-01-15 23:07:48 -05:00
registerEth ( "optimism-sepolia" , 11155420 , { } ) ;
2023-07-29 02:37:03 -04:00
registerEth ( "xdai" , 100 , { ensNetwork : 1 } ) ;
2022-10-20 05:03:32 -04:00
}
2022-09-05 16:57:11 -04:00
//# sourceMappingURL=network.js.map