index.ts 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. "use strict";
  2. import { Logger } from "@ethersproject/logger";
  3. import { version } from "./_version";
  4. const logger = new Logger(version);
  5. import { Network, Networkish } from "./types";
  6. export {
  7. Network,
  8. Networkish
  9. };
  10. type DefaultProviderFunc = (providers: any, options?: any) => any;
  11. interface Renetworkable extends DefaultProviderFunc {
  12. renetwork: (network: Network) => DefaultProviderFunc;
  13. };
  14. function isRenetworkable(value: any): value is Renetworkable {
  15. return (value && typeof(value.renetwork) === "function");
  16. }
  17. function ethDefaultProvider(network: string | Network): Renetworkable {
  18. const func = function(providers: any, options?: any): any {
  19. if (options == null) { options = { }; }
  20. const providerList: Array<any> = [];
  21. if (providers.InfuraProvider && options.infura !== "-") {
  22. try {
  23. providerList.push(new providers.InfuraProvider(network, options.infura));
  24. } catch(error) { }
  25. }
  26. if (providers.EtherscanProvider && options.etherscan !== "-") {
  27. try {
  28. providerList.push(new providers.EtherscanProvider(network, options.etherscan));
  29. } catch(error) { }
  30. }
  31. if (providers.AlchemyProvider && options.alchemy !== "-") {
  32. try {
  33. providerList.push(new providers.AlchemyProvider(network, options.alchemy));
  34. } catch(error) { }
  35. }
  36. if (providers.PocketProvider && options.pocket !== "-") {
  37. // These networks are currently faulty on Pocket as their
  38. // network does not handle the Berlin hardfork, which is
  39. // live on these ones.
  40. // @TODO: This goes away once Pocket has upgraded their nodes
  41. const skip = [ "goerli", "ropsten", "rinkeby" ];
  42. try {
  43. const provider = new providers.PocketProvider(network);
  44. if (provider.network && skip.indexOf(provider.network.name) === -1) {
  45. providerList.push(provider);
  46. }
  47. } catch(error) { }
  48. }
  49. if (providers.CloudflareProvider && options.cloudflare !== "-") {
  50. try {
  51. providerList.push(new providers.CloudflareProvider(network));
  52. } catch(error) { }
  53. }
  54. if (providerList.length === 0) { return null; }
  55. if (providers.FallbackProvider) {
  56. let quorum = 1;
  57. if (options.quorum != null) {
  58. quorum = options.quorum;
  59. } else if (network === "homestead") {
  60. quorum = 2;
  61. }
  62. return new providers.FallbackProvider(providerList, quorum);
  63. }
  64. return providerList[0];
  65. };
  66. func.renetwork = function(network: Network) {
  67. return ethDefaultProvider(network);
  68. };
  69. return func;
  70. }
  71. function etcDefaultProvider(url: string, network: string | Network): Renetworkable {
  72. const func = function(providers: any, options?: any): any {
  73. if (providers.JsonRpcProvider) {
  74. return new providers.JsonRpcProvider(url, network);
  75. }
  76. return null;
  77. };
  78. func.renetwork = function(network: Network) {
  79. return etcDefaultProvider(url, network);
  80. };
  81. return func;
  82. }
  83. const homestead: Network = {
  84. chainId: 1,
  85. ensAddress: "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e",
  86. name: "homestead",
  87. _defaultProvider: ethDefaultProvider("homestead")
  88. };
  89. const ropsten: Network = {
  90. chainId: 3,
  91. ensAddress: "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e",
  92. name: "ropsten",
  93. _defaultProvider: ethDefaultProvider("ropsten")
  94. };
  95. const classicMordor: Network = {
  96. chainId: 63,
  97. name: "classicMordor",
  98. _defaultProvider: etcDefaultProvider("https://www.ethercluster.com/mordor", "classicMordor")
  99. };
  100. // See: https://chainlist.org
  101. const networks: { [name: string]: Network } = {
  102. unspecified: { chainId: 0, name: "unspecified" },
  103. homestead: homestead,
  104. mainnet: homestead,
  105. morden: { chainId: 2, name: "morden" },
  106. ropsten: ropsten,
  107. testnet: ropsten,
  108. rinkeby: {
  109. chainId: 4,
  110. ensAddress: "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e",
  111. name: "rinkeby",
  112. _defaultProvider: ethDefaultProvider("rinkeby")
  113. },
  114. kovan: {
  115. chainId: 42,
  116. name: "kovan",
  117. _defaultProvider: ethDefaultProvider("kovan")
  118. },
  119. goerli: {
  120. chainId: 5,
  121. ensAddress: "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e",
  122. name: "goerli",
  123. _defaultProvider: ethDefaultProvider("goerli")
  124. },
  125. kintsugi: { chainId: 1337702, name: "kintsugi" },
  126. // ETC (See: #351)
  127. classic: {
  128. chainId: 61,
  129. name: "classic",
  130. _defaultProvider: etcDefaultProvider("https:/\/www.ethercluster.com/etc", "classic")
  131. },
  132. classicMorden: { chainId: 62, name: "classicMorden" },
  133. classicMordor: classicMordor,
  134. classicTestnet: classicMordor,
  135. classicKotti: {
  136. chainId: 6,
  137. name: "classicKotti",
  138. _defaultProvider: etcDefaultProvider("https:/\/www.ethercluster.com/kotti", "classicKotti")
  139. },
  140. xdai: { chainId: 100, name: "xdai" },
  141. matic: { chainId: 137, name: "matic" },
  142. maticmum: { chainId: 80001, name: "maticmum" },
  143. optimism: { chainId: 10, name: "optimism" },
  144. "optimism-kovan": { chainId: 69, name: "optimism-kovan" },
  145. "optimism-goerli": { chainId: 420, name: "optimism-goerli" },
  146. arbitrum: { chainId: 42161, name: "arbitrum" },
  147. "arbitrum-rinkeby": { chainId: 421611, name: "arbitrum-rinkeby" },
  148. bnb: { chainId: 56, name: "bnb" },
  149. bnbt: { chainId: 97, name: "bnbt" },
  150. }
  151. /**
  152. * getNetwork
  153. *
  154. * Converts a named common networks or chain ID (network ID) to a Network
  155. * and verifies a network is a valid Network..
  156. */
  157. export function getNetwork(network: Networkish): Network {
  158. // No network (null)
  159. if (network == null) { return null; }
  160. if (typeof(network) === "number") {
  161. for (const name in networks) {
  162. const standard = networks[name];
  163. if (standard.chainId === network) {
  164. return {
  165. name: standard.name,
  166. chainId: standard.chainId,
  167. ensAddress: (standard.ensAddress || null),
  168. _defaultProvider: (standard._defaultProvider || null)
  169. };
  170. }
  171. }
  172. return {
  173. chainId: network,
  174. name: "unknown"
  175. };
  176. }
  177. if (typeof(network) === "string") {
  178. const standard = networks[network];
  179. if (standard == null) { return null; }
  180. return {
  181. name: standard.name,
  182. chainId: standard.chainId,
  183. ensAddress: standard.ensAddress,
  184. _defaultProvider: (standard._defaultProvider || null)
  185. };
  186. }
  187. const standard = networks[network.name];
  188. // Not a standard network; check that it is a valid network in general
  189. if (!standard) {
  190. if (typeof(network.chainId) !== "number") {
  191. logger.throwArgumentError("invalid network chainId", "network", network);
  192. }
  193. return network;
  194. }
  195. // Make sure the chainId matches the expected network chainId (or is 0; disable EIP-155)
  196. if (network.chainId !== 0 && network.chainId !== standard.chainId) {
  197. logger.throwArgumentError("network chainId mismatch", "network", network);
  198. }
  199. // @TODO: In the next major version add an attach function to a defaultProvider
  200. // class and move the _defaultProvider internal to this file (extend Network)
  201. let defaultProvider: DefaultProviderFunc = network._defaultProvider || null;
  202. if (defaultProvider == null && standard._defaultProvider) {
  203. if (isRenetworkable(standard._defaultProvider)) {
  204. defaultProvider = standard._defaultProvider.renetwork(network);
  205. } else {
  206. defaultProvider = standard._defaultProvider;
  207. }
  208. }
  209. // Standard Network (allow overriding the ENS address)
  210. return {
  211. name: network.name,
  212. chainId: standard.chainId,
  213. ensAddress: (network.ensAddress || standard.ensAddress || null),
  214. _defaultProvider: defaultProvider
  215. };
  216. }