abstract-provider.js 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409
  1. "use strict";
  2. /**
  3. * The available providers should suffice for most developers purposes,
  4. * but the [[AbstractProvider]] class has many features which enable
  5. * sub-classing it for specific purposes.
  6. *
  7. * @_section: api/providers/abstract-provider: Subclassing Provider [abstract-provider]
  8. */
  9. Object.defineProperty(exports, "__esModule", { value: true });
  10. exports.AbstractProvider = exports.UnmanagedSubscriber = void 0;
  11. // @TODO
  12. // Event coalescence
  13. // When we register an event with an async value (e.g. address is a Signer
  14. // or ENS name), we need to add it immeidately for the Event API, but also
  15. // need time to resolve the address. Upon resolving the address, we need to
  16. // migrate the listener to the static event. We also need to maintain a map
  17. // of Signer/ENS name to address so we can sync respond to listenerCount.
  18. const index_js_1 = require("../address/index.js");
  19. const index_js_2 = require("../constants/index.js");
  20. const index_js_3 = require("../contract/index.js");
  21. const index_js_4 = require("../hash/index.js");
  22. const index_js_5 = require("../transaction/index.js");
  23. const index_js_6 = require("../utils/index.js");
  24. const ens_resolver_js_1 = require("./ens-resolver.js");
  25. const format_js_1 = require("./format.js");
  26. const network_js_1 = require("./network.js");
  27. const provider_js_1 = require("./provider.js");
  28. const subscriber_polling_js_1 = require("./subscriber-polling.js");
  29. // Constants
  30. const BN_2 = BigInt(2);
  31. const MAX_CCIP_REDIRECTS = 10;
  32. function isPromise(value) {
  33. return (value && typeof (value.then) === "function");
  34. }
  35. function getTag(prefix, value) {
  36. return prefix + ":" + JSON.stringify(value, (k, v) => {
  37. if (v == null) {
  38. return "null";
  39. }
  40. if (typeof (v) === "bigint") {
  41. return `bigint:${v.toString()}`;
  42. }
  43. if (typeof (v) === "string") {
  44. return v.toLowerCase();
  45. }
  46. // Sort object keys
  47. if (typeof (v) === "object" && !Array.isArray(v)) {
  48. const keys = Object.keys(v);
  49. keys.sort();
  50. return keys.reduce((accum, key) => {
  51. accum[key] = v[key];
  52. return accum;
  53. }, {});
  54. }
  55. return v;
  56. });
  57. }
  58. /**
  59. * An **UnmanagedSubscriber** is useful for events which do not require
  60. * any additional management, such as ``"debug"`` which only requires
  61. * emit in synchronous event loop triggered calls.
  62. */
  63. class UnmanagedSubscriber {
  64. /**
  65. * The name fof the event.
  66. */
  67. name;
  68. /**
  69. * Create a new UnmanagedSubscriber with %%name%%.
  70. */
  71. constructor(name) { (0, index_js_6.defineProperties)(this, { name }); }
  72. start() { }
  73. stop() { }
  74. pause(dropWhilePaused) { }
  75. resume() { }
  76. }
  77. exports.UnmanagedSubscriber = UnmanagedSubscriber;
  78. function copy(value) {
  79. return JSON.parse(JSON.stringify(value));
  80. }
  81. function concisify(items) {
  82. items = Array.from((new Set(items)).values());
  83. items.sort();
  84. return items;
  85. }
  86. async function getSubscription(_event, provider) {
  87. if (_event == null) {
  88. throw new Error("invalid event");
  89. }
  90. // Normalize topic array info an EventFilter
  91. if (Array.isArray(_event)) {
  92. _event = { topics: _event };
  93. }
  94. if (typeof (_event) === "string") {
  95. switch (_event) {
  96. case "block":
  97. case "debug":
  98. case "error":
  99. case "finalized":
  100. case "network":
  101. case "pending":
  102. case "safe": {
  103. return { type: _event, tag: _event };
  104. }
  105. }
  106. }
  107. if ((0, index_js_6.isHexString)(_event, 32)) {
  108. const hash = _event.toLowerCase();
  109. return { type: "transaction", tag: getTag("tx", { hash }), hash };
  110. }
  111. if (_event.orphan) {
  112. const event = _event;
  113. // @TODO: Should lowercase and whatnot things here instead of copy...
  114. return { type: "orphan", tag: getTag("orphan", event), filter: copy(event) };
  115. }
  116. if ((_event.address || _event.topics)) {
  117. const event = _event;
  118. const filter = {
  119. topics: ((event.topics || []).map((t) => {
  120. if (t == null) {
  121. return null;
  122. }
  123. if (Array.isArray(t)) {
  124. return concisify(t.map((t) => t.toLowerCase()));
  125. }
  126. return t.toLowerCase();
  127. }))
  128. };
  129. if (event.address) {
  130. const addresses = [];
  131. const promises = [];
  132. const addAddress = (addr) => {
  133. if ((0, index_js_6.isHexString)(addr)) {
  134. addresses.push(addr);
  135. }
  136. else {
  137. promises.push((async () => {
  138. addresses.push(await (0, index_js_1.resolveAddress)(addr, provider));
  139. })());
  140. }
  141. };
  142. if (Array.isArray(event.address)) {
  143. event.address.forEach(addAddress);
  144. }
  145. else {
  146. addAddress(event.address);
  147. }
  148. if (promises.length) {
  149. await Promise.all(promises);
  150. }
  151. filter.address = concisify(addresses.map((a) => a.toLowerCase()));
  152. }
  153. return { filter, tag: getTag("event", filter), type: "event" };
  154. }
  155. (0, index_js_6.assertArgument)(false, "unknown ProviderEvent", "event", _event);
  156. }
  157. function getTime() { return (new Date()).getTime(); }
  158. const defaultOptions = {
  159. cacheTimeout: 250,
  160. pollingInterval: 4000
  161. };
  162. /**
  163. * An **AbstractProvider** provides a base class for other sub-classes to
  164. * implement the [[Provider]] API by normalizing input arguments and
  165. * formatting output results as well as tracking events for consistent
  166. * behaviour on an eventually-consistent network.
  167. */
  168. class AbstractProvider {
  169. #subs;
  170. #plugins;
  171. // null=unpaused, true=paused+dropWhilePaused, false=paused
  172. #pausedState;
  173. #destroyed;
  174. #networkPromise;
  175. #anyNetwork;
  176. #performCache;
  177. // The most recent block number if running an event or -1 if no "block" event
  178. #lastBlockNumber;
  179. #nextTimer;
  180. #timers;
  181. #disableCcipRead;
  182. #options;
  183. /**
  184. * Create a new **AbstractProvider** connected to %%network%%, or
  185. * use the various network detection capabilities to discover the
  186. * [[Network]] if necessary.
  187. */
  188. constructor(_network, options) {
  189. this.#options = Object.assign({}, defaultOptions, options || {});
  190. if (_network === "any") {
  191. this.#anyNetwork = true;
  192. this.#networkPromise = null;
  193. }
  194. else if (_network) {
  195. const network = network_js_1.Network.from(_network);
  196. this.#anyNetwork = false;
  197. this.#networkPromise = Promise.resolve(network);
  198. setTimeout(() => { this.emit("network", network, null); }, 0);
  199. }
  200. else {
  201. this.#anyNetwork = false;
  202. this.#networkPromise = null;
  203. }
  204. this.#lastBlockNumber = -1;
  205. this.#performCache = new Map();
  206. this.#subs = new Map();
  207. this.#plugins = new Map();
  208. this.#pausedState = null;
  209. this.#destroyed = false;
  210. this.#nextTimer = 1;
  211. this.#timers = new Map();
  212. this.#disableCcipRead = false;
  213. }
  214. get pollingInterval() { return this.#options.pollingInterval; }
  215. /**
  216. * Returns ``this``, to allow an **AbstractProvider** to implement
  217. * the [[ContractRunner]] interface.
  218. */
  219. get provider() { return this; }
  220. /**
  221. * Returns all the registered plug-ins.
  222. */
  223. get plugins() {
  224. return Array.from(this.#plugins.values());
  225. }
  226. /**
  227. * Attach a new plug-in.
  228. */
  229. attachPlugin(plugin) {
  230. if (this.#plugins.get(plugin.name)) {
  231. throw new Error(`cannot replace existing plugin: ${plugin.name} `);
  232. }
  233. this.#plugins.set(plugin.name, plugin.connect(this));
  234. return this;
  235. }
  236. /**
  237. * Get a plugin by name.
  238. */
  239. getPlugin(name) {
  240. return (this.#plugins.get(name)) || null;
  241. }
  242. /**
  243. * Prevent any CCIP-read operation, regardless of whether requested
  244. * in a [[call]] using ``enableCcipRead``.
  245. */
  246. get disableCcipRead() { return this.#disableCcipRead; }
  247. set disableCcipRead(value) { this.#disableCcipRead = !!value; }
  248. // Shares multiple identical requests made during the same 250ms
  249. async #perform(req) {
  250. const timeout = this.#options.cacheTimeout;
  251. // Caching disabled
  252. if (timeout < 0) {
  253. return await this._perform(req);
  254. }
  255. // Create a tag
  256. const tag = getTag(req.method, req);
  257. let perform = this.#performCache.get(tag);
  258. if (!perform) {
  259. perform = this._perform(req);
  260. this.#performCache.set(tag, perform);
  261. setTimeout(() => {
  262. if (this.#performCache.get(tag) === perform) {
  263. this.#performCache.delete(tag);
  264. }
  265. }, timeout);
  266. }
  267. return await perform;
  268. }
  269. /**
  270. * Resolves to the data for executing the CCIP-read operations.
  271. */
  272. async ccipReadFetch(tx, calldata, urls) {
  273. if (this.disableCcipRead || urls.length === 0 || tx.to == null) {
  274. return null;
  275. }
  276. const sender = tx.to.toLowerCase();
  277. const data = calldata.toLowerCase();
  278. const errorMessages = [];
  279. for (let i = 0; i < urls.length; i++) {
  280. const url = urls[i];
  281. // URL expansion
  282. const href = url.replace("{sender}", sender).replace("{data}", data);
  283. // If no {data} is present, use POST; otherwise GET
  284. //const json: string | null = (url.indexOf("{data}") >= 0) ? null: JSON.stringify({ data, sender });
  285. //const result = await fetchJson({ url: href, errorPassThrough: true }, json, (value, response) => {
  286. // value.status = response.statusCode;
  287. // return value;
  288. //});
  289. const request = new index_js_6.FetchRequest(href);
  290. if (url.indexOf("{data}") === -1) {
  291. request.body = { data, sender };
  292. }
  293. this.emit("debug", { action: "sendCcipReadFetchRequest", request, index: i, urls });
  294. let errorMessage = "unknown error";
  295. // Fetch the resource...
  296. let resp;
  297. try {
  298. resp = await request.send();
  299. }
  300. catch (error) {
  301. // ...low-level fetch error (missing host, bad SSL, etc.),
  302. // so try next URL
  303. errorMessages.push(error.message);
  304. this.emit("debug", { action: "receiveCcipReadFetchError", request, result: { error } });
  305. continue;
  306. }
  307. try {
  308. const result = resp.bodyJson;
  309. if (result.data) {
  310. this.emit("debug", { action: "receiveCcipReadFetchResult", request, result });
  311. return result.data;
  312. }
  313. if (result.message) {
  314. errorMessage = result.message;
  315. }
  316. this.emit("debug", { action: "receiveCcipReadFetchError", request, result });
  317. }
  318. catch (error) { }
  319. // 4xx indicates the result is not present; stop
  320. (0, index_js_6.assert)(resp.statusCode < 400 || resp.statusCode >= 500, `response not found during CCIP fetch: ${errorMessage}`, "OFFCHAIN_FAULT", { reason: "404_MISSING_RESOURCE", transaction: tx, info: { url, errorMessage } });
  321. // 5xx indicates server issue; try the next url
  322. errorMessages.push(errorMessage);
  323. }
  324. (0, index_js_6.assert)(false, `error encountered during CCIP fetch: ${errorMessages.map((m) => JSON.stringify(m)).join(", ")}`, "OFFCHAIN_FAULT", {
  325. reason: "500_SERVER_ERROR",
  326. transaction: tx, info: { urls, errorMessages }
  327. });
  328. }
  329. /**
  330. * Provides the opportunity for a sub-class to wrap a block before
  331. * returning it, to add additional properties or an alternate
  332. * sub-class of [[Block]].
  333. */
  334. _wrapBlock(value, network) {
  335. return new provider_js_1.Block((0, format_js_1.formatBlock)(value), this);
  336. }
  337. /**
  338. * Provides the opportunity for a sub-class to wrap a log before
  339. * returning it, to add additional properties or an alternate
  340. * sub-class of [[Log]].
  341. */
  342. _wrapLog(value, network) {
  343. return new provider_js_1.Log((0, format_js_1.formatLog)(value), this);
  344. }
  345. /**
  346. * Provides the opportunity for a sub-class to wrap a transaction
  347. * receipt before returning it, to add additional properties or an
  348. * alternate sub-class of [[TransactionReceipt]].
  349. */
  350. _wrapTransactionReceipt(value, network) {
  351. return new provider_js_1.TransactionReceipt((0, format_js_1.formatTransactionReceipt)(value), this);
  352. }
  353. /**
  354. * Provides the opportunity for a sub-class to wrap a transaction
  355. * response before returning it, to add additional properties or an
  356. * alternate sub-class of [[TransactionResponse]].
  357. */
  358. _wrapTransactionResponse(tx, network) {
  359. return new provider_js_1.TransactionResponse((0, format_js_1.formatTransactionResponse)(tx), this);
  360. }
  361. /**
  362. * Resolves to the Network, forcing a network detection using whatever
  363. * technique the sub-class requires.
  364. *
  365. * Sub-classes **must** override this.
  366. */
  367. _detectNetwork() {
  368. (0, index_js_6.assert)(false, "sub-classes must implement this", "UNSUPPORTED_OPERATION", {
  369. operation: "_detectNetwork"
  370. });
  371. }
  372. /**
  373. * Sub-classes should use this to perform all built-in operations. All
  374. * methods sanitizes and normalizes the values passed into this.
  375. *
  376. * Sub-classes **must** override this.
  377. */
  378. async _perform(req) {
  379. (0, index_js_6.assert)(false, `unsupported method: ${req.method}`, "UNSUPPORTED_OPERATION", {
  380. operation: req.method,
  381. info: req
  382. });
  383. }
  384. // State
  385. async getBlockNumber() {
  386. const blockNumber = (0, index_js_6.getNumber)(await this.#perform({ method: "getBlockNumber" }), "%response");
  387. if (this.#lastBlockNumber >= 0) {
  388. this.#lastBlockNumber = blockNumber;
  389. }
  390. return blockNumber;
  391. }
  392. /**
  393. * Returns or resolves to the address for %%address%%, resolving ENS
  394. * names and [[Addressable]] objects and returning if already an
  395. * address.
  396. */
  397. _getAddress(address) {
  398. return (0, index_js_1.resolveAddress)(address, this);
  399. }
  400. /**
  401. * Returns or resolves to a valid block tag for %%blockTag%%, resolving
  402. * negative values and returning if already a valid block tag.
  403. */
  404. _getBlockTag(blockTag) {
  405. if (blockTag == null) {
  406. return "latest";
  407. }
  408. switch (blockTag) {
  409. case "earliest":
  410. return "0x0";
  411. case "finalized":
  412. case "latest":
  413. case "pending":
  414. case "safe":
  415. return blockTag;
  416. }
  417. if ((0, index_js_6.isHexString)(blockTag)) {
  418. if ((0, index_js_6.isHexString)(blockTag, 32)) {
  419. return blockTag;
  420. }
  421. return (0, index_js_6.toQuantity)(blockTag);
  422. }
  423. if (typeof (blockTag) === "bigint") {
  424. blockTag = (0, index_js_6.getNumber)(blockTag, "blockTag");
  425. }
  426. if (typeof (blockTag) === "number") {
  427. if (blockTag >= 0) {
  428. return (0, index_js_6.toQuantity)(blockTag);
  429. }
  430. if (this.#lastBlockNumber >= 0) {
  431. return (0, index_js_6.toQuantity)(this.#lastBlockNumber + blockTag);
  432. }
  433. return this.getBlockNumber().then((b) => (0, index_js_6.toQuantity)(b + blockTag));
  434. }
  435. (0, index_js_6.assertArgument)(false, "invalid blockTag", "blockTag", blockTag);
  436. }
  437. /**
  438. * Returns or resolves to a filter for %%filter%%, resolving any ENS
  439. * names or [[Addressable]] object and returning if already a valid
  440. * filter.
  441. */
  442. _getFilter(filter) {
  443. // Create a canonical representation of the topics
  444. const topics = (filter.topics || []).map((t) => {
  445. if (t == null) {
  446. return null;
  447. }
  448. if (Array.isArray(t)) {
  449. return concisify(t.map((t) => t.toLowerCase()));
  450. }
  451. return t.toLowerCase();
  452. });
  453. const blockHash = ("blockHash" in filter) ? filter.blockHash : undefined;
  454. const resolve = (_address, fromBlock, toBlock) => {
  455. let address = undefined;
  456. switch (_address.length) {
  457. case 0: break;
  458. case 1:
  459. address = _address[0];
  460. break;
  461. default:
  462. _address.sort();
  463. address = _address;
  464. }
  465. if (blockHash) {
  466. if (fromBlock != null || toBlock != null) {
  467. throw new Error("invalid filter");
  468. }
  469. }
  470. const filter = {};
  471. if (address) {
  472. filter.address = address;
  473. }
  474. if (topics.length) {
  475. filter.topics = topics;
  476. }
  477. if (fromBlock) {
  478. filter.fromBlock = fromBlock;
  479. }
  480. if (toBlock) {
  481. filter.toBlock = toBlock;
  482. }
  483. if (blockHash) {
  484. filter.blockHash = blockHash;
  485. }
  486. return filter;
  487. };
  488. // Addresses could be async (ENS names or Addressables)
  489. let address = [];
  490. if (filter.address) {
  491. if (Array.isArray(filter.address)) {
  492. for (const addr of filter.address) {
  493. address.push(this._getAddress(addr));
  494. }
  495. }
  496. else {
  497. address.push(this._getAddress(filter.address));
  498. }
  499. }
  500. let fromBlock = undefined;
  501. if ("fromBlock" in filter) {
  502. fromBlock = this._getBlockTag(filter.fromBlock);
  503. }
  504. let toBlock = undefined;
  505. if ("toBlock" in filter) {
  506. toBlock = this._getBlockTag(filter.toBlock);
  507. }
  508. if (address.filter((a) => (typeof (a) !== "string")).length ||
  509. (fromBlock != null && typeof (fromBlock) !== "string") ||
  510. (toBlock != null && typeof (toBlock) !== "string")) {
  511. return Promise.all([Promise.all(address), fromBlock, toBlock]).then((result) => {
  512. return resolve(result[0], result[1], result[2]);
  513. });
  514. }
  515. return resolve(address, fromBlock, toBlock);
  516. }
  517. /**
  518. * Returns or resolves to a transaction for %%request%%, resolving
  519. * any ENS names or [[Addressable]] and returning if already a valid
  520. * transaction.
  521. */
  522. _getTransactionRequest(_request) {
  523. const request = (0, provider_js_1.copyRequest)(_request);
  524. const promises = [];
  525. ["to", "from"].forEach((key) => {
  526. if (request[key] == null) {
  527. return;
  528. }
  529. const addr = (0, index_js_1.resolveAddress)(request[key], this);
  530. if (isPromise(addr)) {
  531. promises.push((async function () { request[key] = await addr; })());
  532. }
  533. else {
  534. request[key] = addr;
  535. }
  536. });
  537. if (request.blockTag != null) {
  538. const blockTag = this._getBlockTag(request.blockTag);
  539. if (isPromise(blockTag)) {
  540. promises.push((async function () { request.blockTag = await blockTag; })());
  541. }
  542. else {
  543. request.blockTag = blockTag;
  544. }
  545. }
  546. if (promises.length) {
  547. return (async function () {
  548. await Promise.all(promises);
  549. return request;
  550. })();
  551. }
  552. return request;
  553. }
  554. async getNetwork() {
  555. // No explicit network was set and this is our first time
  556. if (this.#networkPromise == null) {
  557. // Detect the current network (shared with all calls)
  558. const detectNetwork = (async () => {
  559. try {
  560. const network = await this._detectNetwork();
  561. this.emit("network", network, null);
  562. return network;
  563. }
  564. catch (error) {
  565. if (this.#networkPromise === detectNetwork) {
  566. this.#networkPromise = null;
  567. }
  568. throw error;
  569. }
  570. })();
  571. this.#networkPromise = detectNetwork;
  572. return (await detectNetwork).clone();
  573. }
  574. const networkPromise = this.#networkPromise;
  575. const [expected, actual] = await Promise.all([
  576. networkPromise,
  577. this._detectNetwork() // The actual connected network
  578. ]);
  579. if (expected.chainId !== actual.chainId) {
  580. if (this.#anyNetwork) {
  581. // The "any" network can change, so notify listeners
  582. this.emit("network", actual, expected);
  583. // Update the network if something else hasn't already changed it
  584. if (this.#networkPromise === networkPromise) {
  585. this.#networkPromise = Promise.resolve(actual);
  586. }
  587. }
  588. else {
  589. // Otherwise, we do not allow changes to the underlying network
  590. (0, index_js_6.assert)(false, `network changed: ${expected.chainId} => ${actual.chainId} `, "NETWORK_ERROR", {
  591. event: "changed"
  592. });
  593. }
  594. }
  595. return expected.clone();
  596. }
  597. async getFeeData() {
  598. const network = await this.getNetwork();
  599. const getFeeDataFunc = async () => {
  600. const { _block, gasPrice, priorityFee } = await (0, index_js_6.resolveProperties)({
  601. _block: this.#getBlock("latest", false),
  602. gasPrice: ((async () => {
  603. try {
  604. const value = await this.#perform({ method: "getGasPrice" });
  605. return (0, index_js_6.getBigInt)(value, "%response");
  606. }
  607. catch (error) { }
  608. return null;
  609. })()),
  610. priorityFee: ((async () => {
  611. try {
  612. const value = await this.#perform({ method: "getPriorityFee" });
  613. return (0, index_js_6.getBigInt)(value, "%response");
  614. }
  615. catch (error) { }
  616. return null;
  617. })())
  618. });
  619. let maxFeePerGas = null;
  620. let maxPriorityFeePerGas = null;
  621. // These are the recommended EIP-1559 heuristics for fee data
  622. const block = this._wrapBlock(_block, network);
  623. if (block && block.baseFeePerGas) {
  624. maxPriorityFeePerGas = (priorityFee != null) ? priorityFee : BigInt("1000000000");
  625. maxFeePerGas = (block.baseFeePerGas * BN_2) + maxPriorityFeePerGas;
  626. }
  627. return new provider_js_1.FeeData(gasPrice, maxFeePerGas, maxPriorityFeePerGas);
  628. };
  629. // Check for a FeeDataNetWorkPlugin
  630. const plugin = network.getPlugin("org.ethers.plugins.network.FetchUrlFeeDataPlugin");
  631. if (plugin) {
  632. const req = new index_js_6.FetchRequest(plugin.url);
  633. const feeData = await plugin.processFunc(getFeeDataFunc, this, req);
  634. return new provider_js_1.FeeData(feeData.gasPrice, feeData.maxFeePerGas, feeData.maxPriorityFeePerGas);
  635. }
  636. return await getFeeDataFunc();
  637. }
  638. async estimateGas(_tx) {
  639. let tx = this._getTransactionRequest(_tx);
  640. if (isPromise(tx)) {
  641. tx = await tx;
  642. }
  643. return (0, index_js_6.getBigInt)(await this.#perform({
  644. method: "estimateGas", transaction: tx
  645. }), "%response");
  646. }
  647. async #call(tx, blockTag, attempt) {
  648. (0, index_js_6.assert)(attempt < MAX_CCIP_REDIRECTS, "CCIP read exceeded maximum redirections", "OFFCHAIN_FAULT", {
  649. reason: "TOO_MANY_REDIRECTS",
  650. transaction: Object.assign({}, tx, { blockTag, enableCcipRead: true })
  651. });
  652. // This came in as a PerformActionTransaction, so to/from are safe; we can cast
  653. const transaction = (0, provider_js_1.copyRequest)(tx);
  654. try {
  655. return (0, index_js_6.hexlify)(await this._perform({ method: "call", transaction, blockTag }));
  656. }
  657. catch (error) {
  658. // CCIP Read OffchainLookup
  659. if (!this.disableCcipRead && (0, index_js_6.isCallException)(error) && error.data && attempt >= 0 && blockTag === "latest" && transaction.to != null && (0, index_js_6.dataSlice)(error.data, 0, 4) === "0x556f1830") {
  660. const data = error.data;
  661. const txSender = await (0, index_js_1.resolveAddress)(transaction.to, this);
  662. // Parse the CCIP Read Arguments
  663. let ccipArgs;
  664. try {
  665. ccipArgs = parseOffchainLookup((0, index_js_6.dataSlice)(error.data, 4));
  666. }
  667. catch (error) {
  668. (0, index_js_6.assert)(false, error.message, "OFFCHAIN_FAULT", {
  669. reason: "BAD_DATA", transaction, info: { data }
  670. });
  671. }
  672. // Check the sender of the OffchainLookup matches the transaction
  673. (0, index_js_6.assert)(ccipArgs.sender.toLowerCase() === txSender.toLowerCase(), "CCIP Read sender mismatch", "CALL_EXCEPTION", {
  674. action: "call",
  675. data,
  676. reason: "OffchainLookup",
  677. transaction: transaction,
  678. invocation: null,
  679. revert: {
  680. signature: "OffchainLookup(address,string[],bytes,bytes4,bytes)",
  681. name: "OffchainLookup",
  682. args: ccipArgs.errorArgs
  683. }
  684. });
  685. const ccipResult = await this.ccipReadFetch(transaction, ccipArgs.calldata, ccipArgs.urls);
  686. (0, index_js_6.assert)(ccipResult != null, "CCIP Read failed to fetch data", "OFFCHAIN_FAULT", {
  687. reason: "FETCH_FAILED", transaction, info: { data: error.data, errorArgs: ccipArgs.errorArgs }
  688. });
  689. const tx = {
  690. to: txSender,
  691. data: (0, index_js_6.concat)([ccipArgs.selector, encodeBytes([ccipResult, ccipArgs.extraData])])
  692. };
  693. this.emit("debug", { action: "sendCcipReadCall", transaction: tx });
  694. try {
  695. const result = await this.#call(tx, blockTag, attempt + 1);
  696. this.emit("debug", { action: "receiveCcipReadCallResult", transaction: Object.assign({}, tx), result });
  697. return result;
  698. }
  699. catch (error) {
  700. this.emit("debug", { action: "receiveCcipReadCallError", transaction: Object.assign({}, tx), error });
  701. throw error;
  702. }
  703. }
  704. throw error;
  705. }
  706. }
  707. async #checkNetwork(promise) {
  708. const { value } = await (0, index_js_6.resolveProperties)({
  709. network: this.getNetwork(),
  710. value: promise
  711. });
  712. return value;
  713. }
  714. async call(_tx) {
  715. const { tx, blockTag } = await (0, index_js_6.resolveProperties)({
  716. tx: this._getTransactionRequest(_tx),
  717. blockTag: this._getBlockTag(_tx.blockTag)
  718. });
  719. return await this.#checkNetwork(this.#call(tx, blockTag, _tx.enableCcipRead ? 0 : -1));
  720. }
  721. // Account
  722. async #getAccountValue(request, _address, _blockTag) {
  723. let address = this._getAddress(_address);
  724. let blockTag = this._getBlockTag(_blockTag);
  725. if (typeof (address) !== "string" || typeof (blockTag) !== "string") {
  726. [address, blockTag] = await Promise.all([address, blockTag]);
  727. }
  728. return await this.#checkNetwork(this.#perform(Object.assign(request, { address, blockTag })));
  729. }
  730. async getBalance(address, blockTag) {
  731. return (0, index_js_6.getBigInt)(await this.#getAccountValue({ method: "getBalance" }, address, blockTag), "%response");
  732. }
  733. async getTransactionCount(address, blockTag) {
  734. return (0, index_js_6.getNumber)(await this.#getAccountValue({ method: "getTransactionCount" }, address, blockTag), "%response");
  735. }
  736. async getCode(address, blockTag) {
  737. return (0, index_js_6.hexlify)(await this.#getAccountValue({ method: "getCode" }, address, blockTag));
  738. }
  739. async getStorage(address, _position, blockTag) {
  740. const position = (0, index_js_6.getBigInt)(_position, "position");
  741. return (0, index_js_6.hexlify)(await this.#getAccountValue({ method: "getStorage", position }, address, blockTag));
  742. }
  743. // Write
  744. async broadcastTransaction(signedTx) {
  745. const { blockNumber, hash, network } = await (0, index_js_6.resolveProperties)({
  746. blockNumber: this.getBlockNumber(),
  747. hash: this._perform({
  748. method: "broadcastTransaction",
  749. signedTransaction: signedTx
  750. }),
  751. network: this.getNetwork()
  752. });
  753. const tx = index_js_5.Transaction.from(signedTx);
  754. if (tx.hash !== hash) {
  755. throw new Error("@TODO: the returned hash did not match");
  756. }
  757. return this._wrapTransactionResponse(tx, network).replaceableTransaction(blockNumber);
  758. }
  759. async #getBlock(block, includeTransactions) {
  760. // @TODO: Add CustomBlockPlugin check
  761. if ((0, index_js_6.isHexString)(block, 32)) {
  762. return await this.#perform({
  763. method: "getBlock", blockHash: block, includeTransactions
  764. });
  765. }
  766. let blockTag = this._getBlockTag(block);
  767. if (typeof (blockTag) !== "string") {
  768. blockTag = await blockTag;
  769. }
  770. return await this.#perform({
  771. method: "getBlock", blockTag, includeTransactions
  772. });
  773. }
  774. // Queries
  775. async getBlock(block, prefetchTxs) {
  776. const { network, params } = await (0, index_js_6.resolveProperties)({
  777. network: this.getNetwork(),
  778. params: this.#getBlock(block, !!prefetchTxs)
  779. });
  780. if (params == null) {
  781. return null;
  782. }
  783. return this._wrapBlock(params, network);
  784. }
  785. async getTransaction(hash) {
  786. const { network, params } = await (0, index_js_6.resolveProperties)({
  787. network: this.getNetwork(),
  788. params: this.#perform({ method: "getTransaction", hash })
  789. });
  790. if (params == null) {
  791. return null;
  792. }
  793. return this._wrapTransactionResponse(params, network);
  794. }
  795. async getTransactionReceipt(hash) {
  796. const { network, params } = await (0, index_js_6.resolveProperties)({
  797. network: this.getNetwork(),
  798. params: this.#perform({ method: "getTransactionReceipt", hash })
  799. });
  800. if (params == null) {
  801. return null;
  802. }
  803. // Some backends did not backfill the effectiveGasPrice into old transactions
  804. // in the receipt, so we look it up manually and inject it.
  805. if (params.gasPrice == null && params.effectiveGasPrice == null) {
  806. const tx = await this.#perform({ method: "getTransaction", hash });
  807. if (tx == null) {
  808. throw new Error("report this; could not find tx or effectiveGasPrice");
  809. }
  810. params.effectiveGasPrice = tx.gasPrice;
  811. }
  812. return this._wrapTransactionReceipt(params, network);
  813. }
  814. async getTransactionResult(hash) {
  815. const { result } = await (0, index_js_6.resolveProperties)({
  816. network: this.getNetwork(),
  817. result: this.#perform({ method: "getTransactionResult", hash })
  818. });
  819. if (result == null) {
  820. return null;
  821. }
  822. return (0, index_js_6.hexlify)(result);
  823. }
  824. // Bloom-filter Queries
  825. async getLogs(_filter) {
  826. let filter = this._getFilter(_filter);
  827. if (isPromise(filter)) {
  828. filter = await filter;
  829. }
  830. const { network, params } = await (0, index_js_6.resolveProperties)({
  831. network: this.getNetwork(),
  832. params: this.#perform({ method: "getLogs", filter })
  833. });
  834. return params.map((p) => this._wrapLog(p, network));
  835. }
  836. // ENS
  837. _getProvider(chainId) {
  838. (0, index_js_6.assert)(false, "provider cannot connect to target network", "UNSUPPORTED_OPERATION", {
  839. operation: "_getProvider()"
  840. });
  841. }
  842. async getResolver(name) {
  843. return await ens_resolver_js_1.EnsResolver.fromName(this, name);
  844. }
  845. async getAvatar(name) {
  846. const resolver = await this.getResolver(name);
  847. if (resolver) {
  848. return await resolver.getAvatar();
  849. }
  850. return null;
  851. }
  852. async resolveName(name) {
  853. const resolver = await this.getResolver(name);
  854. if (resolver) {
  855. return await resolver.getAddress();
  856. }
  857. return null;
  858. }
  859. async lookupAddress(address) {
  860. address = (0, index_js_1.getAddress)(address);
  861. const node = (0, index_js_4.namehash)(address.substring(2).toLowerCase() + ".addr.reverse");
  862. try {
  863. const ensAddr = await ens_resolver_js_1.EnsResolver.getEnsAddress(this);
  864. const ensContract = new index_js_3.Contract(ensAddr, [
  865. "function resolver(bytes32) view returns (address)"
  866. ], this);
  867. const resolver = await ensContract.resolver(node);
  868. if (resolver == null || resolver === index_js_2.ZeroAddress) {
  869. return null;
  870. }
  871. const resolverContract = new index_js_3.Contract(resolver, [
  872. "function name(bytes32) view returns (string)"
  873. ], this);
  874. const name = await resolverContract.name(node);
  875. // Failed forward resolution
  876. const check = await this.resolveName(name);
  877. if (check !== address) {
  878. return null;
  879. }
  880. return name;
  881. }
  882. catch (error) {
  883. // No data was returned from the resolver
  884. if ((0, index_js_6.isError)(error, "BAD_DATA") && error.value === "0x") {
  885. return null;
  886. }
  887. // Something reerted
  888. if ((0, index_js_6.isError)(error, "CALL_EXCEPTION")) {
  889. return null;
  890. }
  891. throw error;
  892. }
  893. return null;
  894. }
  895. async waitForTransaction(hash, _confirms, timeout) {
  896. const confirms = (_confirms != null) ? _confirms : 1;
  897. if (confirms === 0) {
  898. return this.getTransactionReceipt(hash);
  899. }
  900. return new Promise(async (resolve, reject) => {
  901. let timer = null;
  902. const listener = (async (blockNumber) => {
  903. try {
  904. const receipt = await this.getTransactionReceipt(hash);
  905. if (receipt != null) {
  906. if (blockNumber - receipt.blockNumber + 1 >= confirms) {
  907. resolve(receipt);
  908. //this.off("block", listener);
  909. if (timer) {
  910. clearTimeout(timer);
  911. timer = null;
  912. }
  913. return;
  914. }
  915. }
  916. }
  917. catch (error) {
  918. console.log("EEE", error);
  919. }
  920. this.once("block", listener);
  921. });
  922. if (timeout != null) {
  923. timer = setTimeout(() => {
  924. if (timer == null) {
  925. return;
  926. }
  927. timer = null;
  928. this.off("block", listener);
  929. reject((0, index_js_6.makeError)("timeout", "TIMEOUT", { reason: "timeout" }));
  930. }, timeout);
  931. }
  932. listener(await this.getBlockNumber());
  933. });
  934. }
  935. async waitForBlock(blockTag) {
  936. (0, index_js_6.assert)(false, "not implemented yet", "NOT_IMPLEMENTED", {
  937. operation: "waitForBlock"
  938. });
  939. }
  940. /**
  941. * Clear a timer created using the [[_setTimeout]] method.
  942. */
  943. _clearTimeout(timerId) {
  944. const timer = this.#timers.get(timerId);
  945. if (!timer) {
  946. return;
  947. }
  948. if (timer.timer) {
  949. clearTimeout(timer.timer);
  950. }
  951. this.#timers.delete(timerId);
  952. }
  953. /**
  954. * Create a timer that will execute %%func%% after at least %%timeout%%
  955. * (in ms). If %%timeout%% is unspecified, then %%func%% will execute
  956. * in the next event loop.
  957. *
  958. * [Pausing](AbstractProvider-paused) the provider will pause any
  959. * associated timers.
  960. */
  961. _setTimeout(_func, timeout) {
  962. if (timeout == null) {
  963. timeout = 0;
  964. }
  965. const timerId = this.#nextTimer++;
  966. const func = () => {
  967. this.#timers.delete(timerId);
  968. _func();
  969. };
  970. if (this.paused) {
  971. this.#timers.set(timerId, { timer: null, func, time: timeout });
  972. }
  973. else {
  974. const timer = setTimeout(func, timeout);
  975. this.#timers.set(timerId, { timer, func, time: getTime() });
  976. }
  977. return timerId;
  978. }
  979. /**
  980. * Perform %%func%% on each subscriber.
  981. */
  982. _forEachSubscriber(func) {
  983. for (const sub of this.#subs.values()) {
  984. func(sub.subscriber);
  985. }
  986. }
  987. /**
  988. * Sub-classes may override this to customize subscription
  989. * implementations.
  990. */
  991. _getSubscriber(sub) {
  992. switch (sub.type) {
  993. case "debug":
  994. case "error":
  995. case "network":
  996. return new UnmanagedSubscriber(sub.type);
  997. case "block": {
  998. const subscriber = new subscriber_polling_js_1.PollingBlockSubscriber(this);
  999. subscriber.pollingInterval = this.pollingInterval;
  1000. return subscriber;
  1001. }
  1002. case "safe":
  1003. case "finalized":
  1004. return new subscriber_polling_js_1.PollingBlockTagSubscriber(this, sub.type);
  1005. case "event":
  1006. return new subscriber_polling_js_1.PollingEventSubscriber(this, sub.filter);
  1007. case "transaction":
  1008. return new subscriber_polling_js_1.PollingTransactionSubscriber(this, sub.hash);
  1009. case "orphan":
  1010. return new subscriber_polling_js_1.PollingOrphanSubscriber(this, sub.filter);
  1011. }
  1012. throw new Error(`unsupported event: ${sub.type}`);
  1013. }
  1014. /**
  1015. * If a [[Subscriber]] fails and needs to replace itself, this
  1016. * method may be used.
  1017. *
  1018. * For example, this is used for providers when using the
  1019. * ``eth_getFilterChanges`` method, which can return null if state
  1020. * filters are not supported by the backend, allowing the Subscriber
  1021. * to swap in a [[PollingEventSubscriber]].
  1022. */
  1023. _recoverSubscriber(oldSub, newSub) {
  1024. for (const sub of this.#subs.values()) {
  1025. if (sub.subscriber === oldSub) {
  1026. if (sub.started) {
  1027. sub.subscriber.stop();
  1028. }
  1029. sub.subscriber = newSub;
  1030. if (sub.started) {
  1031. newSub.start();
  1032. }
  1033. if (this.#pausedState != null) {
  1034. newSub.pause(this.#pausedState);
  1035. }
  1036. break;
  1037. }
  1038. }
  1039. }
  1040. async #hasSub(event, emitArgs) {
  1041. let sub = await getSubscription(event, this);
  1042. // This is a log that is removing an existing log; we actually want
  1043. // to emit an orphan event for the removed log
  1044. if (sub.type === "event" && emitArgs && emitArgs.length > 0 && emitArgs[0].removed === true) {
  1045. sub = await getSubscription({ orphan: "drop-log", log: emitArgs[0] }, this);
  1046. }
  1047. return this.#subs.get(sub.tag) || null;
  1048. }
  1049. async #getSub(event) {
  1050. const subscription = await getSubscription(event, this);
  1051. // Prevent tampering with our tag in any subclass' _getSubscriber
  1052. const tag = subscription.tag;
  1053. let sub = this.#subs.get(tag);
  1054. if (!sub) {
  1055. const subscriber = this._getSubscriber(subscription);
  1056. const addressableMap = new WeakMap();
  1057. const nameMap = new Map();
  1058. sub = { subscriber, tag, addressableMap, nameMap, started: false, listeners: [] };
  1059. this.#subs.set(tag, sub);
  1060. }
  1061. return sub;
  1062. }
  1063. async on(event, listener) {
  1064. const sub = await this.#getSub(event);
  1065. sub.listeners.push({ listener, once: false });
  1066. if (!sub.started) {
  1067. sub.subscriber.start();
  1068. sub.started = true;
  1069. if (this.#pausedState != null) {
  1070. sub.subscriber.pause(this.#pausedState);
  1071. }
  1072. }
  1073. return this;
  1074. }
  1075. async once(event, listener) {
  1076. const sub = await this.#getSub(event);
  1077. sub.listeners.push({ listener, once: true });
  1078. if (!sub.started) {
  1079. sub.subscriber.start();
  1080. sub.started = true;
  1081. if (this.#pausedState != null) {
  1082. sub.subscriber.pause(this.#pausedState);
  1083. }
  1084. }
  1085. return this;
  1086. }
  1087. async emit(event, ...args) {
  1088. const sub = await this.#hasSub(event, args);
  1089. // If there is not subscription or if a recent emit removed
  1090. // the last of them (which also deleted the sub) do nothing
  1091. if (!sub || sub.listeners.length === 0) {
  1092. return false;
  1093. }
  1094. ;
  1095. const count = sub.listeners.length;
  1096. sub.listeners = sub.listeners.filter(({ listener, once }) => {
  1097. const payload = new index_js_6.EventPayload(this, (once ? null : listener), event);
  1098. try {
  1099. listener.call(this, ...args, payload);
  1100. }
  1101. catch (error) { }
  1102. return !once;
  1103. });
  1104. if (sub.listeners.length === 0) {
  1105. if (sub.started) {
  1106. sub.subscriber.stop();
  1107. }
  1108. this.#subs.delete(sub.tag);
  1109. }
  1110. return (count > 0);
  1111. }
  1112. async listenerCount(event) {
  1113. if (event) {
  1114. const sub = await this.#hasSub(event);
  1115. if (!sub) {
  1116. return 0;
  1117. }
  1118. return sub.listeners.length;
  1119. }
  1120. let total = 0;
  1121. for (const { listeners } of this.#subs.values()) {
  1122. total += listeners.length;
  1123. }
  1124. return total;
  1125. }
  1126. async listeners(event) {
  1127. if (event) {
  1128. const sub = await this.#hasSub(event);
  1129. if (!sub) {
  1130. return [];
  1131. }
  1132. return sub.listeners.map(({ listener }) => listener);
  1133. }
  1134. let result = [];
  1135. for (const { listeners } of this.#subs.values()) {
  1136. result = result.concat(listeners.map(({ listener }) => listener));
  1137. }
  1138. return result;
  1139. }
  1140. async off(event, listener) {
  1141. const sub = await this.#hasSub(event);
  1142. if (!sub) {
  1143. return this;
  1144. }
  1145. if (listener) {
  1146. const index = sub.listeners.map(({ listener }) => listener).indexOf(listener);
  1147. if (index >= 0) {
  1148. sub.listeners.splice(index, 1);
  1149. }
  1150. }
  1151. if (!listener || sub.listeners.length === 0) {
  1152. if (sub.started) {
  1153. sub.subscriber.stop();
  1154. }
  1155. this.#subs.delete(sub.tag);
  1156. }
  1157. return this;
  1158. }
  1159. async removeAllListeners(event) {
  1160. if (event) {
  1161. const { tag, started, subscriber } = await this.#getSub(event);
  1162. if (started) {
  1163. subscriber.stop();
  1164. }
  1165. this.#subs.delete(tag);
  1166. }
  1167. else {
  1168. for (const [tag, { started, subscriber }] of this.#subs) {
  1169. if (started) {
  1170. subscriber.stop();
  1171. }
  1172. this.#subs.delete(tag);
  1173. }
  1174. }
  1175. return this;
  1176. }
  1177. // Alias for "on"
  1178. async addListener(event, listener) {
  1179. return await this.on(event, listener);
  1180. }
  1181. // Alias for "off"
  1182. async removeListener(event, listener) {
  1183. return this.off(event, listener);
  1184. }
  1185. /**
  1186. * If this provider has been destroyed using the [[destroy]] method.
  1187. *
  1188. * Once destroyed, all resources are reclaimed, internal event loops
  1189. * and timers are cleaned up and no further requests may be sent to
  1190. * the provider.
  1191. */
  1192. get destroyed() {
  1193. return this.#destroyed;
  1194. }
  1195. /**
  1196. * Sub-classes may use this to shutdown any sockets or release their
  1197. * resources and reject any pending requests.
  1198. *
  1199. * Sub-classes **must** call ``super.destroy()``.
  1200. */
  1201. destroy() {
  1202. // Stop all listeners
  1203. this.removeAllListeners();
  1204. // Shut down all tiemrs
  1205. for (const timerId of this.#timers.keys()) {
  1206. this._clearTimeout(timerId);
  1207. }
  1208. this.#destroyed = true;
  1209. }
  1210. /**
  1211. * Whether the provider is currently paused.
  1212. *
  1213. * A paused provider will not emit any events, and generally should
  1214. * not make any requests to the network, but that is up to sub-classes
  1215. * to manage.
  1216. *
  1217. * Setting ``paused = true`` is identical to calling ``.pause(false)``,
  1218. * which will buffer any events that occur while paused until the
  1219. * provider is unpaused.
  1220. */
  1221. get paused() { return (this.#pausedState != null); }
  1222. set paused(pause) {
  1223. if (!!pause === this.paused) {
  1224. return;
  1225. }
  1226. if (this.paused) {
  1227. this.resume();
  1228. }
  1229. else {
  1230. this.pause(false);
  1231. }
  1232. }
  1233. /**
  1234. * Pause the provider. If %%dropWhilePaused%%, any events that occur
  1235. * while paused are dropped, otherwise all events will be emitted once
  1236. * the provider is unpaused.
  1237. */
  1238. pause(dropWhilePaused) {
  1239. this.#lastBlockNumber = -1;
  1240. if (this.#pausedState != null) {
  1241. if (this.#pausedState == !!dropWhilePaused) {
  1242. return;
  1243. }
  1244. (0, index_js_6.assert)(false, "cannot change pause type; resume first", "UNSUPPORTED_OPERATION", {
  1245. operation: "pause"
  1246. });
  1247. }
  1248. this._forEachSubscriber((s) => s.pause(dropWhilePaused));
  1249. this.#pausedState = !!dropWhilePaused;
  1250. for (const timer of this.#timers.values()) {
  1251. // Clear the timer
  1252. if (timer.timer) {
  1253. clearTimeout(timer.timer);
  1254. }
  1255. // Remaining time needed for when we become unpaused
  1256. timer.time = getTime() - timer.time;
  1257. }
  1258. }
  1259. /**
  1260. * Resume the provider.
  1261. */
  1262. resume() {
  1263. if (this.#pausedState == null) {
  1264. return;
  1265. }
  1266. this._forEachSubscriber((s) => s.resume());
  1267. this.#pausedState = null;
  1268. for (const timer of this.#timers.values()) {
  1269. // Remaining time when we were paused
  1270. let timeout = timer.time;
  1271. if (timeout < 0) {
  1272. timeout = 0;
  1273. }
  1274. // Start time (in cause paused, so we con compute remaininf time)
  1275. timer.time = getTime();
  1276. // Start the timer
  1277. setTimeout(timer.func, timeout);
  1278. }
  1279. }
  1280. }
  1281. exports.AbstractProvider = AbstractProvider;
  1282. function _parseString(result, start) {
  1283. try {
  1284. const bytes = _parseBytes(result, start);
  1285. if (bytes) {
  1286. return (0, index_js_6.toUtf8String)(bytes);
  1287. }
  1288. }
  1289. catch (error) { }
  1290. return null;
  1291. }
  1292. function _parseBytes(result, start) {
  1293. if (result === "0x") {
  1294. return null;
  1295. }
  1296. try {
  1297. const offset = (0, index_js_6.getNumber)((0, index_js_6.dataSlice)(result, start, start + 32));
  1298. const length = (0, index_js_6.getNumber)((0, index_js_6.dataSlice)(result, offset, offset + 32));
  1299. return (0, index_js_6.dataSlice)(result, offset + 32, offset + 32 + length);
  1300. }
  1301. catch (error) { }
  1302. return null;
  1303. }
  1304. function numPad(value) {
  1305. const result = (0, index_js_6.toBeArray)(value);
  1306. if (result.length > 32) {
  1307. throw new Error("internal; should not happen");
  1308. }
  1309. const padded = new Uint8Array(32);
  1310. padded.set(result, 32 - result.length);
  1311. return padded;
  1312. }
  1313. function bytesPad(value) {
  1314. if ((value.length % 32) === 0) {
  1315. return value;
  1316. }
  1317. const result = new Uint8Array(Math.ceil(value.length / 32) * 32);
  1318. result.set(value);
  1319. return result;
  1320. }
  1321. const empty = new Uint8Array([]);
  1322. // ABI Encodes a series of (bytes, bytes, ...)
  1323. function encodeBytes(datas) {
  1324. const result = [];
  1325. let byteCount = 0;
  1326. // Add place-holders for pointers as we add items
  1327. for (let i = 0; i < datas.length; i++) {
  1328. result.push(empty);
  1329. byteCount += 32;
  1330. }
  1331. for (let i = 0; i < datas.length; i++) {
  1332. const data = (0, index_js_6.getBytes)(datas[i]);
  1333. // Update the bytes offset
  1334. result[i] = numPad(byteCount);
  1335. // The length and padded value of data
  1336. result.push(numPad(data.length));
  1337. result.push(bytesPad(data));
  1338. byteCount += 32 + Math.ceil(data.length / 32) * 32;
  1339. }
  1340. return (0, index_js_6.concat)(result);
  1341. }
  1342. const zeros = "0x0000000000000000000000000000000000000000000000000000000000000000";
  1343. function parseOffchainLookup(data) {
  1344. const result = {
  1345. sender: "", urls: [], calldata: "", selector: "", extraData: "", errorArgs: []
  1346. };
  1347. (0, index_js_6.assert)((0, index_js_6.dataLength)(data) >= 5 * 32, "insufficient OffchainLookup data", "OFFCHAIN_FAULT", {
  1348. reason: "insufficient OffchainLookup data"
  1349. });
  1350. const sender = (0, index_js_6.dataSlice)(data, 0, 32);
  1351. (0, index_js_6.assert)((0, index_js_6.dataSlice)(sender, 0, 12) === (0, index_js_6.dataSlice)(zeros, 0, 12), "corrupt OffchainLookup sender", "OFFCHAIN_FAULT", {
  1352. reason: "corrupt OffchainLookup sender"
  1353. });
  1354. result.sender = (0, index_js_6.dataSlice)(sender, 12);
  1355. // Read the URLs from the response
  1356. try {
  1357. const urls = [];
  1358. const urlsOffset = (0, index_js_6.getNumber)((0, index_js_6.dataSlice)(data, 32, 64));
  1359. const urlsLength = (0, index_js_6.getNumber)((0, index_js_6.dataSlice)(data, urlsOffset, urlsOffset + 32));
  1360. const urlsData = (0, index_js_6.dataSlice)(data, urlsOffset + 32);
  1361. for (let u = 0; u < urlsLength; u++) {
  1362. const url = _parseString(urlsData, u * 32);
  1363. if (url == null) {
  1364. throw new Error("abort");
  1365. }
  1366. urls.push(url);
  1367. }
  1368. result.urls = urls;
  1369. }
  1370. catch (error) {
  1371. (0, index_js_6.assert)(false, "corrupt OffchainLookup urls", "OFFCHAIN_FAULT", {
  1372. reason: "corrupt OffchainLookup urls"
  1373. });
  1374. }
  1375. // Get the CCIP calldata to forward
  1376. try {
  1377. const calldata = _parseBytes(data, 64);
  1378. if (calldata == null) {
  1379. throw new Error("abort");
  1380. }
  1381. result.calldata = calldata;
  1382. }
  1383. catch (error) {
  1384. (0, index_js_6.assert)(false, "corrupt OffchainLookup calldata", "OFFCHAIN_FAULT", {
  1385. reason: "corrupt OffchainLookup calldata"
  1386. });
  1387. }
  1388. // Get the callbackSelector (bytes4)
  1389. (0, index_js_6.assert)((0, index_js_6.dataSlice)(data, 100, 128) === (0, index_js_6.dataSlice)(zeros, 0, 28), "corrupt OffchainLookup callbaackSelector", "OFFCHAIN_FAULT", {
  1390. reason: "corrupt OffchainLookup callbaackSelector"
  1391. });
  1392. result.selector = (0, index_js_6.dataSlice)(data, 96, 100);
  1393. // Get the extra data to send back to the contract as context
  1394. try {
  1395. const extraData = _parseBytes(data, 128);
  1396. if (extraData == null) {
  1397. throw new Error("abort");
  1398. }
  1399. result.extraData = extraData;
  1400. }
  1401. catch (error) {
  1402. (0, index_js_6.assert)(false, "corrupt OffchainLookup extraData", "OFFCHAIN_FAULT", {
  1403. reason: "corrupt OffchainLookup extraData"
  1404. });
  1405. }
  1406. result.errorArgs = "sender,urls,calldata,selector,extraData".split(/,/).map((k) => result[k]);
  1407. return result;
  1408. }
  1409. //# sourceMappingURL=abstract-provider.js.map