ponder 0.9.0-next.9 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,7 +6,7 @@ import {
6
6
  never,
7
7
  promiseWithResolvers,
8
8
  serialize
9
- } from "../chunk-KZYYPB5L.js";
9
+ } from "../chunk-IFTUFVCL.js";
10
10
  import {
11
11
  onchain
12
12
  } from "../chunk-K2TLRLX3.js";
@@ -606,6 +606,7 @@ var buildOptions = ({ cliOptions }) => {
606
606
  rootDir,
607
607
  configFile: path2.join(rootDir, cliOptions.config),
608
608
  schemaFile: path2.join(rootDir, "ponder.schema.ts"),
609
+ apiDir: path2.join(rootDir, "src", "api"),
609
610
  apiFile: path2.join(rootDir, "src", "api", "index.ts"),
610
611
  indexingDir: path2.join(rootDir, "src"),
611
612
  generatedDir: path2.join(rootDir, "generated"),
@@ -1983,6 +1984,13 @@ async function buildConfigAndIndexingFunctions({
1983
1984
  const excludedRegisteredEventSelectors = registeredEventSelectors.filter(
1984
1985
  (s) => filteredEventSelectors.includes(s) === false
1985
1986
  );
1987
+ for (const selector of filteredEventSelectors) {
1988
+ if (registeredEventSelectors.includes(selector) === false) {
1989
+ throw new Error(
1990
+ `Validation failed: Event selector '${abiEvents.bySelector[selector]?.safeName}' is used in a filter but does not have a corresponding indexing function.`
1991
+ );
1992
+ }
1993
+ }
1986
1994
  if (excludedRegisteredEventSelectors.length > 0) {
1987
1995
  topicsArray.push({
1988
1996
  topic0: excludedRegisteredEventSelectors,
@@ -3344,6 +3352,7 @@ var createBuild = async ({
3344
3352
  const escapedIndexingDir = common.options.indexingDir.replace(/\\/g, "/").replace(escapeRegex, "\\$&");
3345
3353
  const indexingRegex = new RegExp(`^${escapedIndexingDir}/.*\\.(ts|js)$`);
3346
3354
  const indexingPattern = path5.join(common.options.indexingDir, "**/*.{js,mjs,ts,mts}").replace(/\\/g, "/");
3355
+ const apiPattern = path5.join(common.options.apiDir, "**/*.{js,mjs,ts,mts}").replace(/\\/g, "/");
3347
3356
  const viteLogger = {
3348
3357
  warnedMessages: /* @__PURE__ */ new Set(),
3349
3358
  loggedErrors: /* @__PURE__ */ new WeakSet(),
@@ -3445,7 +3454,7 @@ var createBuild = async ({
3445
3454
  },
3446
3455
  async executeIndexingFunctions() {
3447
3456
  const files = glob.sync(indexingPattern, {
3448
- ignore: common.options.apiFile
3457
+ ignore: glob.sync(apiPattern)
3449
3458
  });
3450
3459
  const executeResults = await Promise.all(
3451
3460
  files.map(async (file) => ({
@@ -3504,6 +3513,8 @@ var createBuild = async ({
3504
3513
  });
3505
3514
  return { status: "error", error };
3506
3515
  }
3516
+ viteNodeRunner.moduleCache.invalidateDepTree(glob.sync(apiPattern));
3517
+ viteNodeRunner.moduleCache.deleteByModuleId("ponder:api");
3507
3518
  const executeResult = await executeFile({
3508
3519
  file: common.options.apiFile
3509
3520
  });
@@ -3713,12 +3724,10 @@ var createBuild = async ({
3713
3724
  ]);
3714
3725
  viteNodeRunner.moduleCache.invalidateDepTree(
3715
3726
  glob.sync(indexingPattern, {
3716
- ignore: common.options.apiFile
3727
+ ignore: glob.sync(apiPattern)
3717
3728
  })
3718
3729
  );
3719
- viteNodeRunner.moduleCache.invalidateDepTree([
3720
- common.options.apiFile
3721
- ]);
3730
+ viteNodeRunner.moduleCache.invalidateDepTree(glob.sync(apiPattern));
3722
3731
  viteNodeRunner.moduleCache.deleteByModuleId("ponder:registry");
3723
3732
  viteNodeRunner.moduleCache.deleteByModuleId("ponder:api");
3724
3733
  onReload("indexing");
@@ -4556,6 +4565,69 @@ function createPool(config, logger) {
4556
4565
  });
4557
4566
  return pool;
4558
4567
  }
4568
+ function createReadonlyPool(config, logger, namespace) {
4569
+ class ReadonlyClient extends pg.Client {
4570
+ // @ts-expect-error
4571
+ connect(callback) {
4572
+ if (callback) {
4573
+ super.connect(() => {
4574
+ this.query(
4575
+ `
4576
+ SET search_path = "${namespace}";
4577
+ SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY;
4578
+ SET work_mem = '512MB';
4579
+ SET statement_timeout = '500ms';
4580
+ SET lock_timeout = '500ms';
4581
+ `,
4582
+ callback
4583
+ );
4584
+ });
4585
+ } else {
4586
+ return super.connect().then(
4587
+ () => this.query(
4588
+ `
4589
+ SET search_path = "${namespace}";
4590
+ SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY;
4591
+ SET work_mem = '512MB';
4592
+ SET statement_timeout = '500ms';
4593
+ SET lock_timeout = '500ms';
4594
+ `
4595
+ ).then(() => {
4596
+ })
4597
+ );
4598
+ }
4599
+ }
4600
+ }
4601
+ const pool = new pg.Pool({
4602
+ // https://stackoverflow.com/questions/59155572/how-to-set-query-timeout-in-relation-to-statement-timeout
4603
+ statement_timeout: 2 * 60 * 1e3,
4604
+ // 2 minutes
4605
+ // @ts-expect-error: The custom Client is an undocumented option.
4606
+ Client: ReadonlyClient,
4607
+ ...config
4608
+ });
4609
+ function onError2(error) {
4610
+ const client = error.client;
4611
+ const pid = client?.processID ?? "unknown";
4612
+ const applicationName = client?.connectionParameters?.application_name ?? "unknown";
4613
+ logger.error({
4614
+ service: "postgres",
4615
+ msg: `Pool error (application_name: ${applicationName}, pid: ${pid})`,
4616
+ error
4617
+ });
4618
+ }
4619
+ function onNotice(notice) {
4620
+ logger.debug({
4621
+ service: "postgres",
4622
+ msg: `notice: ${notice.message} (code: ${notice.code})`
4623
+ });
4624
+ }
4625
+ pool.on("error", onError2);
4626
+ pool.on("connect", (client) => {
4627
+ client.on("notice", onNotice);
4628
+ });
4629
+ return pool;
4630
+ }
4559
4631
 
4560
4632
  // src/utils/pglite.ts
4561
4633
  import { mkdirSync } from "node:fs";
@@ -4628,17 +4700,6 @@ var createDatabase = async ({
4628
4700
  },
4629
4701
  plugins: [new WithSchemaPlugin(namespace)]
4630
4702
  }),
4631
- readonly: new Kysely({
4632
- dialect: kyselyDialect,
4633
- log(event) {
4634
- if (event.level === "query") {
4635
- common.metrics.ponder_postgres_query_total.inc({
4636
- pool: "readonly"
4637
- });
4638
- }
4639
- },
4640
- plugins: [new WithSchemaPlugin(namespace)]
4641
- }),
4642
4703
  sync: new Kysely({
4643
4704
  dialect: kyselyDialect,
4644
4705
  log(event) {
@@ -4684,13 +4745,14 @@ var createDatabase = async ({
4684
4745
  },
4685
4746
  common.logger
4686
4747
  ),
4687
- readonly: createPool(
4748
+ readonly: createReadonlyPool(
4688
4749
  {
4689
4750
  ...preBuild.databaseConfig.poolConfig,
4690
4751
  application_name: `${namespace}_readonly`,
4691
4752
  max: readonlyMax
4692
4753
  },
4693
- common.logger
4754
+ common.logger,
4755
+ namespace
4694
4756
  ),
4695
4757
  sync: createPool(
4696
4758
  {
@@ -4726,17 +4788,6 @@ var createDatabase = async ({
4726
4788
  },
4727
4789
  plugins: [new WithSchemaPlugin(namespace)]
4728
4790
  }),
4729
- readonly: new Kysely({
4730
- dialect: new PostgresDialect({ pool: driver.readonly }),
4731
- log(event) {
4732
- if (event.level === "query") {
4733
- common.metrics.ponder_postgres_query_total.inc({
4734
- pool: "readonly"
4735
- });
4736
- }
4737
- },
4738
- plugins: [new WithSchemaPlugin(namespace)]
4739
- }),
4740
4791
  sync: new Kysely({
4741
4792
  dialect: new PostgresDialect({ pool: driver.sync }),
4742
4793
  log(event) {
@@ -5487,7 +5538,7 @@ var App = (ui) => {
5487
5538
  }
5488
5539
  ]
5489
5540
  }
5490
- ), /* @__PURE__ */ React3.createElement(Text3, null, " "), /* @__PURE__ */ React3.createElement(Box2, { flexDirection: "row" }, /* @__PURE__ */ React3.createElement(Text3, { bold: true }, "Progress "), app.mode === void 0 || app.progress === 0 ? null : /* @__PURE__ */ React3.createElement(Text3, null, "(", app.mode === "historical" ? /* @__PURE__ */ React3.createElement(Text3, { color: "yellowBright" }, "historical") : app.mode === "realtime" ? /* @__PURE__ */ React3.createElement(Text3, { color: "greenBright" }, "live") : /* @__PURE__ */ React3.createElement(Text3, { color: "greenBright" }, "complete"), ")")), /* @__PURE__ */ React3.createElement(Text3, null, " "), /* @__PURE__ */ React3.createElement(Box2, { flexDirection: "row" }, /* @__PURE__ */ React3.createElement(ProgressBar, { current: app.progress, end: 1, width: 48 }), /* @__PURE__ */ React3.createElement(Text3, null, " ", formatPercentage(app.progress), app.eta === void 0 || app.eta === 0 ? null : ` (${formatEta(app.eta)} eta)`)), /* @__PURE__ */ React3.createElement(Text3, null, " "), /* @__PURE__ */ React3.createElement(Box2, { flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Text3, { bold: true }, "GraphQL "), /* @__PURE__ */ React3.createElement(Box2, { flexDirection: "row" }, /* @__PURE__ */ React3.createElement(Text3, null, "Server live at http://", hostname, ":", port)))));
5541
+ ), /* @__PURE__ */ React3.createElement(Text3, null, " "), /* @__PURE__ */ React3.createElement(Box2, { flexDirection: "row" }, /* @__PURE__ */ React3.createElement(Text3, { bold: true }, "Progress "), app.mode === void 0 || app.progress === 0 ? null : /* @__PURE__ */ React3.createElement(Text3, null, "(", app.mode === "historical" ? /* @__PURE__ */ React3.createElement(Text3, { color: "yellowBright" }, "historical") : app.mode === "realtime" ? /* @__PURE__ */ React3.createElement(Text3, { color: "greenBright" }, "live") : /* @__PURE__ */ React3.createElement(Text3, { color: "greenBright" }, "complete"), ")")), /* @__PURE__ */ React3.createElement(Text3, null, " "), /* @__PURE__ */ React3.createElement(Box2, { flexDirection: "row" }, /* @__PURE__ */ React3.createElement(ProgressBar, { current: app.progress, end: 1, width: 48 }), /* @__PURE__ */ React3.createElement(Text3, null, " ", formatPercentage(app.progress), app.eta === void 0 || app.eta === 0 ? null : ` (${formatEta(app.eta)} eta)`)), /* @__PURE__ */ React3.createElement(Text3, null, " "), /* @__PURE__ */ React3.createElement(Box2, { flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Text3, { bold: true }, "API functions "), /* @__PURE__ */ React3.createElement(Box2, { flexDirection: "row" }, /* @__PURE__ */ React3.createElement(Text3, null, "Server live at http://", hostname, ":", port)))));
5491
5542
  };
5492
5543
  var setupInkApp = (ui) => {
5493
5544
  const app = inkRender(/* @__PURE__ */ React3.createElement(App, { ...ui }));
@@ -10367,11 +10418,11 @@ import {
10367
10418
  getLogsRetryHelper as getLogsRetryHelper2
10368
10419
  } from "@ponder/utils";
10369
10420
  import {
10370
- BlockNotFoundError as BlockNotFoundError2,
10371
10421
  HttpRequestError,
10372
- InternalRpcError,
10373
- InvalidInputRpcError,
10374
- LimitExceededRpcError,
10422
+ JsonRpcVersionUnsupportedError,
10423
+ MethodNotFoundRpcError,
10424
+ MethodNotSupportedRpcError,
10425
+ ParseRpcError,
10375
10426
  isHex
10376
10427
  } from "viem";
10377
10428
  var RETRY_COUNT = 9;
@@ -10456,36 +10507,24 @@ var createRequestQueue = ({
10456
10507
  };
10457
10508
  function shouldRetry(error) {
10458
10509
  if ("code" in error && typeof error.code === "number") {
10459
- if (error.code === -1)
10460
- return true;
10461
- if (error.code === InvalidInputRpcError.code)
10462
- return true;
10463
- if (error.code === LimitExceededRpcError.code)
10464
- return true;
10465
- if (error.code === InternalRpcError.code)
10466
- return true;
10467
- return false;
10510
+ if (error.code === ParseRpcError.code)
10511
+ return false;
10512
+ if (error.code === MethodNotFoundRpcError.code)
10513
+ return false;
10514
+ if (error.code === MethodNotSupportedRpcError.code)
10515
+ return false;
10516
+ if (error.code === JsonRpcVersionUnsupportedError.code)
10517
+ return false;
10468
10518
  }
10469
- if (error instanceof BlockNotFoundError2)
10470
- return true;
10471
10519
  if (error instanceof HttpRequestError && error.status) {
10472
- if (error.status === 403)
10473
- return true;
10474
- if (error.status === 408)
10475
- return true;
10476
- if (error.status === 413)
10477
- return true;
10478
- if (error.status === 429)
10479
- return true;
10480
- if (error.status === 500)
10481
- return true;
10482
- if (error.status === 502)
10483
- return true;
10484
- if (error.status === 503)
10485
- return true;
10486
- if (error.status === 504)
10487
- return true;
10488
- return false;
10520
+ if (error.status === 405)
10521
+ return false;
10522
+ if (error.status === 404)
10523
+ return false;
10524
+ if (error.status === 501)
10525
+ return false;
10526
+ if (error.status === 505)
10527
+ return false;
10489
10528
  }
10490
10529
  return true;
10491
10530
  }