@mikeatlast/ponder 0.16.1-fork.1
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.
- package/CHANGELOG.md +3415 -0
- package/README.md +186 -0
- package/dist/esm/bin/commands/codegen.js +46 -0
- package/dist/esm/bin/commands/codegen.js.map +1 -0
- package/dist/esm/bin/commands/createViews.js +196 -0
- package/dist/esm/bin/commands/createViews.js.map +1 -0
- package/dist/esm/bin/commands/dev.js +430 -0
- package/dist/esm/bin/commands/dev.js.map +1 -0
- package/dist/esm/bin/commands/list.js +148 -0
- package/dist/esm/bin/commands/list.js.map +1 -0
- package/dist/esm/bin/commands/prune.js +223 -0
- package/dist/esm/bin/commands/prune.js.map +1 -0
- package/dist/esm/bin/commands/serve.js +198 -0
- package/dist/esm/bin/commands/serve.js.map +1 -0
- package/dist/esm/bin/commands/start.js +253 -0
- package/dist/esm/bin/commands/start.js.map +1 -0
- package/dist/esm/bin/isolatedController.js +200 -0
- package/dist/esm/bin/isolatedController.js.map +1 -0
- package/dist/esm/bin/isolatedWorker.js +146 -0
- package/dist/esm/bin/isolatedWorker.js.map +1 -0
- package/dist/esm/bin/ponder.js +137 -0
- package/dist/esm/bin/ponder.js.map +1 -0
- package/dist/esm/bin/utils/codegen.js +25 -0
- package/dist/esm/bin/utils/codegen.js.map +1 -0
- package/dist/esm/bin/utils/exit.js +100 -0
- package/dist/esm/bin/utils/exit.js.map +1 -0
- package/dist/esm/build/config.js +745 -0
- package/dist/esm/build/config.js.map +1 -0
- package/dist/esm/build/factory.js +82 -0
- package/dist/esm/build/factory.js.map +1 -0
- package/dist/esm/build/index.js +567 -0
- package/dist/esm/build/index.js.map +1 -0
- package/dist/esm/build/plugin.js +53 -0
- package/dist/esm/build/plugin.js.map +1 -0
- package/dist/esm/build/pre.js +83 -0
- package/dist/esm/build/pre.js.map +1 -0
- package/dist/esm/build/schema.js +202 -0
- package/dist/esm/build/schema.js.map +1 -0
- package/dist/esm/build/stacktrace.js +137 -0
- package/dist/esm/build/stacktrace.js.map +1 -0
- package/dist/esm/client/index.js +441 -0
- package/dist/esm/client/index.js.map +1 -0
- package/dist/esm/config/address.js +2 -0
- package/dist/esm/config/address.js.map +1 -0
- package/dist/esm/config/eventFilter.js +2 -0
- package/dist/esm/config/eventFilter.js.map +1 -0
- package/dist/esm/config/index.js +2 -0
- package/dist/esm/config/index.js.map +1 -0
- package/dist/esm/config/utilityTypes.js +2 -0
- package/dist/esm/config/utilityTypes.js.map +1 -0
- package/dist/esm/database/actions.js +445 -0
- package/dist/esm/database/actions.js.map +1 -0
- package/dist/esm/database/index.js +604 -0
- package/dist/esm/database/index.js.map +1 -0
- package/dist/esm/database/queryBuilder.js +314 -0
- package/dist/esm/database/queryBuilder.js.map +1 -0
- package/dist/esm/drizzle/bigint.js +38 -0
- package/dist/esm/drizzle/bigint.js.map +1 -0
- package/dist/esm/drizzle/bytes.js +47 -0
- package/dist/esm/drizzle/bytes.js.map +1 -0
- package/dist/esm/drizzle/hex.js +40 -0
- package/dist/esm/drizzle/hex.js.map +1 -0
- package/dist/esm/drizzle/index.js +28 -0
- package/dist/esm/drizzle/index.js.map +1 -0
- package/dist/esm/drizzle/json.js +123 -0
- package/dist/esm/drizzle/json.js.map +1 -0
- package/dist/esm/drizzle/kit/index.js +927 -0
- package/dist/esm/drizzle/kit/index.js.map +1 -0
- package/dist/esm/drizzle/onchain.js +184 -0
- package/dist/esm/drizzle/onchain.js.map +1 -0
- package/dist/esm/drizzle/text.js +61 -0
- package/dist/esm/drizzle/text.js.map +1 -0
- package/dist/esm/graphql/graphiql.html.js +59 -0
- package/dist/esm/graphql/graphiql.html.js.map +1 -0
- package/dist/esm/graphql/index.js +934 -0
- package/dist/esm/graphql/index.js.map +1 -0
- package/dist/esm/graphql/json.js +42 -0
- package/dist/esm/graphql/json.js.map +1 -0
- package/dist/esm/graphql/middleware.js +83 -0
- package/dist/esm/graphql/middleware.js.map +1 -0
- package/dist/esm/index.js +9 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/indexing/addStackTrace.js +54 -0
- package/dist/esm/indexing/addStackTrace.js.map +1 -0
- package/dist/esm/indexing/client.js +675 -0
- package/dist/esm/indexing/client.js.map +1 -0
- package/dist/esm/indexing/index.js +663 -0
- package/dist/esm/indexing/index.js.map +1 -0
- package/dist/esm/indexing/profile.js +584 -0
- package/dist/esm/indexing/profile.js.map +1 -0
- package/dist/esm/indexing-store/cache.js +666 -0
- package/dist/esm/indexing-store/cache.js.map +1 -0
- package/dist/esm/indexing-store/index.js +461 -0
- package/dist/esm/indexing-store/index.js.map +1 -0
- package/dist/esm/indexing-store/profile.js +428 -0
- package/dist/esm/indexing-store/profile.js.map +1 -0
- package/dist/esm/indexing-store/utils.js +111 -0
- package/dist/esm/indexing-store/utils.js.map +1 -0
- package/dist/esm/internal/common.js +2 -0
- package/dist/esm/internal/common.js.map +1 -0
- package/dist/esm/internal/errors.js +300 -0
- package/dist/esm/internal/errors.js.map +1 -0
- package/dist/esm/internal/logger.js +178 -0
- package/dist/esm/internal/logger.js.map +1 -0
- package/dist/esm/internal/metrics.js +1049 -0
- package/dist/esm/internal/metrics.js.map +1 -0
- package/dist/esm/internal/options.js +73 -0
- package/dist/esm/internal/options.js.map +1 -0
- package/dist/esm/internal/shutdown.js +24 -0
- package/dist/esm/internal/shutdown.js.map +1 -0
- package/dist/esm/internal/telemetry.js +200 -0
- package/dist/esm/internal/telemetry.js.map +1 -0
- package/dist/esm/internal/types.js +2 -0
- package/dist/esm/internal/types.js.map +1 -0
- package/dist/esm/rpc/actions.js +988 -0
- package/dist/esm/rpc/actions.js.map +1 -0
- package/dist/esm/rpc/http.js +130 -0
- package/dist/esm/rpc/http.js.map +1 -0
- package/dist/esm/rpc/index.js +749 -0
- package/dist/esm/rpc/index.js.map +1 -0
- package/dist/esm/runtime/events.js +664 -0
- package/dist/esm/runtime/events.js.map +1 -0
- package/dist/esm/runtime/filter.js +476 -0
- package/dist/esm/runtime/filter.js.map +1 -0
- package/dist/esm/runtime/fragments.js +478 -0
- package/dist/esm/runtime/fragments.js.map +1 -0
- package/dist/esm/runtime/historical.js +954 -0
- package/dist/esm/runtime/historical.js.map +1 -0
- package/dist/esm/runtime/index.js +316 -0
- package/dist/esm/runtime/index.js.map +1 -0
- package/dist/esm/runtime/init.js +12 -0
- package/dist/esm/runtime/init.js.map +1 -0
- package/dist/esm/runtime/isolated.js +464 -0
- package/dist/esm/runtime/isolated.js.map +1 -0
- package/dist/esm/runtime/multichain.js +511 -0
- package/dist/esm/runtime/multichain.js.map +1 -0
- package/dist/esm/runtime/omnichain.js +546 -0
- package/dist/esm/runtime/omnichain.js.map +1 -0
- package/dist/esm/runtime/realtime.js +722 -0
- package/dist/esm/runtime/realtime.js.map +1 -0
- package/dist/esm/server/error.js +56 -0
- package/dist/esm/server/error.js.map +1 -0
- package/dist/esm/server/index.js +121 -0
- package/dist/esm/server/index.js.map +1 -0
- package/dist/esm/sync-historical/index.js +703 -0
- package/dist/esm/sync-historical/index.js.map +1 -0
- package/dist/esm/sync-realtime/bloom.js +76 -0
- package/dist/esm/sync-realtime/bloom.js.map +1 -0
- package/dist/esm/sync-realtime/index.js +918 -0
- package/dist/esm/sync-realtime/index.js.map +1 -0
- package/dist/esm/sync-store/encode.js +105 -0
- package/dist/esm/sync-store/encode.js.map +1 -0
- package/dist/esm/sync-store/index.js +885 -0
- package/dist/esm/sync-store/index.js.map +1 -0
- package/dist/esm/sync-store/migrations.js +1595 -0
- package/dist/esm/sync-store/migrations.js.map +1 -0
- package/dist/esm/sync-store/schema.js +181 -0
- package/dist/esm/sync-store/schema.js.map +1 -0
- package/dist/esm/types/db.js +2 -0
- package/dist/esm/types/db.js.map +1 -0
- package/dist/esm/types/eth.js +2 -0
- package/dist/esm/types/eth.js.map +1 -0
- package/dist/esm/types/utils.js +2 -0
- package/dist/esm/types/utils.js.map +1 -0
- package/dist/esm/types/virtual.js +2 -0
- package/dist/esm/types/virtual.js.map +1 -0
- package/dist/esm/ui/app.js +157 -0
- package/dist/esm/ui/app.js.map +1 -0
- package/dist/esm/ui/index.js +29 -0
- package/dist/esm/ui/index.js.map +1 -0
- package/dist/esm/ui/patch.js +140 -0
- package/dist/esm/ui/patch.js.map +1 -0
- package/dist/esm/utils/abi.js +55 -0
- package/dist/esm/utils/abi.js.map +1 -0
- package/dist/esm/utils/bigint.js +37 -0
- package/dist/esm/utils/bigint.js.map +1 -0
- package/dist/esm/utils/chains.js +21 -0
- package/dist/esm/utils/chains.js.map +1 -0
- package/dist/esm/utils/checkpoint.js +139 -0
- package/dist/esm/utils/checkpoint.js.map +1 -0
- package/dist/esm/utils/chunk.js +8 -0
- package/dist/esm/utils/chunk.js.map +1 -0
- package/dist/esm/utils/copy.js +129 -0
- package/dist/esm/utils/copy.js.map +1 -0
- package/dist/esm/utils/date.js +27 -0
- package/dist/esm/utils/date.js.map +1 -0
- package/dist/esm/utils/debug.js +2 -0
- package/dist/esm/utils/debug.js.map +1 -0
- package/dist/esm/utils/decodeAbiParameters.js +290 -0
- package/dist/esm/utils/decodeAbiParameters.js.map +1 -0
- package/dist/esm/utils/decodeEventLog.js +75 -0
- package/dist/esm/utils/decodeEventLog.js.map +1 -0
- package/dist/esm/utils/dedupe.js +29 -0
- package/dist/esm/utils/dedupe.js.map +1 -0
- package/dist/esm/utils/duplicates.js +19 -0
- package/dist/esm/utils/duplicates.js.map +1 -0
- package/dist/esm/utils/estimate.js +6 -0
- package/dist/esm/utils/estimate.js.map +1 -0
- package/dist/esm/utils/finality.js +38 -0
- package/dist/esm/utils/finality.js.map +1 -0
- package/dist/esm/utils/format.js +20 -0
- package/dist/esm/utils/format.js.map +1 -0
- package/dist/esm/utils/generators.js +121 -0
- package/dist/esm/utils/generators.js.map +1 -0
- package/dist/esm/utils/hash.js +11 -0
- package/dist/esm/utils/hash.js.map +1 -0
- package/dist/esm/utils/interval.js +171 -0
- package/dist/esm/utils/interval.js.map +1 -0
- package/dist/esm/utils/lowercase.js +7 -0
- package/dist/esm/utils/lowercase.js.map +1 -0
- package/dist/esm/utils/mutex.js +26 -0
- package/dist/esm/utils/mutex.js.map +1 -0
- package/dist/esm/utils/never.js +4 -0
- package/dist/esm/utils/never.js.map +1 -0
- package/dist/esm/utils/offset.js +101 -0
- package/dist/esm/utils/offset.js.map +1 -0
- package/dist/esm/utils/order.js +18 -0
- package/dist/esm/utils/order.js.map +1 -0
- package/dist/esm/utils/partition.js +46 -0
- package/dist/esm/utils/partition.js.map +1 -0
- package/dist/esm/utils/pg.js +175 -0
- package/dist/esm/utils/pg.js.map +1 -0
- package/dist/esm/utils/pglite.js +80 -0
- package/dist/esm/utils/pglite.js.map +1 -0
- package/dist/esm/utils/port.js +30 -0
- package/dist/esm/utils/port.js.map +1 -0
- package/dist/esm/utils/print.js +23 -0
- package/dist/esm/utils/print.js.map +1 -0
- package/dist/esm/utils/promiseAllSettledWithThrow.js +19 -0
- package/dist/esm/utils/promiseAllSettledWithThrow.js.map +1 -0
- package/dist/esm/utils/promiseWithResolvers.js +13 -0
- package/dist/esm/utils/promiseWithResolvers.js.map +1 -0
- package/dist/esm/utils/queue.js +150 -0
- package/dist/esm/utils/queue.js.map +1 -0
- package/dist/esm/utils/range.js +8 -0
- package/dist/esm/utils/range.js.map +1 -0
- package/dist/esm/utils/result.js +10 -0
- package/dist/esm/utils/result.js.map +1 -0
- package/dist/esm/utils/sql-parse.js +1326 -0
- package/dist/esm/utils/sql-parse.js.map +1 -0
- package/dist/esm/utils/timer.js +9 -0
- package/dist/esm/utils/timer.js.map +1 -0
- package/dist/esm/utils/truncate.js +15 -0
- package/dist/esm/utils/truncate.js.map +1 -0
- package/dist/esm/utils/wait.js +10 -0
- package/dist/esm/utils/wait.js.map +1 -0
- package/dist/esm/utils/zipper.js +67 -0
- package/dist/esm/utils/zipper.js.map +1 -0
- package/dist/types/bin/commands/codegen.d.ts +5 -0
- package/dist/types/bin/commands/codegen.d.ts.map +1 -0
- package/dist/types/bin/commands/createViews.d.ts +8 -0
- package/dist/types/bin/commands/createViews.d.ts.map +1 -0
- package/dist/types/bin/commands/dev.d.ts +5 -0
- package/dist/types/bin/commands/dev.d.ts.map +1 -0
- package/dist/types/bin/commands/list.d.ts +5 -0
- package/dist/types/bin/commands/list.d.ts.map +1 -0
- package/dist/types/bin/commands/prune.d.ts +5 -0
- package/dist/types/bin/commands/prune.d.ts.map +1 -0
- package/dist/types/bin/commands/serve.d.ts +5 -0
- package/dist/types/bin/commands/serve.d.ts.map +1 -0
- package/dist/types/bin/commands/start.d.ts +19 -0
- package/dist/types/bin/commands/start.d.ts.map +1 -0
- package/dist/types/bin/isolatedController.d.ts +13 -0
- package/dist/types/bin/isolatedController.d.ts.map +1 -0
- package/dist/types/bin/isolatedWorker.d.ts +9 -0
- package/dist/types/bin/isolatedWorker.d.ts.map +1 -0
- package/dist/types/bin/ponder.d.ts +37 -0
- package/dist/types/bin/ponder.d.ts.map +1 -0
- package/dist/types/bin/utils/codegen.d.ts +6 -0
- package/dist/types/bin/utils/codegen.d.ts.map +1 -0
- package/dist/types/bin/utils/exit.d.ts +10 -0
- package/dist/types/bin/utils/exit.d.ts.map +1 -0
- package/dist/types/build/config.d.ts +97 -0
- package/dist/types/build/config.d.ts.map +1 -0
- package/dist/types/build/factory.d.ts +15 -0
- package/dist/types/build/factory.d.ts.map +1 -0
- package/dist/types/build/index.d.ts +84 -0
- package/dist/types/build/index.d.ts.map +1 -0
- package/dist/types/build/plugin.d.ts +4 -0
- package/dist/types/build/plugin.d.ts.map +1 -0
- package/dist/types/build/pre.d.ts +29 -0
- package/dist/types/build/pre.d.ts.map +1 -0
- package/dist/types/build/schema.d.ts +20 -0
- package/dist/types/build/schema.d.ts.map +1 -0
- package/dist/types/build/stacktrace.d.ts +13 -0
- package/dist/types/build/stacktrace.d.ts.map +1 -0
- package/dist/types/client/index.d.ts +27 -0
- package/dist/types/client/index.d.ts.map +1 -0
- package/dist/types/config/address.d.ts +34 -0
- package/dist/types/config/address.d.ts.map +1 -0
- package/dist/types/config/eventFilter.d.ts +18 -0
- package/dist/types/config/eventFilter.d.ts.map +1 -0
- package/dist/types/config/index.d.ts +144 -0
- package/dist/types/config/index.d.ts.map +1 -0
- package/dist/types/config/utilityTypes.d.ts +43 -0
- package/dist/types/config/utilityTypes.d.ts.map +1 -0
- package/dist/types/database/actions.d.ts +99 -0
- package/dist/types/database/actions.d.ts.map +1 -0
- package/dist/types/database/index.d.ts +493 -0
- package/dist/types/database/index.d.ts.map +1 -0
- package/dist/types/database/queryBuilder.d.ts +65 -0
- package/dist/types/database/queryBuilder.d.ts.map +1 -0
- package/dist/types/drizzle/bigint.d.ts +25 -0
- package/dist/types/drizzle/bigint.d.ts.map +1 -0
- package/dist/types/drizzle/bytes.d.ts +31 -0
- package/dist/types/drizzle/bytes.d.ts.map +1 -0
- package/dist/types/drizzle/hex.d.ts +25 -0
- package/dist/types/drizzle/hex.d.ts.map +1 -0
- package/dist/types/drizzle/index.d.ts +6 -0
- package/dist/types/drizzle/index.d.ts.map +1 -0
- package/dist/types/drizzle/json.d.ts +51 -0
- package/dist/types/drizzle/json.d.ts.map +1 -0
- package/dist/types/drizzle/kit/index.d.ts +187 -0
- package/dist/types/drizzle/kit/index.d.ts.map +1 -0
- package/dist/types/drizzle/onchain.d.ts +298 -0
- package/dist/types/drizzle/onchain.d.ts.map +1 -0
- package/dist/types/drizzle/text.d.ts +29 -0
- package/dist/types/drizzle/text.d.ts.map +1 -0
- package/dist/types/graphql/graphiql.html.d.ts +2 -0
- package/dist/types/graphql/graphiql.html.d.ts.map +1 -0
- package/dist/types/graphql/index.d.ts +12 -0
- package/dist/types/graphql/index.d.ts.map +1 -0
- package/dist/types/graphql/json.d.ts +3 -0
- package/dist/types/graphql/json.d.ts.map +1 -0
- package/dist/types/graphql/middleware.d.ts +29 -0
- package/dist/types/graphql/middleware.d.ts.map +1 -0
- package/dist/types/index.d.ts +23 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/indexing/addStackTrace.d.ts +3 -0
- package/dist/types/indexing/addStackTrace.d.ts.map +1 -0
- package/dist/types/indexing/client.d.ts +154 -0
- package/dist/types/indexing/client.d.ts.map +1 -0
- package/dist/types/indexing/index.d.ts +72 -0
- package/dist/types/indexing/index.d.ts.map +1 -0
- package/dist/types/indexing/profile.d.ts +16 -0
- package/dist/types/indexing/profile.d.ts.map +1 -0
- package/dist/types/indexing-store/cache.d.ts +115 -0
- package/dist/types/indexing-store/cache.d.ts.map +1 -0
- package/dist/types/indexing-store/index.d.ts +24 -0
- package/dist/types/indexing-store/index.d.ts.map +1 -0
- package/dist/types/indexing-store/profile.d.ts +7 -0
- package/dist/types/indexing-store/profile.d.ts.map +1 -0
- package/dist/types/indexing-store/utils.d.ts +19 -0
- package/dist/types/indexing-store/utils.d.ts.map +1 -0
- package/dist/types/internal/common.d.ts +15 -0
- package/dist/types/internal/common.d.ts.map +1 -0
- package/dist/types/internal/errors.d.ts +101 -0
- package/dist/types/internal/errors.d.ts.map +1 -0
- package/dist/types/internal/logger.d.ts +37 -0
- package/dist/types/internal/logger.d.ts.map +1 -0
- package/dist/types/internal/metrics.d.ts +120 -0
- package/dist/types/internal/metrics.d.ts.map +1 -0
- package/dist/types/internal/options.d.ts +62 -0
- package/dist/types/internal/options.d.ts.map +1 -0
- package/dist/types/internal/shutdown.d.ts +8 -0
- package/dist/types/internal/shutdown.d.ts.map +1 -0
- package/dist/types/internal/telemetry.d.ts +43 -0
- package/dist/types/internal/telemetry.d.ts.map +1 -0
- package/dist/types/internal/types.d.ts +443 -0
- package/dist/types/internal/types.d.ts.map +1 -0
- package/dist/types/rpc/actions.d.ts +360 -0
- package/dist/types/rpc/actions.d.ts.map +1 -0
- package/dist/types/rpc/http.d.ts +17 -0
- package/dist/types/rpc/http.d.ts.map +1 -0
- package/dist/types/rpc/index.d.ts +43 -0
- package/dist/types/rpc/index.d.ts.map +1 -0
- package/dist/types/runtime/events.d.ts +40 -0
- package/dist/types/runtime/events.d.ts.map +1 -0
- package/dist/types/runtime/filter.d.ts +96 -0
- package/dist/types/runtime/filter.d.ts.map +1 -0
- package/dist/types/runtime/fragments.d.ts +30 -0
- package/dist/types/runtime/fragments.d.ts.map +1 -0
- package/dist/types/runtime/historical.d.ts +123 -0
- package/dist/types/runtime/historical.d.ts.map +1 -0
- package/dist/types/runtime/index.d.ts +89 -0
- package/dist/types/runtime/index.d.ts.map +1 -0
- package/dist/types/runtime/init.d.ts +28 -0
- package/dist/types/runtime/init.d.ts.map +1 -0
- package/dist/types/runtime/isolated.d.ts +14 -0
- package/dist/types/runtime/isolated.d.ts.map +1 -0
- package/dist/types/runtime/multichain.d.ts +13 -0
- package/dist/types/runtime/multichain.d.ts.map +1 -0
- package/dist/types/runtime/omnichain.d.ts +23 -0
- package/dist/types/runtime/omnichain.d.ts.map +1 -0
- package/dist/types/runtime/realtime.d.ts +93 -0
- package/dist/types/runtime/realtime.d.ts.map +1 -0
- package/dist/types/server/error.d.ts +5 -0
- package/dist/types/server/error.d.ts.map +1 -0
- package/dist/types/server/index.d.ts +13 -0
- package/dist/types/server/index.d.ts.map +1 -0
- package/dist/types/sync-historical/index.d.ts +36 -0
- package/dist/types/sync-historical/index.d.ts.map +1 -0
- package/dist/types/sync-realtime/bloom.d.ts +18 -0
- package/dist/types/sync-realtime/bloom.d.ts.map +1 -0
- package/dist/types/sync-realtime/index.d.ts +48 -0
- package/dist/types/sync-realtime/index.d.ts.map +1 -0
- package/dist/types/sync-store/encode.d.ts +25 -0
- package/dist/types/sync-store/encode.d.ts.map +1 -0
- package/dist/types/sync-store/index.d.ts +135 -0
- package/dist/types/sync-store/index.d.ts.map +1 -0
- package/dist/types/sync-store/migrations.d.ts +8 -0
- package/dist/types/sync-store/migrations.d.ts.map +1 -0
- package/dist/types/sync-store/schema.d.ts +1828 -0
- package/dist/types/sync-store/schema.d.ts.map +1 -0
- package/dist/types/types/db.d.ts +213 -0
- package/dist/types/types/db.d.ts.map +1 -0
- package/dist/types/types/eth.d.ts +196 -0
- package/dist/types/types/eth.d.ts.map +1 -0
- package/dist/types/types/utils.d.ts +38 -0
- package/dist/types/types/utils.d.ts.map +1 -0
- package/dist/types/types/virtual.d.ts +99 -0
- package/dist/types/types/virtual.d.ts.map +1 -0
- package/dist/types/ui/app.d.ts +22 -0
- package/dist/types/ui/app.d.ts.map +1 -0
- package/dist/types/ui/index.d.ts +5 -0
- package/dist/types/ui/index.d.ts.map +1 -0
- package/dist/types/ui/patch.d.ts +7 -0
- package/dist/types/ui/patch.d.ts.map +1 -0
- package/dist/types/utils/abi.d.ts +23 -0
- package/dist/types/utils/abi.d.ts.map +1 -0
- package/dist/types/utils/bigint.d.ts +15 -0
- package/dist/types/utils/bigint.d.ts.map +1 -0
- package/dist/types/utils/chains.d.ts +42 -0
- package/dist/types/utils/chains.d.ts.map +1 -0
- package/dist/types/utils/checkpoint.d.ts +52 -0
- package/dist/types/utils/checkpoint.d.ts.map +1 -0
- package/dist/types/utils/chunk.d.ts +2 -0
- package/dist/types/utils/chunk.d.ts.map +1 -0
- package/dist/types/utils/copy.d.ts +16 -0
- package/dist/types/utils/copy.d.ts.map +1 -0
- package/dist/types/utils/date.d.ts +7 -0
- package/dist/types/utils/date.d.ts.map +1 -0
- package/dist/types/utils/debug.d.ts +105 -0
- package/dist/types/utils/debug.d.ts.map +1 -0
- package/dist/types/utils/decodeAbiParameters.d.ts +28 -0
- package/dist/types/utils/decodeAbiParameters.d.ts.map +1 -0
- package/dist/types/utils/decodeEventLog.d.ts +12 -0
- package/dist/types/utils/decodeEventLog.d.ts.map +1 -0
- package/dist/types/utils/dedupe.d.ts +20 -0
- package/dist/types/utils/dedupe.d.ts.map +1 -0
- package/dist/types/utils/duplicates.d.ts +7 -0
- package/dist/types/utils/duplicates.d.ts.map +1 -0
- package/dist/types/utils/estimate.d.ts +11 -0
- package/dist/types/utils/estimate.d.ts.map +1 -0
- package/dist/types/utils/finality.d.ts +12 -0
- package/dist/types/utils/finality.d.ts.map +1 -0
- package/dist/types/utils/format.d.ts +3 -0
- package/dist/types/utils/format.d.ts.map +1 -0
- package/dist/types/utils/generators.d.ts +42 -0
- package/dist/types/utils/generators.d.ts.map +1 -0
- package/dist/types/utils/hash.d.ts +11 -0
- package/dist/types/utils/hash.d.ts.map +1 -0
- package/dist/types/utils/interval.d.ts +53 -0
- package/dist/types/utils/interval.d.ts.map +1 -0
- package/dist/types/utils/lowercase.d.ts +5 -0
- package/dist/types/utils/lowercase.d.ts.map +1 -0
- package/dist/types/utils/mutex.d.ts +5 -0
- package/dist/types/utils/mutex.d.ts.map +1 -0
- package/dist/types/utils/never.d.ts +2 -0
- package/dist/types/utils/never.d.ts.map +1 -0
- package/dist/types/utils/offset.d.ts +8 -0
- package/dist/types/utils/offset.d.ts.map +1 -0
- package/dist/types/utils/order.d.ts +2 -0
- package/dist/types/utils/order.d.ts.map +1 -0
- package/dist/types/utils/partition.d.ts +22 -0
- package/dist/types/utils/partition.d.ts.map +1 -0
- package/dist/types/utils/pg.d.ts +8 -0
- package/dist/types/utils/pg.d.ts.map +1 -0
- package/dist/types/utils/pglite.d.ts +25 -0
- package/dist/types/utils/pglite.d.ts.map +1 -0
- package/dist/types/utils/port.d.ts +5 -0
- package/dist/types/utils/port.d.ts.map +1 -0
- package/dist/types/utils/print.d.ts +2 -0
- package/dist/types/utils/print.d.ts.map +1 -0
- package/dist/types/utils/promiseAllSettledWithThrow.d.ts +8 -0
- package/dist/types/utils/promiseAllSettledWithThrow.d.ts.map +1 -0
- package/dist/types/utils/promiseWithResolvers.d.ts +10 -0
- package/dist/types/utils/promiseWithResolvers.d.ts.map +1 -0
- package/dist/types/utils/queue.d.ts +33 -0
- package/dist/types/utils/queue.d.ts.map +1 -0
- package/dist/types/utils/range.d.ts +8 -0
- package/dist/types/utils/range.d.ts.map +1 -0
- package/dist/types/utils/result.d.ts +17 -0
- package/dist/types/utils/result.d.ts.map +1 -0
- package/dist/types/utils/sql-parse.d.ts +21 -0
- package/dist/types/utils/sql-parse.d.ts.map +1 -0
- package/dist/types/utils/timer.d.ts +6 -0
- package/dist/types/utils/timer.d.ts.map +1 -0
- package/dist/types/utils/truncate.d.ts +9 -0
- package/dist/types/utils/truncate.d.ts.map +1 -0
- package/dist/types/utils/wait.d.ts +6 -0
- package/dist/types/utils/wait.d.ts.map +1 -0
- package/dist/types/utils/zipper.d.ts +36 -0
- package/dist/types/utils/zipper.d.ts.map +1 -0
- package/package.json +114 -0
- package/src/bin/commands/codegen.ts +56 -0
- package/src/bin/commands/createViews.ts +318 -0
- package/src/bin/commands/dev.ts +490 -0
- package/src/bin/commands/list.ts +208 -0
- package/src/bin/commands/prune.ts +322 -0
- package/src/bin/commands/serve.ts +236 -0
- package/src/bin/commands/start.ts +319 -0
- package/src/bin/isolatedController.ts +300 -0
- package/src/bin/isolatedWorker.ts +192 -0
- package/src/bin/ponder.ts +208 -0
- package/src/bin/utils/codegen.ts +32 -0
- package/src/bin/utils/exit.ts +112 -0
- package/src/build/config.ts +1141 -0
- package/src/build/factory.ts +147 -0
- package/src/build/index.ts +790 -0
- package/src/build/plugin.ts +58 -0
- package/src/build/pre.ts +114 -0
- package/src/build/schema.ts +358 -0
- package/src/build/stacktrace.ts +137 -0
- package/src/client/index.ts +551 -0
- package/src/config/address.ts +45 -0
- package/src/config/eventFilter.ts +33 -0
- package/src/config/index.ts +240 -0
- package/src/config/utilityTypes.ts +152 -0
- package/src/database/actions.ts +873 -0
- package/src/database/index.ts +1029 -0
- package/src/database/queryBuilder.ts +537 -0
- package/src/drizzle/bigint.ts +57 -0
- package/src/drizzle/bytes.ts +68 -0
- package/src/drizzle/hex.ts +58 -0
- package/src/drizzle/index.ts +40 -0
- package/src/drizzle/json.ts +159 -0
- package/src/drizzle/kit/index.ts +1348 -0
- package/src/drizzle/onchain.ts +476 -0
- package/src/drizzle/text.ts +77 -0
- package/src/graphql/graphiql.html.ts +59 -0
- package/src/graphql/index.ts +1351 -0
- package/src/graphql/json.ts +62 -0
- package/src/graphql/middleware.ts +115 -0
- package/src/index.ts +139 -0
- package/src/indexing/addStackTrace.ts +69 -0
- package/src/indexing/client.ts +1184 -0
- package/src/indexing/index.ts +976 -0
- package/src/indexing/profile.ts +771 -0
- package/src/indexing-store/cache.ts +1057 -0
- package/src/indexing-store/index.ts +628 -0
- package/src/indexing-store/profile.ts +557 -0
- package/src/indexing-store/utils.ts +162 -0
- package/src/internal/common.ts +15 -0
- package/src/internal/errors.ts +228 -0
- package/src/internal/logger.ts +252 -0
- package/src/internal/metrics.ts +1030 -0
- package/src/internal/options.ts +130 -0
- package/src/internal/shutdown.ts +32 -0
- package/src/internal/telemetry.ts +303 -0
- package/src/internal/types.ts +611 -0
- package/src/rpc/actions.ts +1344 -0
- package/src/rpc/http.ts +164 -0
- package/src/rpc/index.ts +959 -0
- package/src/runtime/events.ts +875 -0
- package/src/runtime/filter.ts +705 -0
- package/src/runtime/fragments.ts +674 -0
- package/src/runtime/historical.ts +1522 -0
- package/src/runtime/index.ts +569 -0
- package/src/runtime/init.ts +49 -0
- package/src/runtime/isolated.ts +775 -0
- package/src/runtime/multichain.ts +860 -0
- package/src/runtime/omnichain.ts +920 -0
- package/src/runtime/realtime.ts +1164 -0
- package/src/server/error.ts +68 -0
- package/src/server/index.ts +173 -0
- package/src/sync-historical/index.ts +1065 -0
- package/src/sync-realtime/bloom.ts +102 -0
- package/src/sync-realtime/index.ts +1304 -0
- package/src/sync-store/encode.ts +153 -0
- package/src/sync-store/index.ts +1633 -0
- package/src/sync-store/migrations.ts +1801 -0
- package/src/sync-store/schema.ts +248 -0
- package/src/types/db.ts +292 -0
- package/src/types/eth.ts +216 -0
- package/src/types/utils.ts +47 -0
- package/src/types/virtual.ts +244 -0
- package/src/types.d.ts +38 -0
- package/src/ui/app.ts +207 -0
- package/src/ui/index.ts +37 -0
- package/src/ui/patch.ts +204 -0
- package/src/utils/abi.ts +103 -0
- package/src/utils/bigint.ts +41 -0
- package/src/utils/chains.ts +22 -0
- package/src/utils/checkpoint.ts +203 -0
- package/src/utils/chunk.ts +7 -0
- package/src/utils/copy.ts +151 -0
- package/src/utils/date.ts +26 -0
- package/src/utils/debug.ts +110 -0
- package/src/utils/decodeAbiParameters.ts +428 -0
- package/src/utils/decodeEventLog.ts +100 -0
- package/src/utils/dedupe.ts +32 -0
- package/src/utils/duplicates.ts +19 -0
- package/src/utils/estimate.ts +27 -0
- package/src/utils/finality.ts +40 -0
- package/src/utils/format.ts +22 -0
- package/src/utils/generators.ts +157 -0
- package/src/utils/hash.ts +22 -0
- package/src/utils/interval.ts +212 -0
- package/src/utils/lowercase.ts +6 -0
- package/src/utils/mutex.ts +33 -0
- package/src/utils/never.ts +3 -0
- package/src/utils/offset.ts +133 -0
- package/src/utils/order.ts +16 -0
- package/src/utils/partition.ts +53 -0
- package/src/utils/pg.ts +230 -0
- package/src/utils/pglite.ts +97 -0
- package/src/utils/port.ts +34 -0
- package/src/utils/print.ts +31 -0
- package/src/utils/promiseAllSettledWithThrow.ts +27 -0
- package/src/utils/promiseWithResolvers.ts +20 -0
- package/src/utils/queue.ts +258 -0
- package/src/utils/range.ts +8 -0
- package/src/utils/result.ts +26 -0
- package/src/utils/sql-parse.ts +1477 -0
- package/src/utils/timer.ts +8 -0
- package/src/utils/truncate.ts +15 -0
- package/src/utils/wait.ts +8 -0
- package/src/utils/zipper.ts +80 -0
|
@@ -0,0 +1,918 @@
|
|
|
1
|
+
import { ShutdownError } from '../internal/errors.js';
|
|
2
|
+
import { debug_traceBlockByHash, eth_getBlockByHash, eth_getBlockByNumber, eth_getBlockReceipts, eth_getLogs, eth_getTransactionReceipt, validateLogsAndBlock, validateReceiptsAndBlock, validateTracesAndBlock, validateTransactionsAndBlock, } from '../rpc/actions.js';
|
|
3
|
+
import { getChildAddress, getChildStartBlock, getFilterFactories, isAddressFactory, isAddressMatched, isBlockFilterMatched, isLogFactoryMatched, isLogFilterMatched, isTraceFilterMatched, isTransactionFilterMatched, isTransferFilterMatched, } from '../runtime/filter.js';
|
|
4
|
+
import { createLock } from '../utils/mutex.js';
|
|
5
|
+
import { range } from '../utils/range.js';
|
|
6
|
+
import { startClock } from '../utils/timer.js';
|
|
7
|
+
import { hexToNumber, numberToHex, zeroHash, } from "viem";
|
|
8
|
+
import { isFilterInBloom, isInBloom, zeroLogsBloom } from "./bloom.js";
|
|
9
|
+
const MAX_LATEST_BLOCK_ATTEMPT_MS = 10 * 60 * 1000; // 10 minutes
|
|
10
|
+
const MAX_QUEUED_BLOCKS = 50;
|
|
11
|
+
export const createRealtimeSync = (args) => {
|
|
12
|
+
let isBlockReceipts = true;
|
|
13
|
+
let finalizedBlock = args.syncProgress.finalized;
|
|
14
|
+
const childAddresses = args.childAddresses;
|
|
15
|
+
/** Annotates `childAddresses` for efficient lookup by block number */
|
|
16
|
+
const childAddressesPerBlock = new Map();
|
|
17
|
+
/**
|
|
18
|
+
* Blocks that have been ingested and are
|
|
19
|
+
* waiting to be finalized. It is an invariant that
|
|
20
|
+
* all blocks are linked to each other,
|
|
21
|
+
* `parentHash` => `hash`.
|
|
22
|
+
*/
|
|
23
|
+
let unfinalizedBlocks = [];
|
|
24
|
+
/** Closest-to-tip block that has been fetched but not yet reconciled. */
|
|
25
|
+
let latestFetchedBlock;
|
|
26
|
+
let fetchAndReconcileLatestBlockErrorCount = 0;
|
|
27
|
+
const realtimeSyncLock = createLock();
|
|
28
|
+
const factories = [];
|
|
29
|
+
const logFilters = [];
|
|
30
|
+
const traceFilters = [];
|
|
31
|
+
const transactionFilters = [];
|
|
32
|
+
const transferFilters = [];
|
|
33
|
+
const blockFilters = [];
|
|
34
|
+
for (const eventCallback of args.eventCallbacks) {
|
|
35
|
+
if (eventCallback.filter.toBlock &&
|
|
36
|
+
eventCallback.filter.toBlock <= hexToNumber(finalizedBlock.number)) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
// Collect filters from event callbacks
|
|
40
|
+
if (eventCallback.filter.type === "log") {
|
|
41
|
+
logFilters.push(eventCallback.filter);
|
|
42
|
+
}
|
|
43
|
+
else if (eventCallback.filter.type === "trace") {
|
|
44
|
+
traceFilters.push(eventCallback.filter);
|
|
45
|
+
}
|
|
46
|
+
else if (eventCallback.filter.type === "transaction") {
|
|
47
|
+
transactionFilters.push(eventCallback.filter);
|
|
48
|
+
}
|
|
49
|
+
else if (eventCallback.filter.type === "transfer") {
|
|
50
|
+
transferFilters.push(eventCallback.filter);
|
|
51
|
+
}
|
|
52
|
+
else if (eventCallback.filter.type === "block") {
|
|
53
|
+
blockFilters.push(eventCallback.filter);
|
|
54
|
+
}
|
|
55
|
+
for (const factory of getFilterFactories(eventCallback.filter)) {
|
|
56
|
+
if (factory.toBlock &&
|
|
57
|
+
factory.toBlock <= hexToNumber(finalizedBlock.number)) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
factories.push(factory);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const syncTransactionReceipts = async (block, transactionHashes, ethGetBlockMethod, context) => {
|
|
64
|
+
if (transactionHashes.size === 0) {
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
if (isBlockReceipts === false) {
|
|
68
|
+
const transactionReceipts = await Promise.all(Array.from(transactionHashes).map(async (hash) => {
|
|
69
|
+
const receipt = await eth_getTransactionReceipt(args.rpc, [hash], context);
|
|
70
|
+
validateReceiptsAndBlock([receipt], block, {
|
|
71
|
+
method: "eth_getTransactionReceipt",
|
|
72
|
+
params: [hash],
|
|
73
|
+
}, ethGetBlockMethod === "eth_getBlockByNumber"
|
|
74
|
+
? {
|
|
75
|
+
method: "eth_getBlockByNumber",
|
|
76
|
+
params: [block.number, true],
|
|
77
|
+
}
|
|
78
|
+
: {
|
|
79
|
+
method: "eth_getBlockByHash",
|
|
80
|
+
params: [block.hash, true],
|
|
81
|
+
});
|
|
82
|
+
return receipt;
|
|
83
|
+
}));
|
|
84
|
+
return transactionReceipts;
|
|
85
|
+
}
|
|
86
|
+
let blockReceipts;
|
|
87
|
+
try {
|
|
88
|
+
blockReceipts = await eth_getBlockReceipts(args.rpc, [block.hash], context);
|
|
89
|
+
}
|
|
90
|
+
catch (_error) {
|
|
91
|
+
const error = _error;
|
|
92
|
+
args.common.logger.warn({
|
|
93
|
+
msg: "Caught eth_getBlockReceipts error, switching to eth_getTransactionReceipt method",
|
|
94
|
+
action: "fetch block data",
|
|
95
|
+
chain: args.chain.name,
|
|
96
|
+
chain_id: args.chain.id,
|
|
97
|
+
error,
|
|
98
|
+
});
|
|
99
|
+
isBlockReceipts = false;
|
|
100
|
+
return syncTransactionReceipts(block, transactionHashes, ethGetBlockMethod, context);
|
|
101
|
+
}
|
|
102
|
+
validateReceiptsAndBlock(blockReceipts, block, {
|
|
103
|
+
method: "eth_getBlockReceipts",
|
|
104
|
+
params: [block.hash],
|
|
105
|
+
}, ethGetBlockMethod === "eth_getBlockByNumber"
|
|
106
|
+
? {
|
|
107
|
+
method: "eth_getBlockByNumber",
|
|
108
|
+
params: [block.number, true],
|
|
109
|
+
}
|
|
110
|
+
: {
|
|
111
|
+
method: "eth_getBlockByHash",
|
|
112
|
+
params: [block.hash, true],
|
|
113
|
+
});
|
|
114
|
+
const transactionReceipts = blockReceipts.filter((receipt) => transactionHashes.has(receipt.transactionHash));
|
|
115
|
+
return transactionReceipts;
|
|
116
|
+
};
|
|
117
|
+
const getLatestUnfinalizedBlock = () => {
|
|
118
|
+
if (unfinalizedBlocks.length === 0) {
|
|
119
|
+
return finalizedBlock;
|
|
120
|
+
}
|
|
121
|
+
else
|
|
122
|
+
return unfinalizedBlocks[unfinalizedBlocks.length - 1];
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* Fetch all data (logs, traces, receipts) for the specified block required by `args.sources`
|
|
126
|
+
*
|
|
127
|
+
* @dev The data returned by this function may include false positives. This
|
|
128
|
+
* is due to the fact that factory addresses are unknown and are always
|
|
129
|
+
* treated as "matched".
|
|
130
|
+
*/
|
|
131
|
+
const fetchBlockEventData = async (maybeBlockHeader) => {
|
|
132
|
+
const context = {
|
|
133
|
+
logger: args.common.logger.child({ action: "fetch_block_data" }),
|
|
134
|
+
};
|
|
135
|
+
const endClock = startClock();
|
|
136
|
+
let block;
|
|
137
|
+
let ethGetBlockMethod;
|
|
138
|
+
if (maybeBlockHeader.transactions !== undefined) {
|
|
139
|
+
block = maybeBlockHeader;
|
|
140
|
+
ethGetBlockMethod = "eth_getBlockByNumber";
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
ethGetBlockMethod = "eth_getBlockByHash";
|
|
144
|
+
}
|
|
145
|
+
////////
|
|
146
|
+
// Logs
|
|
147
|
+
////////
|
|
148
|
+
// "eth_getLogs" calls can be skipped if no filters match `newHeadBlock.logsBloom`.
|
|
149
|
+
const shouldRequestLogs = maybeBlockHeader.logsBloom === zeroLogsBloom ||
|
|
150
|
+
logFilters.some((filter) => isFilterInBloom({ block: maybeBlockHeader, filter }));
|
|
151
|
+
let logs = [];
|
|
152
|
+
if (shouldRequestLogs) {
|
|
153
|
+
if (block === undefined) {
|
|
154
|
+
[block, logs] = await Promise.all([
|
|
155
|
+
eth_getBlockByHash(args.rpc, [maybeBlockHeader.hash, true], context),
|
|
156
|
+
eth_getLogs(args.rpc, [{ blockHash: maybeBlockHeader.hash }], context),
|
|
157
|
+
]);
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
logs = await eth_getLogs(args.rpc, [{ blockHash: block.hash }], context);
|
|
161
|
+
}
|
|
162
|
+
validateLogsAndBlock(logs, block, {
|
|
163
|
+
method: "eth_getLogs",
|
|
164
|
+
params: [{ blockHash: block.hash }],
|
|
165
|
+
}, ethGetBlockMethod === "eth_getBlockByNumber"
|
|
166
|
+
? {
|
|
167
|
+
method: "eth_getBlockByNumber",
|
|
168
|
+
params: [block.number, true],
|
|
169
|
+
}
|
|
170
|
+
: {
|
|
171
|
+
method: "eth_getBlockByHash",
|
|
172
|
+
params: [block.hash, true],
|
|
173
|
+
});
|
|
174
|
+
// Note: Exact `logsBloom` validations were considered too strict to add to `validateLogsAndBlock`.
|
|
175
|
+
let isInvalidLogsBloom = false;
|
|
176
|
+
for (const log of logs) {
|
|
177
|
+
if (isInBloom(block.logsBloom, log.address) === false) {
|
|
178
|
+
isInvalidLogsBloom = true;
|
|
179
|
+
}
|
|
180
|
+
if (log.topics[0] &&
|
|
181
|
+
isInBloom(block.logsBloom, log.topics[0]) === false) {
|
|
182
|
+
isInvalidLogsBloom = true;
|
|
183
|
+
}
|
|
184
|
+
if (log.topics[1] &&
|
|
185
|
+
isInBloom(block.logsBloom, log.topics[1]) === false) {
|
|
186
|
+
isInvalidLogsBloom = true;
|
|
187
|
+
}
|
|
188
|
+
if (log.topics[2] &&
|
|
189
|
+
isInBloom(block.logsBloom, log.topics[2]) === false) {
|
|
190
|
+
isInvalidLogsBloom = true;
|
|
191
|
+
}
|
|
192
|
+
if (log.topics[3] &&
|
|
193
|
+
isInBloom(block.logsBloom, log.topics[3]) === false) {
|
|
194
|
+
isInvalidLogsBloom = true;
|
|
195
|
+
}
|
|
196
|
+
if (isInvalidLogsBloom) {
|
|
197
|
+
args.common.logger.warn({
|
|
198
|
+
msg: "Detected inconsistent RPC responses. Log not found in block.logsBloom.",
|
|
199
|
+
action: "fetch_block_data",
|
|
200
|
+
chain: args.chain.name,
|
|
201
|
+
chain_id: args.chain.id,
|
|
202
|
+
number: hexToNumber(block.number),
|
|
203
|
+
hash: block.hash,
|
|
204
|
+
logIndex: hexToNumber(log.logIndex),
|
|
205
|
+
});
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
for (const log of logs) {
|
|
210
|
+
if (log.transactionHash === zeroHash) {
|
|
211
|
+
args.common.logger.warn({
|
|
212
|
+
msg: "Detected log with empty transaction hash. This is expected for some chains like ZKsync.",
|
|
213
|
+
action: "fetch_block_data",
|
|
214
|
+
chain: args.chain.name,
|
|
215
|
+
chain_id: args.chain.id,
|
|
216
|
+
number: hexToNumber(block.number),
|
|
217
|
+
hash: block.hash,
|
|
218
|
+
logIndex: hexToNumber(log.logIndex),
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
if (shouldRequestLogs === false && logFilters.length > 0) {
|
|
224
|
+
args.common.logger.trace({
|
|
225
|
+
msg: "Skipped eth_getLogs request due to bloom filter result",
|
|
226
|
+
action: "fetch_block_data",
|
|
227
|
+
chain: args.chain.name,
|
|
228
|
+
chain_id: args.chain.id,
|
|
229
|
+
number: hexToNumber(maybeBlockHeader.number),
|
|
230
|
+
hash: maybeBlockHeader.hash,
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
////////
|
|
234
|
+
// Traces
|
|
235
|
+
////////
|
|
236
|
+
const shouldRequestTraces = traceFilters.length > 0 || transferFilters.length > 0;
|
|
237
|
+
let traces = [];
|
|
238
|
+
if (shouldRequestTraces) {
|
|
239
|
+
if (block === undefined) {
|
|
240
|
+
[block, traces] = await Promise.all([
|
|
241
|
+
eth_getBlockByHash(args.rpc, [maybeBlockHeader.hash, true], context),
|
|
242
|
+
debug_traceBlockByHash(args.rpc, [maybeBlockHeader.hash, { tracer: "callTracer" }], context),
|
|
243
|
+
]);
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
traces = await debug_traceBlockByHash(args.rpc, [block.hash, { tracer: "callTracer" }], context);
|
|
247
|
+
}
|
|
248
|
+
validateTracesAndBlock(traces, block, {
|
|
249
|
+
method: "debug_traceBlockByNumber",
|
|
250
|
+
params: [block.number, { tracer: "callTracer" }],
|
|
251
|
+
}, ethGetBlockMethod === "eth_getBlockByNumber"
|
|
252
|
+
? {
|
|
253
|
+
method: "eth_getBlockByNumber",
|
|
254
|
+
params: [block.number, true],
|
|
255
|
+
}
|
|
256
|
+
: {
|
|
257
|
+
method: "eth_getBlockByHash",
|
|
258
|
+
params: [block.hash, true],
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
////////
|
|
262
|
+
// Get Matched
|
|
263
|
+
////////
|
|
264
|
+
// Record `blockChildAddresses` that contain factory child addresses with their start blocks
|
|
265
|
+
const blockChildAddresses = new Map();
|
|
266
|
+
const childAddressDecodeFailureIds = new Set();
|
|
267
|
+
let childAddressDecodeFailureCount = 0;
|
|
268
|
+
let childAddressDecodeSuccessCount = 0;
|
|
269
|
+
for (const factory of factories) {
|
|
270
|
+
blockChildAddresses.set(factory, new Map());
|
|
271
|
+
for (const log of logs) {
|
|
272
|
+
if (isLogFactoryMatched({ factory, log })) {
|
|
273
|
+
let address;
|
|
274
|
+
try {
|
|
275
|
+
address = getChildAddress({ log, factory });
|
|
276
|
+
childAddressDecodeSuccessCount++;
|
|
277
|
+
}
|
|
278
|
+
catch (error) {
|
|
279
|
+
if (factory.address === undefined) {
|
|
280
|
+
childAddressDecodeFailureCount++;
|
|
281
|
+
if (childAddressDecodeFailureIds.has(factory.id) === false) {
|
|
282
|
+
childAddressDecodeFailureIds.add(factory.id);
|
|
283
|
+
args.common.logger.debug({
|
|
284
|
+
msg: "Failed to extract child address from log matched by factory using the provided ABI item",
|
|
285
|
+
chain: args.chain.name,
|
|
286
|
+
chain_id: args.chain.id,
|
|
287
|
+
factory: factory.sourceId,
|
|
288
|
+
block_number: hexToNumber(log.blockNumber),
|
|
289
|
+
log_index: hexToNumber(log.logIndex),
|
|
290
|
+
data: log.data,
|
|
291
|
+
topics: JSON.stringify(log.topics),
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
throw error;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
// Use childStartBlock from event field or static config, fall back to log's block number
|
|
301
|
+
const childStartBlock = getChildStartBlock({ log, factory });
|
|
302
|
+
const startBlockNumber = childStartBlock ?? hexToNumber(log.blockNumber);
|
|
303
|
+
blockChildAddresses.get(factory).set(address, startBlockNumber);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
if (childAddressDecodeFailureCount > 0) {
|
|
308
|
+
args.common.logger.debug({
|
|
309
|
+
msg: "Logs matched by factory contained child addresses that could not be extracted",
|
|
310
|
+
failure_count: childAddressDecodeFailureCount,
|
|
311
|
+
success_count: childAddressDecodeSuccessCount,
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
const requiredTransactions = new Set();
|
|
315
|
+
const requiredTransactionReceipts = new Set();
|
|
316
|
+
// Remove logs that don't match a filter, recording required transactions
|
|
317
|
+
logs = logs.filter((log) => {
|
|
318
|
+
let isMatched = false;
|
|
319
|
+
for (const filter of logFilters) {
|
|
320
|
+
if (isLogFilterMatched({ filter, log })) {
|
|
321
|
+
isMatched = true;
|
|
322
|
+
if (log.transactionHash !== zeroHash) {
|
|
323
|
+
requiredTransactions.add(log.transactionHash);
|
|
324
|
+
if (filter.hasTransactionReceipt) {
|
|
325
|
+
requiredTransactionReceipts.add(log.transactionHash);
|
|
326
|
+
// skip to next log
|
|
327
|
+
break;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return isMatched;
|
|
333
|
+
});
|
|
334
|
+
// Initial weak trace filtering before full filtering with factory addresses in handleBlock
|
|
335
|
+
traces = traces.filter((trace) => {
|
|
336
|
+
let isMatched = false;
|
|
337
|
+
for (const filter of transferFilters) {
|
|
338
|
+
if (isTransferFilterMatched({
|
|
339
|
+
filter,
|
|
340
|
+
trace: trace.trace,
|
|
341
|
+
block: maybeBlockHeader,
|
|
342
|
+
})) {
|
|
343
|
+
requiredTransactions.add(trace.transactionHash);
|
|
344
|
+
isMatched = true;
|
|
345
|
+
if (filter.hasTransactionReceipt) {
|
|
346
|
+
requiredTransactionReceipts.add(trace.transactionHash);
|
|
347
|
+
// skip to next trace
|
|
348
|
+
break;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
for (const filter of traceFilters) {
|
|
353
|
+
if (isTraceFilterMatched({
|
|
354
|
+
filter,
|
|
355
|
+
trace: trace.trace,
|
|
356
|
+
block: maybeBlockHeader,
|
|
357
|
+
})) {
|
|
358
|
+
requiredTransactions.add(trace.transactionHash);
|
|
359
|
+
isMatched = true;
|
|
360
|
+
if (filter.hasTransactionReceipt) {
|
|
361
|
+
requiredTransactionReceipts.add(trace.transactionHash);
|
|
362
|
+
// skip to next trace
|
|
363
|
+
break;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
return isMatched;
|
|
368
|
+
});
|
|
369
|
+
////////
|
|
370
|
+
// Transactions
|
|
371
|
+
////////
|
|
372
|
+
// exit early if no logs or traces were requested and no transactions are required
|
|
373
|
+
if (block === undefined && transactionFilters.length === 0) {
|
|
374
|
+
args.common.logger.debug({
|
|
375
|
+
msg: "Fetched block data",
|
|
376
|
+
chain: args.chain.name,
|
|
377
|
+
chain_id: args.chain.id,
|
|
378
|
+
number: hexToNumber(maybeBlockHeader.number),
|
|
379
|
+
hash: maybeBlockHeader.hash,
|
|
380
|
+
transaction_count: 0,
|
|
381
|
+
receipt_count: 0,
|
|
382
|
+
trace_count: 0,
|
|
383
|
+
log_count: 0,
|
|
384
|
+
child_address_count: 0,
|
|
385
|
+
duration: endClock(),
|
|
386
|
+
}, ["chain", "number", "hash"]);
|
|
387
|
+
return {
|
|
388
|
+
block: maybeBlockHeader,
|
|
389
|
+
transactions: [],
|
|
390
|
+
transactionReceipts: [],
|
|
391
|
+
logs: [],
|
|
392
|
+
traces: [],
|
|
393
|
+
childAddresses: blockChildAddresses,
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
if (block === undefined) {
|
|
397
|
+
block = await eth_getBlockByHash(args.rpc, [maybeBlockHeader.hash, true], context);
|
|
398
|
+
}
|
|
399
|
+
validateTransactionsAndBlock(block, ethGetBlockMethod === "eth_getBlockByNumber"
|
|
400
|
+
? {
|
|
401
|
+
method: "eth_getBlockByNumber",
|
|
402
|
+
params: [block.number, true],
|
|
403
|
+
}
|
|
404
|
+
: {
|
|
405
|
+
method: "eth_getBlockByHash",
|
|
406
|
+
params: [block.hash, true],
|
|
407
|
+
});
|
|
408
|
+
const transactions = block.transactions.filter((transaction) => {
|
|
409
|
+
let isMatched = requiredTransactions.has(transaction.hash);
|
|
410
|
+
for (const filter of transactionFilters) {
|
|
411
|
+
if (isTransactionFilterMatched({ filter, transaction })) {
|
|
412
|
+
requiredTransactions.add(transaction.hash);
|
|
413
|
+
requiredTransactionReceipts.add(transaction.hash);
|
|
414
|
+
isMatched = true;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
return isMatched;
|
|
418
|
+
});
|
|
419
|
+
////////
|
|
420
|
+
// Transaction Receipts
|
|
421
|
+
////////
|
|
422
|
+
const transactionReceipts = await syncTransactionReceipts(block, requiredTransactionReceipts, ethGetBlockMethod, context);
|
|
423
|
+
let childAddressCount = 0;
|
|
424
|
+
for (const childAddresses of blockChildAddresses.values()) {
|
|
425
|
+
childAddressCount += childAddresses.size;
|
|
426
|
+
}
|
|
427
|
+
args.common.logger.debug({
|
|
428
|
+
msg: "Fetched block data",
|
|
429
|
+
chain: args.chain.name,
|
|
430
|
+
chain_id: args.chain.id,
|
|
431
|
+
number: hexToNumber(block.number),
|
|
432
|
+
hash: block.hash,
|
|
433
|
+
transaction_count: transactions.length,
|
|
434
|
+
log_count: logs.length,
|
|
435
|
+
trace_count: traces.length,
|
|
436
|
+
receipt_count: transactionReceipts.length,
|
|
437
|
+
child_address_count: childAddressCount,
|
|
438
|
+
duration: endClock(),
|
|
439
|
+
}, ["chain", "number", "hash"]);
|
|
440
|
+
return {
|
|
441
|
+
block,
|
|
442
|
+
transactions,
|
|
443
|
+
transactionReceipts,
|
|
444
|
+
logs,
|
|
445
|
+
traces,
|
|
446
|
+
childAddresses: blockChildAddresses,
|
|
447
|
+
};
|
|
448
|
+
};
|
|
449
|
+
/**
|
|
450
|
+
* Filter the block event data using the filters and child addresses.
|
|
451
|
+
*/
|
|
452
|
+
const filterBlockEventData = ({ block, logs, traces, transactions, transactionReceipts, childAddresses: blockChildAddresses, }) => {
|
|
453
|
+
// Update `childAddresses`
|
|
454
|
+
for (const factory of factories) {
|
|
455
|
+
const factoryId = factory.id;
|
|
456
|
+
for (const [address, startBlockNumber] of blockChildAddresses.get(factory)) {
|
|
457
|
+
if (childAddresses.get(factoryId).has(address) === false) {
|
|
458
|
+
childAddresses.get(factoryId).set(address, startBlockNumber);
|
|
459
|
+
}
|
|
460
|
+
else {
|
|
461
|
+
blockChildAddresses.get(factory).delete(address);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
// Save per block child addresses so that they can be undone in the event of a reorg.
|
|
466
|
+
childAddressesPerBlock.set(hexToNumber(block.number), blockChildAddresses);
|
|
467
|
+
/**
|
|
468
|
+
* `logs` and `callTraces` must be filtered again (already filtered in `extract`)
|
|
469
|
+
* because `extract` doesn't have factory address information.
|
|
470
|
+
*/
|
|
471
|
+
const matchedFilters = new Set();
|
|
472
|
+
// Remove logs that don't match a filter, accounting for factory addresses
|
|
473
|
+
logs = logs.filter((log) => {
|
|
474
|
+
let isMatched = false;
|
|
475
|
+
for (const filter of logFilters) {
|
|
476
|
+
if (isLogFilterMatched({ filter, log }) &&
|
|
477
|
+
(isAddressFactory(filter.address)
|
|
478
|
+
? isAddressMatched({
|
|
479
|
+
address: log.address,
|
|
480
|
+
blockNumber: hexToNumber(block.number),
|
|
481
|
+
childAddresses: childAddresses.get(filter.address.id),
|
|
482
|
+
})
|
|
483
|
+
: true)) {
|
|
484
|
+
matchedFilters.add(filter);
|
|
485
|
+
isMatched = true;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
return isMatched;
|
|
489
|
+
});
|
|
490
|
+
traces = traces.filter((trace) => {
|
|
491
|
+
let isMatched = false;
|
|
492
|
+
for (const filter of transferFilters) {
|
|
493
|
+
if (isTransferFilterMatched({
|
|
494
|
+
filter,
|
|
495
|
+
trace: trace.trace,
|
|
496
|
+
block,
|
|
497
|
+
}) &&
|
|
498
|
+
(isAddressFactory(filter.fromAddress)
|
|
499
|
+
? isAddressMatched({
|
|
500
|
+
address: trace.trace.from,
|
|
501
|
+
blockNumber: hexToNumber(block.number),
|
|
502
|
+
childAddresses: childAddresses.get(filter.fromAddress.id),
|
|
503
|
+
})
|
|
504
|
+
: true) &&
|
|
505
|
+
(isAddressFactory(filter.toAddress)
|
|
506
|
+
? isAddressMatched({
|
|
507
|
+
address: trace.trace.to,
|
|
508
|
+
blockNumber: hexToNumber(block.number),
|
|
509
|
+
childAddresses: childAddresses.get(filter.toAddress.id),
|
|
510
|
+
})
|
|
511
|
+
: true)) {
|
|
512
|
+
matchedFilters.add(filter);
|
|
513
|
+
isMatched = true;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
for (const filter of traceFilters) {
|
|
517
|
+
if (isTraceFilterMatched({
|
|
518
|
+
filter,
|
|
519
|
+
trace: trace.trace,
|
|
520
|
+
block,
|
|
521
|
+
}) &&
|
|
522
|
+
(isAddressFactory(filter.fromAddress)
|
|
523
|
+
? isAddressMatched({
|
|
524
|
+
address: trace.trace.from,
|
|
525
|
+
blockNumber: hexToNumber(block.number),
|
|
526
|
+
childAddresses: childAddresses.get(filter.fromAddress.id),
|
|
527
|
+
})
|
|
528
|
+
: true) &&
|
|
529
|
+
(isAddressFactory(filter.toAddress)
|
|
530
|
+
? isAddressMatched({
|
|
531
|
+
address: trace.trace.to,
|
|
532
|
+
blockNumber: hexToNumber(block.number),
|
|
533
|
+
childAddresses: childAddresses.get(filter.toAddress.id),
|
|
534
|
+
})
|
|
535
|
+
: true)) {
|
|
536
|
+
matchedFilters.add(filter);
|
|
537
|
+
isMatched = true;
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
return isMatched;
|
|
541
|
+
});
|
|
542
|
+
// Remove transactions and transaction receipts that may have been filtered out
|
|
543
|
+
const transactionHashes = new Set();
|
|
544
|
+
for (const log of logs) {
|
|
545
|
+
transactionHashes.add(log.transactionHash);
|
|
546
|
+
}
|
|
547
|
+
for (const trace of traces) {
|
|
548
|
+
transactionHashes.add(trace.transactionHash);
|
|
549
|
+
}
|
|
550
|
+
transactions = transactions.filter((transaction) => {
|
|
551
|
+
let isMatched = transactionHashes.has(transaction.hash);
|
|
552
|
+
for (const filter of transactionFilters) {
|
|
553
|
+
if (isTransactionFilterMatched({ filter, transaction }) &&
|
|
554
|
+
(isAddressFactory(filter.fromAddress)
|
|
555
|
+
? isAddressMatched({
|
|
556
|
+
address: transaction.from,
|
|
557
|
+
blockNumber: hexToNumber(block.number),
|
|
558
|
+
childAddresses: childAddresses.get(filter.fromAddress.id),
|
|
559
|
+
})
|
|
560
|
+
: true) &&
|
|
561
|
+
(isAddressFactory(filter.toAddress)
|
|
562
|
+
? isAddressMatched({
|
|
563
|
+
address: transaction.to ?? undefined,
|
|
564
|
+
blockNumber: hexToNumber(block.number),
|
|
565
|
+
childAddresses: childAddresses.get(filter.toAddress.id),
|
|
566
|
+
})
|
|
567
|
+
: true)) {
|
|
568
|
+
matchedFilters.add(filter);
|
|
569
|
+
isMatched = true;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
return isMatched;
|
|
573
|
+
});
|
|
574
|
+
for (const transaction of transactions) {
|
|
575
|
+
transactionHashes.add(transaction.hash);
|
|
576
|
+
}
|
|
577
|
+
transactionReceipts = transactionReceipts.filter((t) => transactionHashes.has(t.transactionHash));
|
|
578
|
+
// Record matched block filters
|
|
579
|
+
for (const filter of blockFilters) {
|
|
580
|
+
if (isBlockFilterMatched({ filter, block })) {
|
|
581
|
+
matchedFilters.add(filter);
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
return {
|
|
585
|
+
matchedFilters,
|
|
586
|
+
block,
|
|
587
|
+
logs,
|
|
588
|
+
transactions,
|
|
589
|
+
transactionReceipts,
|
|
590
|
+
traces,
|
|
591
|
+
childAddresses: blockChildAddresses,
|
|
592
|
+
};
|
|
593
|
+
};
|
|
594
|
+
/**
|
|
595
|
+
* Traverse the remote chain until we find a block that is
|
|
596
|
+
* compatible with our local chain.
|
|
597
|
+
*
|
|
598
|
+
* @param block Block that caused reorg to be detected.
|
|
599
|
+
* Must be at most 1 block ahead of the local chain.
|
|
600
|
+
*/
|
|
601
|
+
const reconcileReorg = async (block) => {
|
|
602
|
+
const context = {
|
|
603
|
+
logger: args.common.logger.child({ action: "reconcile_reorg" }),
|
|
604
|
+
};
|
|
605
|
+
const endClock = startClock();
|
|
606
|
+
args.common.logger.debug({
|
|
607
|
+
msg: "Detected reorg in local chain",
|
|
608
|
+
chain: args.chain.name,
|
|
609
|
+
chain_id: args.chain.id,
|
|
610
|
+
number: hexToNumber(block.number),
|
|
611
|
+
hash: block.hash,
|
|
612
|
+
});
|
|
613
|
+
// Record blocks that have been removed from the local chain.
|
|
614
|
+
const reorgedBlocks = unfinalizedBlocks.filter((lb) => hexToNumber(lb.number) >= hexToNumber(block.number));
|
|
615
|
+
// Prune the local chain of blocks that have been reorged out
|
|
616
|
+
unfinalizedBlocks = unfinalizedBlocks.filter((lb) => hexToNumber(lb.number) < hexToNumber(block.number));
|
|
617
|
+
// Block we are attempting to fit into the local chain.
|
|
618
|
+
let remoteBlock = block;
|
|
619
|
+
while (true) {
|
|
620
|
+
const parentBlock = getLatestUnfinalizedBlock();
|
|
621
|
+
if (parentBlock.hash === remoteBlock.parentHash)
|
|
622
|
+
break;
|
|
623
|
+
if (unfinalizedBlocks.length === 0) {
|
|
624
|
+
// No compatible block was found in the local chain, must be a deep reorg.
|
|
625
|
+
// Note: reorgedBlocks aren't removed from `unfinalizedBlocks` because we are "bailing"
|
|
626
|
+
// from this attempt to reconcile the reorg, we need to reset the local chain state back
|
|
627
|
+
// to what it was before we started.
|
|
628
|
+
unfinalizedBlocks = reorgedBlocks;
|
|
629
|
+
args.common.logger.warn({
|
|
630
|
+
msg: "Encountered unrecoverable reorg",
|
|
631
|
+
chain: args.chain.name,
|
|
632
|
+
chain_id: args.chain.id,
|
|
633
|
+
finalized_block: hexToNumber(finalizedBlock.number),
|
|
634
|
+
duration: endClock(),
|
|
635
|
+
});
|
|
636
|
+
throw new Error(`Encountered unrecoverable '${args.chain.name}' reorg beyond finalized block ${hexToNumber(finalizedBlock.number)}`);
|
|
637
|
+
}
|
|
638
|
+
else {
|
|
639
|
+
remoteBlock = await eth_getBlockByHash(args.rpc, [remoteBlock.parentHash, false], context);
|
|
640
|
+
// Add tip to `reorgedBlocks`
|
|
641
|
+
reorgedBlocks.unshift(unfinalizedBlocks.pop());
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
const commonAncestor = getLatestUnfinalizedBlock();
|
|
645
|
+
args.common.logger.debug({
|
|
646
|
+
msg: "Reconciled reorg in local chain",
|
|
647
|
+
chain: args.chain.name,
|
|
648
|
+
chain_id: args.chain.id,
|
|
649
|
+
reorg_depth: reorgedBlocks.length,
|
|
650
|
+
common_ancestor_block: hexToNumber(commonAncestor.number),
|
|
651
|
+
duration: endClock(),
|
|
652
|
+
});
|
|
653
|
+
// remove reorged blocks from `childAddresses`
|
|
654
|
+
for (const block of reorgedBlocks) {
|
|
655
|
+
for (const factory of factories) {
|
|
656
|
+
const addressMap = childAddressesPerBlock
|
|
657
|
+
.get(hexToNumber(block.number))
|
|
658
|
+
.get(factory);
|
|
659
|
+
for (const address of addressMap.keys()) {
|
|
660
|
+
childAddresses.get(factory.id).delete(address);
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
childAddressesPerBlock.delete(hexToNumber(block.number));
|
|
664
|
+
}
|
|
665
|
+
return {
|
|
666
|
+
type: "reorg",
|
|
667
|
+
block: commonAncestor,
|
|
668
|
+
reorgedBlocks,
|
|
669
|
+
};
|
|
670
|
+
};
|
|
671
|
+
/**
|
|
672
|
+
* Finish syncing a block.
|
|
673
|
+
*
|
|
674
|
+
* The four cases are:
|
|
675
|
+
* 1) Block is the same as the one just processed, no-op.
|
|
676
|
+
* 2) Block is behind the last processed. This is a sign that
|
|
677
|
+
* a reorg has occurred.
|
|
678
|
+
* 3) Block is more than one ahead of the last processed,
|
|
679
|
+
* fetch all intermediate blocks and enqueue them again.
|
|
680
|
+
* 4) Block is exactly one block ahead of the last processed,
|
|
681
|
+
* handle this new block (happy path).
|
|
682
|
+
*
|
|
683
|
+
* @dev `blockCallback` is guaranteed to be called exactly once or an error is thrown.
|
|
684
|
+
* @dev It is an invariant that the correct events are generated or an error is thrown.
|
|
685
|
+
*/
|
|
686
|
+
const reconcileBlock = async function* (blockWithEventData, blockCallback) {
|
|
687
|
+
const endClock = startClock();
|
|
688
|
+
const latestBlock = getLatestUnfinalizedBlock();
|
|
689
|
+
const block = blockWithEventData.block;
|
|
690
|
+
// We already saw and handled this block. No-op.
|
|
691
|
+
if (latestBlock.hash === block.hash) {
|
|
692
|
+
args.common.logger.trace({
|
|
693
|
+
msg: "Detected duplicate block",
|
|
694
|
+
chain: args.chain.name,
|
|
695
|
+
chain_id: args.chain.id,
|
|
696
|
+
number: hexToNumber(block.number),
|
|
697
|
+
hash: block.hash,
|
|
698
|
+
});
|
|
699
|
+
blockCallback?.(false);
|
|
700
|
+
return;
|
|
701
|
+
}
|
|
702
|
+
// Quickly check for a reorg by comparing block numbers. If the block
|
|
703
|
+
// number has not increased, a reorg must have occurred.
|
|
704
|
+
if (hexToNumber(latestBlock.number) >= hexToNumber(block.number)) {
|
|
705
|
+
const reorgEvent = await reconcileReorg(block);
|
|
706
|
+
blockCallback?.(false);
|
|
707
|
+
yield reorgEvent;
|
|
708
|
+
return;
|
|
709
|
+
}
|
|
710
|
+
// Blocks are missing. They should be fetched and enqueued.
|
|
711
|
+
if (hexToNumber(latestBlock.number) + 1 < hexToNumber(block.number)) {
|
|
712
|
+
args.common.logger.trace({
|
|
713
|
+
msg: "Missing blocks from local chain",
|
|
714
|
+
chain: args.chain.name,
|
|
715
|
+
chain_id: args.chain.id,
|
|
716
|
+
block_range: JSON.stringify([
|
|
717
|
+
hexToNumber(latestBlock.number) + 1,
|
|
718
|
+
hexToNumber(block.number) - 1,
|
|
719
|
+
]),
|
|
720
|
+
});
|
|
721
|
+
// Retrieve missing blocks, but only fetch a certain amount.
|
|
722
|
+
const missingBlockRange = range(hexToNumber(latestBlock.number) + 1, Math.min(hexToNumber(block.number), hexToNumber(latestBlock.number) + MAX_QUEUED_BLOCKS));
|
|
723
|
+
const pendingBlocks = await Promise.all(missingBlockRange.map((blockNumber) => eth_getBlockByNumber(args.rpc, [numberToHex(blockNumber), true], {
|
|
724
|
+
logger: args.common.logger.child({
|
|
725
|
+
action: "fetch_missing_blocks",
|
|
726
|
+
}),
|
|
727
|
+
}).then((block) => fetchBlockEventData(block))));
|
|
728
|
+
args.common.logger.debug({
|
|
729
|
+
msg: "Fetched missing blocks",
|
|
730
|
+
chain: args.chain.name,
|
|
731
|
+
chain_id: args.chain.id,
|
|
732
|
+
block_range: JSON.stringify([
|
|
733
|
+
hexToNumber(latestBlock.number) + 1,
|
|
734
|
+
Math.min(hexToNumber(block.number) - 1, hexToNumber(latestBlock.number) + MAX_QUEUED_BLOCKS),
|
|
735
|
+
]),
|
|
736
|
+
});
|
|
737
|
+
for (const pendingBlock of pendingBlocks) {
|
|
738
|
+
yield* reconcileBlock(pendingBlock);
|
|
739
|
+
}
|
|
740
|
+
if (hexToNumber(block.number) - hexToNumber(latestBlock.number) >
|
|
741
|
+
MAX_QUEUED_BLOCKS) {
|
|
742
|
+
args.common.logger.trace({
|
|
743
|
+
msg: "Latest block too far ahead of local chain",
|
|
744
|
+
chain: args.chain.name,
|
|
745
|
+
chain_id: args.chain.id,
|
|
746
|
+
number: hexToNumber(block.number),
|
|
747
|
+
hash: block.hash,
|
|
748
|
+
});
|
|
749
|
+
blockCallback?.(false);
|
|
750
|
+
}
|
|
751
|
+
else {
|
|
752
|
+
yield* reconcileBlock(blockWithEventData, blockCallback);
|
|
753
|
+
}
|
|
754
|
+
return;
|
|
755
|
+
}
|
|
756
|
+
// Check if a reorg occurred by validating the chain of block hashes.
|
|
757
|
+
if (block.parentHash !== latestBlock.hash) {
|
|
758
|
+
const reorgEvent = await reconcileReorg(block);
|
|
759
|
+
blockCallback?.(false);
|
|
760
|
+
yield reorgEvent;
|
|
761
|
+
return;
|
|
762
|
+
}
|
|
763
|
+
// New block is exactly one block ahead of the local chain.
|
|
764
|
+
// Attempt to ingest it.
|
|
765
|
+
const blockWithFilteredEventData = filterBlockEventData(blockWithEventData);
|
|
766
|
+
let childAddressCount = 0;
|
|
767
|
+
for (const childAddresses of blockWithFilteredEventData.childAddresses.values()) {
|
|
768
|
+
childAddressCount += childAddresses.size;
|
|
769
|
+
}
|
|
770
|
+
args.common.logger.debug({
|
|
771
|
+
msg: "Added block to local chain",
|
|
772
|
+
chain: args.chain.name,
|
|
773
|
+
chain_id: args.chain.id,
|
|
774
|
+
number: hexToNumber(block.number),
|
|
775
|
+
hash: block.hash,
|
|
776
|
+
transaction_count: blockWithFilteredEventData.transactions.length,
|
|
777
|
+
log_count: blockWithFilteredEventData.logs.length,
|
|
778
|
+
trace_count: blockWithFilteredEventData.traces.length,
|
|
779
|
+
receipt_count: blockWithFilteredEventData.transactionReceipts.length,
|
|
780
|
+
child_address_count: childAddressCount,
|
|
781
|
+
duration: endClock(),
|
|
782
|
+
}, ["chain", "number", "hash"]);
|
|
783
|
+
unfinalizedBlocks.push({
|
|
784
|
+
hash: block.hash,
|
|
785
|
+
parentHash: block.parentHash,
|
|
786
|
+
number: block.number,
|
|
787
|
+
timestamp: block.timestamp,
|
|
788
|
+
});
|
|
789
|
+
// Make sure `transactions` can be garbage collected
|
|
790
|
+
blockWithEventData.block.transactions =
|
|
791
|
+
blockWithFilteredEventData.block.transactions;
|
|
792
|
+
yield {
|
|
793
|
+
type: "block",
|
|
794
|
+
hasMatchedFilter: blockWithFilteredEventData.matchedFilters.size > 0,
|
|
795
|
+
block: blockWithFilteredEventData.block,
|
|
796
|
+
logs: blockWithFilteredEventData.logs,
|
|
797
|
+
transactions: blockWithFilteredEventData.transactions,
|
|
798
|
+
transactionReceipts: blockWithFilteredEventData.transactionReceipts,
|
|
799
|
+
traces: blockWithFilteredEventData.traces,
|
|
800
|
+
childAddresses: blockWithFilteredEventData.childAddresses,
|
|
801
|
+
blockCallback,
|
|
802
|
+
};
|
|
803
|
+
// Determine if a new range has become finalized by evaluating if the
|
|
804
|
+
// latest block number is 2 * finalityBlockCount >= finalized block number.
|
|
805
|
+
// Essentially, there is a range the width of finalityBlockCount that is entirely
|
|
806
|
+
// finalized.
|
|
807
|
+
const blockMovesFinality = hexToNumber(block.number) >=
|
|
808
|
+
hexToNumber(finalizedBlock.number) + 2 * args.chain.finalityBlockCount;
|
|
809
|
+
if (blockMovesFinality) {
|
|
810
|
+
const pendingFinalizedBlock = unfinalizedBlocks.find((lb) => hexToNumber(lb.number) ===
|
|
811
|
+
hexToNumber(block.number) - args.chain.finalityBlockCount);
|
|
812
|
+
args.common.logger.debug({
|
|
813
|
+
msg: "Removed finalized blocks from local chain",
|
|
814
|
+
chain: args.chain.name,
|
|
815
|
+
chain_id: args.chain.id,
|
|
816
|
+
block_count: hexToNumber(pendingFinalizedBlock.number) -
|
|
817
|
+
hexToNumber(finalizedBlock.number),
|
|
818
|
+
block_range: JSON.stringify([
|
|
819
|
+
hexToNumber(finalizedBlock.number) + 1,
|
|
820
|
+
hexToNumber(pendingFinalizedBlock.number),
|
|
821
|
+
]),
|
|
822
|
+
});
|
|
823
|
+
const finalizedBlocks = unfinalizedBlocks.filter((lb) => hexToNumber(lb.number) <= hexToNumber(pendingFinalizedBlock.number));
|
|
824
|
+
unfinalizedBlocks = unfinalizedBlocks.filter((lb) => hexToNumber(lb.number) > hexToNumber(pendingFinalizedBlock.number));
|
|
825
|
+
for (const block of finalizedBlocks) {
|
|
826
|
+
childAddressesPerBlock.delete(hexToNumber(block.number));
|
|
827
|
+
}
|
|
828
|
+
finalizedBlock = pendingFinalizedBlock;
|
|
829
|
+
yield {
|
|
830
|
+
type: "finalize",
|
|
831
|
+
block: pendingFinalizedBlock,
|
|
832
|
+
};
|
|
833
|
+
}
|
|
834
|
+
};
|
|
835
|
+
const onError = (error, block) => {
|
|
836
|
+
if (args.common.shutdown.isKilled) {
|
|
837
|
+
throw new ShutdownError();
|
|
838
|
+
}
|
|
839
|
+
if (block) {
|
|
840
|
+
args.common.logger.warn({
|
|
841
|
+
msg: "Failed to fetch latest block",
|
|
842
|
+
chain: args.chain.name,
|
|
843
|
+
chain_id: args.chain.id,
|
|
844
|
+
number: hexToNumber(block.number),
|
|
845
|
+
hash: block.hash,
|
|
846
|
+
retry_count: fetchAndReconcileLatestBlockErrorCount,
|
|
847
|
+
error,
|
|
848
|
+
});
|
|
849
|
+
}
|
|
850
|
+
else {
|
|
851
|
+
args.common.logger.warn({
|
|
852
|
+
msg: "Failed to fetch latest block",
|
|
853
|
+
chain: args.chain.name,
|
|
854
|
+
chain_id: args.chain.id,
|
|
855
|
+
retry_count: fetchAndReconcileLatestBlockErrorCount,
|
|
856
|
+
error,
|
|
857
|
+
});
|
|
858
|
+
}
|
|
859
|
+
fetchAndReconcileLatestBlockErrorCount += 1;
|
|
860
|
+
// Number of retries is max(10, `MAX_LATEST_BLOCK_ATTEMPT_MS` / `args.chain.pollingInterval`)
|
|
861
|
+
if (fetchAndReconcileLatestBlockErrorCount >= 10 &&
|
|
862
|
+
fetchAndReconcileLatestBlockErrorCount * args.chain.pollingInterval >
|
|
863
|
+
MAX_LATEST_BLOCK_ATTEMPT_MS) {
|
|
864
|
+
throw error;
|
|
865
|
+
}
|
|
866
|
+
};
|
|
867
|
+
return {
|
|
868
|
+
async *sync(block, blockCallback) {
|
|
869
|
+
try {
|
|
870
|
+
args.common.logger.debug({
|
|
871
|
+
msg: "Received new head block",
|
|
872
|
+
chain: args.chain.name,
|
|
873
|
+
chain_id: args.chain.id,
|
|
874
|
+
number: hexToNumber(block.number),
|
|
875
|
+
hash: block.hash,
|
|
876
|
+
});
|
|
877
|
+
const latestBlock = getLatestUnfinalizedBlock();
|
|
878
|
+
// We already saw and handled this block. No-op.
|
|
879
|
+
if (latestBlock.hash === block.hash ||
|
|
880
|
+
latestFetchedBlock?.hash === block.hash) {
|
|
881
|
+
args.common.logger.trace({
|
|
882
|
+
msg: "Detected duplicate block",
|
|
883
|
+
chain: args.chain.name,
|
|
884
|
+
chain_id: args.chain.id,
|
|
885
|
+
number: hexToNumber(block.number),
|
|
886
|
+
hash: block.hash,
|
|
887
|
+
});
|
|
888
|
+
blockCallback?.(false);
|
|
889
|
+
return;
|
|
890
|
+
}
|
|
891
|
+
// Note: It's possible that a block with the same hash as `block` is
|
|
892
|
+
// currently being fetched but hasn't been fully reconciled. `latestFetchedBlock`
|
|
893
|
+
// is used to handle this case.
|
|
894
|
+
latestFetchedBlock = block;
|
|
895
|
+
const blockWithEventData = await fetchBlockEventData(block);
|
|
896
|
+
// Note: `reconcileBlock` must be called serially.
|
|
897
|
+
await realtimeSyncLock.lock();
|
|
898
|
+
try {
|
|
899
|
+
yield* reconcileBlock(blockWithEventData, blockCallback);
|
|
900
|
+
}
|
|
901
|
+
finally {
|
|
902
|
+
realtimeSyncLock.unlock();
|
|
903
|
+
}
|
|
904
|
+
latestFetchedBlock = undefined;
|
|
905
|
+
fetchAndReconcileLatestBlockErrorCount = 0;
|
|
906
|
+
}
|
|
907
|
+
catch (_error) {
|
|
908
|
+
blockCallback?.(false);
|
|
909
|
+
onError(_error, block);
|
|
910
|
+
}
|
|
911
|
+
},
|
|
912
|
+
onError,
|
|
913
|
+
get unfinalizedBlocks() {
|
|
914
|
+
return unfinalizedBlocks;
|
|
915
|
+
},
|
|
916
|
+
};
|
|
917
|
+
};
|
|
918
|
+
//# sourceMappingURL=index.js.map
|