provider-alchemy.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /**
  2. * [[link-alchemy]] provides a third-party service for connecting to
  3. * various blockchains over JSON-RPC.
  4. *
  5. * **Supported Networks**
  6. *
  7. * - Ethereum Mainnet (``mainnet``)
  8. * - Goerli Testnet (``goerli``)
  9. * - Sepolia Testnet (``sepolia``)
  10. * - Arbitrum (``arbitrum``)
  11. * - Arbitrum Goerli Testnet (``arbitrum-goerli``)
  12. * - Arbitrum Sepolia Testnet (``arbitrum-sepolia``)
  13. * - Base (``base``)
  14. * - Base Goerlia Testnet (``base-goerli``)
  15. * - Base Sepolia Testnet (``base-sepolia``)
  16. * - Optimism (``optimism``)
  17. * - Optimism Goerli Testnet (``optimism-goerli``)
  18. * - Optimism Sepolia Testnet (``optimism-sepolia``)
  19. * - Polygon (``matic``)
  20. * - Polygon Amoy Testnet (``matic-amoy``)
  21. * - Polygon Mumbai Testnet (``matic-mumbai``)
  22. *
  23. * @_subsection: api/providers/thirdparty:Alchemy [providers-alchemy]
  24. */
  25. import { defineProperties, resolveProperties, assert, assertArgument, FetchRequest } from "../utils/index.js";
  26. import { showThrottleMessage } from "./community.js";
  27. import { Network } from "./network.js";
  28. import { JsonRpcProvider } from "./provider-jsonrpc.js";
  29. const defaultApiKey = "_gg7wSSi0KMBsdKnGVfHDueq6xMB9EkC";
  30. function getHost(name) {
  31. switch (name) {
  32. case "mainnet":
  33. return "eth-mainnet.alchemyapi.io";
  34. case "goerli":
  35. return "eth-goerli.g.alchemy.com";
  36. case "sepolia":
  37. return "eth-sepolia.g.alchemy.com";
  38. case "arbitrum":
  39. return "arb-mainnet.g.alchemy.com";
  40. case "arbitrum-goerli":
  41. return "arb-goerli.g.alchemy.com";
  42. case "arbitrum-sepolia":
  43. return "arb-sepolia.g.alchemy.com";
  44. case "base":
  45. return "base-mainnet.g.alchemy.com";
  46. case "base-goerli":
  47. return "base-goerli.g.alchemy.com";
  48. case "base-sepolia":
  49. return "base-sepolia.g.alchemy.com";
  50. case "matic":
  51. return "polygon-mainnet.g.alchemy.com";
  52. case "matic-amoy":
  53. return "polygon-amoy.g.alchemy.com";
  54. case "matic-mumbai":
  55. return "polygon-mumbai.g.alchemy.com";
  56. case "optimism":
  57. return "opt-mainnet.g.alchemy.com";
  58. case "optimism-goerli":
  59. return "opt-goerli.g.alchemy.com";
  60. case "optimism-sepolia":
  61. return "opt-sepolia.g.alchemy.com";
  62. }
  63. assertArgument(false, "unsupported network", "network", name);
  64. }
  65. /**
  66. * The **AlchemyProvider** connects to the [[link-alchemy]]
  67. * JSON-RPC end-points.
  68. *
  69. * By default, a highly-throttled API key is used, which is
  70. * appropriate for quick prototypes and simple scripts. To
  71. * gain access to an increased rate-limit, it is highly
  72. * recommended to [sign up here](link-alchemy-signup).
  73. *
  74. * @_docloc: api/providers/thirdparty
  75. */
  76. export class AlchemyProvider extends JsonRpcProvider {
  77. apiKey;
  78. constructor(_network, apiKey) {
  79. if (_network == null) {
  80. _network = "mainnet";
  81. }
  82. const network = Network.from(_network);
  83. if (apiKey == null) {
  84. apiKey = defaultApiKey;
  85. }
  86. const request = AlchemyProvider.getRequest(network, apiKey);
  87. super(request, network, { staticNetwork: network });
  88. defineProperties(this, { apiKey });
  89. }
  90. _getProvider(chainId) {
  91. try {
  92. return new AlchemyProvider(chainId, this.apiKey);
  93. }
  94. catch (error) { }
  95. return super._getProvider(chainId);
  96. }
  97. async _perform(req) {
  98. // https://docs.alchemy.com/reference/trace-transaction
  99. if (req.method === "getTransactionResult") {
  100. const { trace, tx } = await resolveProperties({
  101. trace: this.send("trace_transaction", [req.hash]),
  102. tx: this.getTransaction(req.hash)
  103. });
  104. if (trace == null || tx == null) {
  105. return null;
  106. }
  107. let data;
  108. let error = false;
  109. try {
  110. data = trace[0].result.output;
  111. error = (trace[0].error === "Reverted");
  112. }
  113. catch (error) { }
  114. if (data) {
  115. assert(!error, "an error occurred during transaction executions", "CALL_EXCEPTION", {
  116. action: "getTransactionResult",
  117. data,
  118. reason: null,
  119. transaction: tx,
  120. invocation: null,
  121. revert: null // @TODO
  122. });
  123. return data;
  124. }
  125. assert(false, "could not parse trace result", "BAD_DATA", { value: trace });
  126. }
  127. return await super._perform(req);
  128. }
  129. isCommunityResource() {
  130. return (this.apiKey === defaultApiKey);
  131. }
  132. static getRequest(network, apiKey) {
  133. if (apiKey == null) {
  134. apiKey = defaultApiKey;
  135. }
  136. const request = new FetchRequest(`https:/\/${getHost(network.name)}/v2/${apiKey}`);
  137. request.allowGzip = true;
  138. if (apiKey === defaultApiKey) {
  139. request.retryFunc = async (request, response, attempt) => {
  140. showThrottleMessage("alchemy");
  141. return true;
  142. };
  143. }
  144. return request;
  145. }
  146. }
  147. //# sourceMappingURL=provider-alchemy.js.map