@subsquid/ponder 0.16.6

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.
Files changed (626) hide show
  1. package/CHANGELOG.md +3452 -0
  2. package/LICENSE +21 -0
  3. package/README.md +182 -0
  4. package/dist/esm/bin/commands/codegen.js +46 -0
  5. package/dist/esm/bin/commands/codegen.js.map +1 -0
  6. package/dist/esm/bin/commands/createViews.js +196 -0
  7. package/dist/esm/bin/commands/createViews.js.map +1 -0
  8. package/dist/esm/bin/commands/dev.js +430 -0
  9. package/dist/esm/bin/commands/dev.js.map +1 -0
  10. package/dist/esm/bin/commands/list.js +148 -0
  11. package/dist/esm/bin/commands/list.js.map +1 -0
  12. package/dist/esm/bin/commands/prune.js +223 -0
  13. package/dist/esm/bin/commands/prune.js.map +1 -0
  14. package/dist/esm/bin/commands/serve.js +198 -0
  15. package/dist/esm/bin/commands/serve.js.map +1 -0
  16. package/dist/esm/bin/commands/start.js +253 -0
  17. package/dist/esm/bin/commands/start.js.map +1 -0
  18. package/dist/esm/bin/isolatedController.js +200 -0
  19. package/dist/esm/bin/isolatedController.js.map +1 -0
  20. package/dist/esm/bin/isolatedWorker.js +146 -0
  21. package/dist/esm/bin/isolatedWorker.js.map +1 -0
  22. package/dist/esm/bin/ponder.js +137 -0
  23. package/dist/esm/bin/ponder.js.map +1 -0
  24. package/dist/esm/bin/utils/codegen.js +25 -0
  25. package/dist/esm/bin/utils/codegen.js.map +1 -0
  26. package/dist/esm/bin/utils/exit.js +100 -0
  27. package/dist/esm/bin/utils/exit.js.map +1 -0
  28. package/dist/esm/build/config.js +746 -0
  29. package/dist/esm/build/config.js.map +1 -0
  30. package/dist/esm/build/factory.js +82 -0
  31. package/dist/esm/build/factory.js.map +1 -0
  32. package/dist/esm/build/index.js +567 -0
  33. package/dist/esm/build/index.js.map +1 -0
  34. package/dist/esm/build/plugin.js +53 -0
  35. package/dist/esm/build/plugin.js.map +1 -0
  36. package/dist/esm/build/pre.js +83 -0
  37. package/dist/esm/build/pre.js.map +1 -0
  38. package/dist/esm/build/schema.js +202 -0
  39. package/dist/esm/build/schema.js.map +1 -0
  40. package/dist/esm/build/stacktrace.js +137 -0
  41. package/dist/esm/build/stacktrace.js.map +1 -0
  42. package/dist/esm/client/index.js +441 -0
  43. package/dist/esm/client/index.js.map +1 -0
  44. package/dist/esm/config/address.js +2 -0
  45. package/dist/esm/config/address.js.map +1 -0
  46. package/dist/esm/config/eventFilter.js +2 -0
  47. package/dist/esm/config/eventFilter.js.map +1 -0
  48. package/dist/esm/config/index.js +2 -0
  49. package/dist/esm/config/index.js.map +1 -0
  50. package/dist/esm/config/utilityTypes.js +2 -0
  51. package/dist/esm/config/utilityTypes.js.map +1 -0
  52. package/dist/esm/database/actions.js +445 -0
  53. package/dist/esm/database/actions.js.map +1 -0
  54. package/dist/esm/database/index.js +604 -0
  55. package/dist/esm/database/index.js.map +1 -0
  56. package/dist/esm/database/queryBuilder.js +314 -0
  57. package/dist/esm/database/queryBuilder.js.map +1 -0
  58. package/dist/esm/drizzle/bigint.js +38 -0
  59. package/dist/esm/drizzle/bigint.js.map +1 -0
  60. package/dist/esm/drizzle/bytes.js +47 -0
  61. package/dist/esm/drizzle/bytes.js.map +1 -0
  62. package/dist/esm/drizzle/hex.js +40 -0
  63. package/dist/esm/drizzle/hex.js.map +1 -0
  64. package/dist/esm/drizzle/index.js +28 -0
  65. package/dist/esm/drizzle/index.js.map +1 -0
  66. package/dist/esm/drizzle/json.js +123 -0
  67. package/dist/esm/drizzle/json.js.map +1 -0
  68. package/dist/esm/drizzle/kit/index.js +927 -0
  69. package/dist/esm/drizzle/kit/index.js.map +1 -0
  70. package/dist/esm/drizzle/onchain.js +184 -0
  71. package/dist/esm/drizzle/onchain.js.map +1 -0
  72. package/dist/esm/drizzle/text.js +61 -0
  73. package/dist/esm/drizzle/text.js.map +1 -0
  74. package/dist/esm/graphql/graphiql.html.js +59 -0
  75. package/dist/esm/graphql/graphiql.html.js.map +1 -0
  76. package/dist/esm/graphql/index.js +964 -0
  77. package/dist/esm/graphql/index.js.map +1 -0
  78. package/dist/esm/graphql/json.js +42 -0
  79. package/dist/esm/graphql/json.js.map +1 -0
  80. package/dist/esm/graphql/middleware.js +83 -0
  81. package/dist/esm/graphql/middleware.js.map +1 -0
  82. package/dist/esm/index.js +9 -0
  83. package/dist/esm/index.js.map +1 -0
  84. package/dist/esm/indexing/addStackTrace.js +54 -0
  85. package/dist/esm/indexing/addStackTrace.js.map +1 -0
  86. package/dist/esm/indexing/client.js +675 -0
  87. package/dist/esm/indexing/client.js.map +1 -0
  88. package/dist/esm/indexing/index.js +663 -0
  89. package/dist/esm/indexing/index.js.map +1 -0
  90. package/dist/esm/indexing/profile.js +584 -0
  91. package/dist/esm/indexing/profile.js.map +1 -0
  92. package/dist/esm/indexing-store/cache.js +666 -0
  93. package/dist/esm/indexing-store/cache.js.map +1 -0
  94. package/dist/esm/indexing-store/index.js +461 -0
  95. package/dist/esm/indexing-store/index.js.map +1 -0
  96. package/dist/esm/indexing-store/profile.js +428 -0
  97. package/dist/esm/indexing-store/profile.js.map +1 -0
  98. package/dist/esm/indexing-store/utils.js +111 -0
  99. package/dist/esm/indexing-store/utils.js.map +1 -0
  100. package/dist/esm/internal/common.js +2 -0
  101. package/dist/esm/internal/common.js.map +1 -0
  102. package/dist/esm/internal/errors.js +300 -0
  103. package/dist/esm/internal/errors.js.map +1 -0
  104. package/dist/esm/internal/logger.js +178 -0
  105. package/dist/esm/internal/logger.js.map +1 -0
  106. package/dist/esm/internal/metrics.js +1049 -0
  107. package/dist/esm/internal/metrics.js.map +1 -0
  108. package/dist/esm/internal/options.js +73 -0
  109. package/dist/esm/internal/options.js.map +1 -0
  110. package/dist/esm/internal/shutdown.js +24 -0
  111. package/dist/esm/internal/shutdown.js.map +1 -0
  112. package/dist/esm/internal/telemetry.js +200 -0
  113. package/dist/esm/internal/telemetry.js.map +1 -0
  114. package/dist/esm/internal/types.js +2 -0
  115. package/dist/esm/internal/types.js.map +1 -0
  116. package/dist/esm/rpc/actions.js +987 -0
  117. package/dist/esm/rpc/actions.js.map +1 -0
  118. package/dist/esm/rpc/http.js +130 -0
  119. package/dist/esm/rpc/http.js.map +1 -0
  120. package/dist/esm/rpc/index.js +749 -0
  121. package/dist/esm/rpc/index.js.map +1 -0
  122. package/dist/esm/runtime/events.js +664 -0
  123. package/dist/esm/runtime/events.js.map +1 -0
  124. package/dist/esm/runtime/filter.js +443 -0
  125. package/dist/esm/runtime/filter.js.map +1 -0
  126. package/dist/esm/runtime/fragments.js +478 -0
  127. package/dist/esm/runtime/fragments.js.map +1 -0
  128. package/dist/esm/runtime/historical.js +953 -0
  129. package/dist/esm/runtime/historical.js.map +1 -0
  130. package/dist/esm/runtime/index.js +316 -0
  131. package/dist/esm/runtime/index.js.map +1 -0
  132. package/dist/esm/runtime/isolated.js +463 -0
  133. package/dist/esm/runtime/isolated.js.map +1 -0
  134. package/dist/esm/runtime/multichain.js +510 -0
  135. package/dist/esm/runtime/multichain.js.map +1 -0
  136. package/dist/esm/runtime/omnichain.js +545 -0
  137. package/dist/esm/runtime/omnichain.js.map +1 -0
  138. package/dist/esm/runtime/realtime.js +724 -0
  139. package/dist/esm/runtime/realtime.js.map +1 -0
  140. package/dist/esm/server/error.js +56 -0
  141. package/dist/esm/server/error.js.map +1 -0
  142. package/dist/esm/server/index.js +121 -0
  143. package/dist/esm/server/index.js.map +1 -0
  144. package/dist/esm/sync-historical/index.js +711 -0
  145. package/dist/esm/sync-historical/index.js.map +1 -0
  146. package/dist/esm/sync-historical/portal-transform.js +104 -0
  147. package/dist/esm/sync-historical/portal-transform.js.map +1 -0
  148. package/dist/esm/sync-historical/portal.js +592 -0
  149. package/dist/esm/sync-historical/portal.js.map +1 -0
  150. package/dist/esm/sync-realtime/bloom.js +76 -0
  151. package/dist/esm/sync-realtime/bloom.js.map +1 -0
  152. package/dist/esm/sync-realtime/index.js +917 -0
  153. package/dist/esm/sync-realtime/index.js.map +1 -0
  154. package/dist/esm/sync-store/encode.js +105 -0
  155. package/dist/esm/sync-store/encode.js.map +1 -0
  156. package/dist/esm/sync-store/index.js +885 -0
  157. package/dist/esm/sync-store/index.js.map +1 -0
  158. package/dist/esm/sync-store/migrations.js +1595 -0
  159. package/dist/esm/sync-store/migrations.js.map +1 -0
  160. package/dist/esm/sync-store/schema.js +181 -0
  161. package/dist/esm/sync-store/schema.js.map +1 -0
  162. package/dist/esm/types/db.js +2 -0
  163. package/dist/esm/types/db.js.map +1 -0
  164. package/dist/esm/types/eth.js +2 -0
  165. package/dist/esm/types/eth.js.map +1 -0
  166. package/dist/esm/types/utils.js +2 -0
  167. package/dist/esm/types/utils.js.map +1 -0
  168. package/dist/esm/types/virtual.js +2 -0
  169. package/dist/esm/types/virtual.js.map +1 -0
  170. package/dist/esm/ui/app.js +157 -0
  171. package/dist/esm/ui/app.js.map +1 -0
  172. package/dist/esm/ui/index.js +29 -0
  173. package/dist/esm/ui/index.js.map +1 -0
  174. package/dist/esm/ui/patch.js +140 -0
  175. package/dist/esm/ui/patch.js.map +1 -0
  176. package/dist/esm/utils/abi.js +55 -0
  177. package/dist/esm/utils/abi.js.map +1 -0
  178. package/dist/esm/utils/bigint.js +37 -0
  179. package/dist/esm/utils/bigint.js.map +1 -0
  180. package/dist/esm/utils/chains.js +21 -0
  181. package/dist/esm/utils/chains.js.map +1 -0
  182. package/dist/esm/utils/checkpoint.js +139 -0
  183. package/dist/esm/utils/checkpoint.js.map +1 -0
  184. package/dist/esm/utils/chunk.js +8 -0
  185. package/dist/esm/utils/chunk.js.map +1 -0
  186. package/dist/esm/utils/copy.js +129 -0
  187. package/dist/esm/utils/copy.js.map +1 -0
  188. package/dist/esm/utils/date.js +27 -0
  189. package/dist/esm/utils/date.js.map +1 -0
  190. package/dist/esm/utils/debug.js +2 -0
  191. package/dist/esm/utils/debug.js.map +1 -0
  192. package/dist/esm/utils/decodeAbiParameters.js +290 -0
  193. package/dist/esm/utils/decodeAbiParameters.js.map +1 -0
  194. package/dist/esm/utils/decodeEventLog.js +75 -0
  195. package/dist/esm/utils/decodeEventLog.js.map +1 -0
  196. package/dist/esm/utils/dedupe.js +29 -0
  197. package/dist/esm/utils/dedupe.js.map +1 -0
  198. package/dist/esm/utils/duplicates.js +19 -0
  199. package/dist/esm/utils/duplicates.js.map +1 -0
  200. package/dist/esm/utils/estimate.js +6 -0
  201. package/dist/esm/utils/estimate.js.map +1 -0
  202. package/dist/esm/utils/finality.js +38 -0
  203. package/dist/esm/utils/finality.js.map +1 -0
  204. package/dist/esm/utils/format.js +20 -0
  205. package/dist/esm/utils/format.js.map +1 -0
  206. package/dist/esm/utils/generators.js +121 -0
  207. package/dist/esm/utils/generators.js.map +1 -0
  208. package/dist/esm/utils/hash.js +11 -0
  209. package/dist/esm/utils/hash.js.map +1 -0
  210. package/dist/esm/utils/interval.js +171 -0
  211. package/dist/esm/utils/interval.js.map +1 -0
  212. package/dist/esm/utils/lowercase.js +7 -0
  213. package/dist/esm/utils/lowercase.js.map +1 -0
  214. package/dist/esm/utils/mutex.js +26 -0
  215. package/dist/esm/utils/mutex.js.map +1 -0
  216. package/dist/esm/utils/never.js +4 -0
  217. package/dist/esm/utils/never.js.map +1 -0
  218. package/dist/esm/utils/offset.js +101 -0
  219. package/dist/esm/utils/offset.js.map +1 -0
  220. package/dist/esm/utils/order.js +18 -0
  221. package/dist/esm/utils/order.js.map +1 -0
  222. package/dist/esm/utils/partition.js +46 -0
  223. package/dist/esm/utils/partition.js.map +1 -0
  224. package/dist/esm/utils/pg.js +175 -0
  225. package/dist/esm/utils/pg.js.map +1 -0
  226. package/dist/esm/utils/pglite.js +80 -0
  227. package/dist/esm/utils/pglite.js.map +1 -0
  228. package/dist/esm/utils/port.js +30 -0
  229. package/dist/esm/utils/port.js.map +1 -0
  230. package/dist/esm/utils/print.js +24 -0
  231. package/dist/esm/utils/print.js.map +1 -0
  232. package/dist/esm/utils/promiseAllSettledWithThrow.js +19 -0
  233. package/dist/esm/utils/promiseAllSettledWithThrow.js.map +1 -0
  234. package/dist/esm/utils/promiseWithResolvers.js +13 -0
  235. package/dist/esm/utils/promiseWithResolvers.js.map +1 -0
  236. package/dist/esm/utils/queue.js +150 -0
  237. package/dist/esm/utils/queue.js.map +1 -0
  238. package/dist/esm/utils/range.js +8 -0
  239. package/dist/esm/utils/range.js.map +1 -0
  240. package/dist/esm/utils/result.js +10 -0
  241. package/dist/esm/utils/result.js.map +1 -0
  242. package/dist/esm/utils/sql-parse.js +1326 -0
  243. package/dist/esm/utils/sql-parse.js.map +1 -0
  244. package/dist/esm/utils/timer.js +9 -0
  245. package/dist/esm/utils/timer.js.map +1 -0
  246. package/dist/esm/utils/truncate.js +15 -0
  247. package/dist/esm/utils/truncate.js.map +1 -0
  248. package/dist/esm/utils/wait.js +10 -0
  249. package/dist/esm/utils/wait.js.map +1 -0
  250. package/dist/esm/utils/zipper.js +67 -0
  251. package/dist/esm/utils/zipper.js.map +1 -0
  252. package/dist/types/bin/commands/codegen.d.ts +5 -0
  253. package/dist/types/bin/commands/codegen.d.ts.map +1 -0
  254. package/dist/types/bin/commands/createViews.d.ts +8 -0
  255. package/dist/types/bin/commands/createViews.d.ts.map +1 -0
  256. package/dist/types/bin/commands/dev.d.ts +5 -0
  257. package/dist/types/bin/commands/dev.d.ts.map +1 -0
  258. package/dist/types/bin/commands/list.d.ts +5 -0
  259. package/dist/types/bin/commands/list.d.ts.map +1 -0
  260. package/dist/types/bin/commands/prune.d.ts +5 -0
  261. package/dist/types/bin/commands/prune.d.ts.map +1 -0
  262. package/dist/types/bin/commands/serve.d.ts +5 -0
  263. package/dist/types/bin/commands/serve.d.ts.map +1 -0
  264. package/dist/types/bin/commands/start.d.ts +19 -0
  265. package/dist/types/bin/commands/start.d.ts.map +1 -0
  266. package/dist/types/bin/isolatedController.d.ts +13 -0
  267. package/dist/types/bin/isolatedController.d.ts.map +1 -0
  268. package/dist/types/bin/isolatedWorker.d.ts +9 -0
  269. package/dist/types/bin/isolatedWorker.d.ts.map +1 -0
  270. package/dist/types/bin/ponder.d.ts +37 -0
  271. package/dist/types/bin/ponder.d.ts.map +1 -0
  272. package/dist/types/bin/utils/codegen.d.ts +6 -0
  273. package/dist/types/bin/utils/codegen.d.ts.map +1 -0
  274. package/dist/types/bin/utils/exit.d.ts +10 -0
  275. package/dist/types/bin/utils/exit.d.ts.map +1 -0
  276. package/dist/types/build/config.d.ts +97 -0
  277. package/dist/types/build/config.d.ts.map +1 -0
  278. package/dist/types/build/factory.d.ts +9 -0
  279. package/dist/types/build/factory.d.ts.map +1 -0
  280. package/dist/types/build/index.d.ts +84 -0
  281. package/dist/types/build/index.d.ts.map +1 -0
  282. package/dist/types/build/plugin.d.ts +4 -0
  283. package/dist/types/build/plugin.d.ts.map +1 -0
  284. package/dist/types/build/pre.d.ts +29 -0
  285. package/dist/types/build/pre.d.ts.map +1 -0
  286. package/dist/types/build/schema.d.ts +20 -0
  287. package/dist/types/build/schema.d.ts.map +1 -0
  288. package/dist/types/build/stacktrace.d.ts +13 -0
  289. package/dist/types/build/stacktrace.d.ts.map +1 -0
  290. package/dist/types/client/index.d.ts +27 -0
  291. package/dist/types/client/index.d.ts.map +1 -0
  292. package/dist/types/config/address.d.ts +35 -0
  293. package/dist/types/config/address.d.ts.map +1 -0
  294. package/dist/types/config/eventFilter.d.ts +18 -0
  295. package/dist/types/config/eventFilter.d.ts.map +1 -0
  296. package/dist/types/config/index.d.ts +150 -0
  297. package/dist/types/config/index.d.ts.map +1 -0
  298. package/dist/types/config/utilityTypes.d.ts +43 -0
  299. package/dist/types/config/utilityTypes.d.ts.map +1 -0
  300. package/dist/types/database/actions.d.ts +99 -0
  301. package/dist/types/database/actions.d.ts.map +1 -0
  302. package/dist/types/database/index.d.ts +493 -0
  303. package/dist/types/database/index.d.ts.map +1 -0
  304. package/dist/types/database/queryBuilder.d.ts +65 -0
  305. package/dist/types/database/queryBuilder.d.ts.map +1 -0
  306. package/dist/types/drizzle/bigint.d.ts +25 -0
  307. package/dist/types/drizzle/bigint.d.ts.map +1 -0
  308. package/dist/types/drizzle/bytes.d.ts +31 -0
  309. package/dist/types/drizzle/bytes.d.ts.map +1 -0
  310. package/dist/types/drizzle/hex.d.ts +25 -0
  311. package/dist/types/drizzle/hex.d.ts.map +1 -0
  312. package/dist/types/drizzle/index.d.ts +6 -0
  313. package/dist/types/drizzle/index.d.ts.map +1 -0
  314. package/dist/types/drizzle/json.d.ts +51 -0
  315. package/dist/types/drizzle/json.d.ts.map +1 -0
  316. package/dist/types/drizzle/kit/index.d.ts +187 -0
  317. package/dist/types/drizzle/kit/index.d.ts.map +1 -0
  318. package/dist/types/drizzle/onchain.d.ts +298 -0
  319. package/dist/types/drizzle/onchain.d.ts.map +1 -0
  320. package/dist/types/drizzle/text.d.ts +29 -0
  321. package/dist/types/drizzle/text.d.ts.map +1 -0
  322. package/dist/types/graphql/graphiql.html.d.ts +2 -0
  323. package/dist/types/graphql/graphiql.html.d.ts.map +1 -0
  324. package/dist/types/graphql/index.d.ts +12 -0
  325. package/dist/types/graphql/index.d.ts.map +1 -0
  326. package/dist/types/graphql/json.d.ts +3 -0
  327. package/dist/types/graphql/json.d.ts.map +1 -0
  328. package/dist/types/graphql/middleware.d.ts +29 -0
  329. package/dist/types/graphql/middleware.d.ts.map +1 -0
  330. package/dist/types/index.d.ts +23 -0
  331. package/dist/types/index.d.ts.map +1 -0
  332. package/dist/types/indexing/addStackTrace.d.ts +3 -0
  333. package/dist/types/indexing/addStackTrace.d.ts.map +1 -0
  334. package/dist/types/indexing/client.d.ts +154 -0
  335. package/dist/types/indexing/client.d.ts.map +1 -0
  336. package/dist/types/indexing/index.d.ts +72 -0
  337. package/dist/types/indexing/index.d.ts.map +1 -0
  338. package/dist/types/indexing/profile.d.ts +16 -0
  339. package/dist/types/indexing/profile.d.ts.map +1 -0
  340. package/dist/types/indexing-store/cache.d.ts +115 -0
  341. package/dist/types/indexing-store/cache.d.ts.map +1 -0
  342. package/dist/types/indexing-store/index.d.ts +24 -0
  343. package/dist/types/indexing-store/index.d.ts.map +1 -0
  344. package/dist/types/indexing-store/profile.d.ts +7 -0
  345. package/dist/types/indexing-store/profile.d.ts.map +1 -0
  346. package/dist/types/indexing-store/utils.d.ts +19 -0
  347. package/dist/types/indexing-store/utils.d.ts.map +1 -0
  348. package/dist/types/internal/common.d.ts +15 -0
  349. package/dist/types/internal/common.d.ts.map +1 -0
  350. package/dist/types/internal/errors.d.ts +101 -0
  351. package/dist/types/internal/errors.d.ts.map +1 -0
  352. package/dist/types/internal/logger.d.ts +37 -0
  353. package/dist/types/internal/logger.d.ts.map +1 -0
  354. package/dist/types/internal/metrics.d.ts +120 -0
  355. package/dist/types/internal/metrics.d.ts.map +1 -0
  356. package/dist/types/internal/options.d.ts +62 -0
  357. package/dist/types/internal/options.d.ts.map +1 -0
  358. package/dist/types/internal/shutdown.d.ts +8 -0
  359. package/dist/types/internal/shutdown.d.ts.map +1 -0
  360. package/dist/types/internal/telemetry.d.ts +43 -0
  361. package/dist/types/internal/telemetry.d.ts.map +1 -0
  362. package/dist/types/internal/types.d.ts +435 -0
  363. package/dist/types/internal/types.d.ts.map +1 -0
  364. package/dist/types/rpc/actions.d.ts +360 -0
  365. package/dist/types/rpc/actions.d.ts.map +1 -0
  366. package/dist/types/rpc/http.d.ts +17 -0
  367. package/dist/types/rpc/http.d.ts.map +1 -0
  368. package/dist/types/rpc/index.d.ts +43 -0
  369. package/dist/types/rpc/index.d.ts.map +1 -0
  370. package/dist/types/runtime/events.d.ts +40 -0
  371. package/dist/types/runtime/events.d.ts.map +1 -0
  372. package/dist/types/runtime/filter.d.ts +87 -0
  373. package/dist/types/runtime/filter.d.ts.map +1 -0
  374. package/dist/types/runtime/fragments.d.ts +30 -0
  375. package/dist/types/runtime/fragments.d.ts.map +1 -0
  376. package/dist/types/runtime/historical.d.ts +123 -0
  377. package/dist/types/runtime/historical.d.ts.map +1 -0
  378. package/dist/types/runtime/index.d.ts +89 -0
  379. package/dist/types/runtime/index.d.ts.map +1 -0
  380. package/dist/types/runtime/isolated.d.ts +14 -0
  381. package/dist/types/runtime/isolated.d.ts.map +1 -0
  382. package/dist/types/runtime/multichain.d.ts +13 -0
  383. package/dist/types/runtime/multichain.d.ts.map +1 -0
  384. package/dist/types/runtime/omnichain.d.ts +23 -0
  385. package/dist/types/runtime/omnichain.d.ts.map +1 -0
  386. package/dist/types/runtime/realtime.d.ts +93 -0
  387. package/dist/types/runtime/realtime.d.ts.map +1 -0
  388. package/dist/types/server/error.d.ts +5 -0
  389. package/dist/types/server/error.d.ts.map +1 -0
  390. package/dist/types/server/index.d.ts +13 -0
  391. package/dist/types/server/index.d.ts.map +1 -0
  392. package/dist/types/sync-historical/index.d.ts +36 -0
  393. package/dist/types/sync-historical/index.d.ts.map +1 -0
  394. package/dist/types/sync-historical/portal-transform.d.ts +50 -0
  395. package/dist/types/sync-historical/portal-transform.d.ts.map +1 -0
  396. package/dist/types/sync-historical/portal.d.ts +31 -0
  397. package/dist/types/sync-historical/portal.d.ts.map +1 -0
  398. package/dist/types/sync-realtime/bloom.d.ts +18 -0
  399. package/dist/types/sync-realtime/bloom.d.ts.map +1 -0
  400. package/dist/types/sync-realtime/index.d.ts +47 -0
  401. package/dist/types/sync-realtime/index.d.ts.map +1 -0
  402. package/dist/types/sync-store/encode.d.ts +25 -0
  403. package/dist/types/sync-store/encode.d.ts.map +1 -0
  404. package/dist/types/sync-store/index.d.ts +135 -0
  405. package/dist/types/sync-store/index.d.ts.map +1 -0
  406. package/dist/types/sync-store/migrations.d.ts +8 -0
  407. package/dist/types/sync-store/migrations.d.ts.map +1 -0
  408. package/dist/types/sync-store/schema.d.ts +1828 -0
  409. package/dist/types/sync-store/schema.d.ts.map +1 -0
  410. package/dist/types/types/db.d.ts +213 -0
  411. package/dist/types/types/db.d.ts.map +1 -0
  412. package/dist/types/types/eth.d.ts +196 -0
  413. package/dist/types/types/eth.d.ts.map +1 -0
  414. package/dist/types/types/utils.d.ts +38 -0
  415. package/dist/types/types/utils.d.ts.map +1 -0
  416. package/dist/types/types/virtual.d.ts +99 -0
  417. package/dist/types/types/virtual.d.ts.map +1 -0
  418. package/dist/types/ui/app.d.ts +22 -0
  419. package/dist/types/ui/app.d.ts.map +1 -0
  420. package/dist/types/ui/index.d.ts +5 -0
  421. package/dist/types/ui/index.d.ts.map +1 -0
  422. package/dist/types/ui/patch.d.ts +7 -0
  423. package/dist/types/ui/patch.d.ts.map +1 -0
  424. package/dist/types/utils/abi.d.ts +23 -0
  425. package/dist/types/utils/abi.d.ts.map +1 -0
  426. package/dist/types/utils/bigint.d.ts +15 -0
  427. package/dist/types/utils/bigint.d.ts.map +1 -0
  428. package/dist/types/utils/chains.d.ts +42 -0
  429. package/dist/types/utils/chains.d.ts.map +1 -0
  430. package/dist/types/utils/checkpoint.d.ts +52 -0
  431. package/dist/types/utils/checkpoint.d.ts.map +1 -0
  432. package/dist/types/utils/chunk.d.ts +2 -0
  433. package/dist/types/utils/chunk.d.ts.map +1 -0
  434. package/dist/types/utils/copy.d.ts +16 -0
  435. package/dist/types/utils/copy.d.ts.map +1 -0
  436. package/dist/types/utils/date.d.ts +7 -0
  437. package/dist/types/utils/date.d.ts.map +1 -0
  438. package/dist/types/utils/debug.d.ts +105 -0
  439. package/dist/types/utils/debug.d.ts.map +1 -0
  440. package/dist/types/utils/decodeAbiParameters.d.ts +28 -0
  441. package/dist/types/utils/decodeAbiParameters.d.ts.map +1 -0
  442. package/dist/types/utils/decodeEventLog.d.ts +12 -0
  443. package/dist/types/utils/decodeEventLog.d.ts.map +1 -0
  444. package/dist/types/utils/dedupe.d.ts +20 -0
  445. package/dist/types/utils/dedupe.d.ts.map +1 -0
  446. package/dist/types/utils/duplicates.d.ts +7 -0
  447. package/dist/types/utils/duplicates.d.ts.map +1 -0
  448. package/dist/types/utils/estimate.d.ts +11 -0
  449. package/dist/types/utils/estimate.d.ts.map +1 -0
  450. package/dist/types/utils/finality.d.ts +12 -0
  451. package/dist/types/utils/finality.d.ts.map +1 -0
  452. package/dist/types/utils/format.d.ts +3 -0
  453. package/dist/types/utils/format.d.ts.map +1 -0
  454. package/dist/types/utils/generators.d.ts +42 -0
  455. package/dist/types/utils/generators.d.ts.map +1 -0
  456. package/dist/types/utils/hash.d.ts +11 -0
  457. package/dist/types/utils/hash.d.ts.map +1 -0
  458. package/dist/types/utils/interval.d.ts +53 -0
  459. package/dist/types/utils/interval.d.ts.map +1 -0
  460. package/dist/types/utils/lowercase.d.ts +5 -0
  461. package/dist/types/utils/lowercase.d.ts.map +1 -0
  462. package/dist/types/utils/mutex.d.ts +5 -0
  463. package/dist/types/utils/mutex.d.ts.map +1 -0
  464. package/dist/types/utils/never.d.ts +2 -0
  465. package/dist/types/utils/never.d.ts.map +1 -0
  466. package/dist/types/utils/offset.d.ts +8 -0
  467. package/dist/types/utils/offset.d.ts.map +1 -0
  468. package/dist/types/utils/order.d.ts +2 -0
  469. package/dist/types/utils/order.d.ts.map +1 -0
  470. package/dist/types/utils/partition.d.ts +22 -0
  471. package/dist/types/utils/partition.d.ts.map +1 -0
  472. package/dist/types/utils/pg.d.ts +8 -0
  473. package/dist/types/utils/pg.d.ts.map +1 -0
  474. package/dist/types/utils/pglite.d.ts +25 -0
  475. package/dist/types/utils/pglite.d.ts.map +1 -0
  476. package/dist/types/utils/port.d.ts +5 -0
  477. package/dist/types/utils/port.d.ts.map +1 -0
  478. package/dist/types/utils/print.d.ts +4 -0
  479. package/dist/types/utils/print.d.ts.map +1 -0
  480. package/dist/types/utils/promiseAllSettledWithThrow.d.ts +8 -0
  481. package/dist/types/utils/promiseAllSettledWithThrow.d.ts.map +1 -0
  482. package/dist/types/utils/promiseWithResolvers.d.ts +10 -0
  483. package/dist/types/utils/promiseWithResolvers.d.ts.map +1 -0
  484. package/dist/types/utils/queue.d.ts +33 -0
  485. package/dist/types/utils/queue.d.ts.map +1 -0
  486. package/dist/types/utils/range.d.ts +8 -0
  487. package/dist/types/utils/range.d.ts.map +1 -0
  488. package/dist/types/utils/result.d.ts +17 -0
  489. package/dist/types/utils/result.d.ts.map +1 -0
  490. package/dist/types/utils/sql-parse.d.ts +21 -0
  491. package/dist/types/utils/sql-parse.d.ts.map +1 -0
  492. package/dist/types/utils/timer.d.ts +6 -0
  493. package/dist/types/utils/timer.d.ts.map +1 -0
  494. package/dist/types/utils/truncate.d.ts +9 -0
  495. package/dist/types/utils/truncate.d.ts.map +1 -0
  496. package/dist/types/utils/wait.d.ts +6 -0
  497. package/dist/types/utils/wait.d.ts.map +1 -0
  498. package/dist/types/utils/zipper.d.ts +36 -0
  499. package/dist/types/utils/zipper.d.ts.map +1 -0
  500. package/package.json +117 -0
  501. package/src/bin/commands/codegen.ts +56 -0
  502. package/src/bin/commands/createViews.ts +318 -0
  503. package/src/bin/commands/dev.ts +490 -0
  504. package/src/bin/commands/list.ts +208 -0
  505. package/src/bin/commands/prune.ts +322 -0
  506. package/src/bin/commands/serve.ts +236 -0
  507. package/src/bin/commands/start.ts +319 -0
  508. package/src/bin/isolatedController.ts +300 -0
  509. package/src/bin/isolatedWorker.ts +192 -0
  510. package/src/bin/ponder.ts +208 -0
  511. package/src/bin/utils/codegen.ts +32 -0
  512. package/src/bin/utils/exit.ts +112 -0
  513. package/src/build/config.ts +1142 -0
  514. package/src/build/factory.ts +125 -0
  515. package/src/build/index.ts +790 -0
  516. package/src/build/plugin.ts +58 -0
  517. package/src/build/pre.ts +114 -0
  518. package/src/build/schema.ts +358 -0
  519. package/src/build/stacktrace.ts +137 -0
  520. package/src/client/index.ts +551 -0
  521. package/src/config/address.ts +46 -0
  522. package/src/config/eventFilter.ts +33 -0
  523. package/src/config/index.ts +246 -0
  524. package/src/config/utilityTypes.ts +152 -0
  525. package/src/database/actions.ts +873 -0
  526. package/src/database/index.ts +1029 -0
  527. package/src/database/queryBuilder.ts +537 -0
  528. package/src/drizzle/bigint.ts +57 -0
  529. package/src/drizzle/bytes.ts +68 -0
  530. package/src/drizzle/hex.ts +58 -0
  531. package/src/drizzle/index.ts +40 -0
  532. package/src/drizzle/json.ts +159 -0
  533. package/src/drizzle/kit/index.ts +1348 -0
  534. package/src/drizzle/onchain.ts +476 -0
  535. package/src/drizzle/text.ts +77 -0
  536. package/src/graphql/graphiql.html.ts +59 -0
  537. package/src/graphql/index.ts +1390 -0
  538. package/src/graphql/json.ts +62 -0
  539. package/src/graphql/middleware.ts +115 -0
  540. package/src/index.ts +139 -0
  541. package/src/indexing/addStackTrace.ts +69 -0
  542. package/src/indexing/client.ts +1184 -0
  543. package/src/indexing/index.ts +976 -0
  544. package/src/indexing/profile.ts +771 -0
  545. package/src/indexing-store/cache.ts +1057 -0
  546. package/src/indexing-store/index.ts +630 -0
  547. package/src/indexing-store/profile.ts +557 -0
  548. package/src/indexing-store/utils.ts +164 -0
  549. package/src/internal/common.ts +15 -0
  550. package/src/internal/errors.ts +228 -0
  551. package/src/internal/logger.ts +252 -0
  552. package/src/internal/metrics.ts +1030 -0
  553. package/src/internal/options.ts +130 -0
  554. package/src/internal/shutdown.ts +32 -0
  555. package/src/internal/telemetry.ts +303 -0
  556. package/src/internal/types.ts +598 -0
  557. package/src/rpc/actions.ts +1343 -0
  558. package/src/rpc/http.ts +164 -0
  559. package/src/rpc/index.ts +959 -0
  560. package/src/runtime/events.ts +875 -0
  561. package/src/runtime/filter.ts +664 -0
  562. package/src/runtime/fragments.ts +674 -0
  563. package/src/runtime/historical.ts +1512 -0
  564. package/src/runtime/index.ts +569 -0
  565. package/src/runtime/isolated.ts +778 -0
  566. package/src/runtime/multichain.ts +860 -0
  567. package/src/runtime/omnichain.ts +920 -0
  568. package/src/runtime/realtime.ts +1166 -0
  569. package/src/server/error.ts +68 -0
  570. package/src/server/index.ts +173 -0
  571. package/src/sync-historical/index.ts +1072 -0
  572. package/src/sync-historical/portal-transform.ts +114 -0
  573. package/src/sync-historical/portal.ts +539 -0
  574. package/src/sync-realtime/bloom.ts +102 -0
  575. package/src/sync-realtime/index.ts +1298 -0
  576. package/src/sync-store/encode.ts +153 -0
  577. package/src/sync-store/index.ts +1633 -0
  578. package/src/sync-store/migrations.ts +1801 -0
  579. package/src/sync-store/schema.ts +248 -0
  580. package/src/types/db.ts +292 -0
  581. package/src/types/eth.ts +216 -0
  582. package/src/types/utils.ts +47 -0
  583. package/src/types/virtual.ts +244 -0
  584. package/src/types.d.ts +38 -0
  585. package/src/ui/app.ts +207 -0
  586. package/src/ui/index.ts +37 -0
  587. package/src/ui/patch.ts +204 -0
  588. package/src/utils/abi.ts +103 -0
  589. package/src/utils/bigint.ts +41 -0
  590. package/src/utils/chains.ts +22 -0
  591. package/src/utils/checkpoint.ts +203 -0
  592. package/src/utils/chunk.ts +7 -0
  593. package/src/utils/copy.ts +151 -0
  594. package/src/utils/date.ts +26 -0
  595. package/src/utils/debug.ts +110 -0
  596. package/src/utils/decodeAbiParameters.ts +428 -0
  597. package/src/utils/decodeEventLog.ts +100 -0
  598. package/src/utils/dedupe.ts +32 -0
  599. package/src/utils/duplicates.ts +19 -0
  600. package/src/utils/estimate.ts +27 -0
  601. package/src/utils/finality.ts +40 -0
  602. package/src/utils/format.ts +22 -0
  603. package/src/utils/generators.ts +157 -0
  604. package/src/utils/hash.ts +22 -0
  605. package/src/utils/interval.ts +212 -0
  606. package/src/utils/lowercase.ts +6 -0
  607. package/src/utils/mutex.ts +33 -0
  608. package/src/utils/never.ts +3 -0
  609. package/src/utils/offset.ts +133 -0
  610. package/src/utils/order.ts +16 -0
  611. package/src/utils/partition.ts +53 -0
  612. package/src/utils/pg.ts +230 -0
  613. package/src/utils/pglite.ts +97 -0
  614. package/src/utils/port.ts +34 -0
  615. package/src/utils/print.ts +34 -0
  616. package/src/utils/promiseAllSettledWithThrow.ts +27 -0
  617. package/src/utils/promiseWithResolvers.ts +20 -0
  618. package/src/utils/queue.ts +258 -0
  619. package/src/utils/range.ts +8 -0
  620. package/src/utils/result.ts +26 -0
  621. package/src/utils/sql-parse.ts +1477 -0
  622. package/src/utils/timer.ts +8 -0
  623. package/src/utils/truncate.ts +15 -0
  624. package/src/utils/wait.ts +8 -0
  625. package/src/utils/zipper.ts +80 -0
  626. package/tsconfig.json +12 -0
@@ -0,0 +1,1512 @@
1
+ import type { Database } from "@/database/index.js";
2
+ import type { Common } from "@/internal/common.js";
3
+ import { ShutdownError } from "@/internal/errors.js";
4
+ import type {
5
+ Chain,
6
+ CrashRecoveryCheckpoint,
7
+ Event,
8
+ EventCallback,
9
+ IndexingBuild,
10
+ RawEvent,
11
+ SyncBlock,
12
+ } from "@/internal/types.js";
13
+ import { eth_getBlockByNumber } from "@/rpc/actions.js";
14
+ import type { Rpc } from "@/rpc/index.js";
15
+ import { buildEvents, decodeEvents } from "@/runtime/events.js";
16
+ import { createHistoricalSync } from "@/sync-historical/index.js";
17
+ import { createPortalHistoricalSync } from "@/sync-historical/portal.js";
18
+ import { type SyncStore, createSyncStore } from "@/sync-store/index.js";
19
+ import {
20
+ MAX_CHECKPOINT,
21
+ ZERO_CHECKPOINT,
22
+ decodeCheckpoint,
23
+ encodeCheckpoint,
24
+ min,
25
+ } from "@/utils/checkpoint.js";
26
+ import { estimate } from "@/utils/estimate.js";
27
+ import { formatPercentage } from "@/utils/format.js";
28
+ import {
29
+ bufferAsyncGenerator,
30
+ createCallbackGenerator,
31
+ mergeAsyncGenerators,
32
+ } from "@/utils/generators.js";
33
+ import { type Interval, intervalSum } from "@/utils/interval.js";
34
+ import { partition } from "@/utils/partition.js";
35
+ import { promiseWithResolvers } from "@/utils/promiseWithResolvers.js";
36
+ import { startClock } from "@/utils/timer.js";
37
+ import { hexToNumber, numberToHex } from "viem";
38
+ import {
39
+ type CachedIntervals,
40
+ type ChildAddresses,
41
+ type SyncProgress,
42
+ getRequiredIntervals,
43
+ getRequiredIntervalsWithFilters,
44
+ } from "./index.js";
45
+ import { getOmnichainCheckpoint } from "./omnichain.js";
46
+
47
+ export async function* getHistoricalEventsOmnichain(params: {
48
+ common: Common;
49
+ indexingBuild: Pick<IndexingBuild, "eventCallbacks" | "chains" | "rpcs">;
50
+ crashRecoveryCheckpoint: CrashRecoveryCheckpoint;
51
+ perChainSync: Map<
52
+ Chain,
53
+ {
54
+ syncProgress: SyncProgress;
55
+ childAddresses: ChildAddresses;
56
+ cachedIntervals: CachedIntervals;
57
+ }
58
+ >;
59
+ database: Database;
60
+ }): AsyncGenerator<
61
+ | {
62
+ type: "events";
63
+ result: {
64
+ chainId: number;
65
+ events: Event[];
66
+ checkpoint: string;
67
+ blockRange: [number, number];
68
+ }[];
69
+ }
70
+ | { type: "pending"; result: Event[] }
71
+ > {
72
+ let pendingEvents: Event[] = [];
73
+ let isCatchup = false;
74
+ const perChainCursor = new Map<Chain, string>();
75
+
76
+ while (true) {
77
+ const eventGenerators = Array.from(params.perChainSync.entries()).map(
78
+ async function* ([
79
+ chain,
80
+ { syncProgress, childAddresses, cachedIntervals },
81
+ ]) {
82
+ const rpc =
83
+ params.indexingBuild.rpcs[
84
+ params.indexingBuild.chains.findIndex((c) => c.id === chain.id)
85
+ ]!;
86
+
87
+ const eventCallbacks =
88
+ params.indexingBuild.eventCallbacks[
89
+ params.indexingBuild.chains.findIndex((c) => c.id === chain.id)
90
+ ]!;
91
+
92
+ const crashRecoveryCheckpoint = params.crashRecoveryCheckpoint?.find(
93
+ ({ chainId }) => chainId === chain.id,
94
+ )?.checkpoint;
95
+
96
+ const to = min(
97
+ syncProgress.getCheckpoint({ tag: "finalized" }),
98
+ syncProgress.getCheckpoint({ tag: "end" }),
99
+ );
100
+ const omnichainTo = min(
101
+ getOmnichainCheckpoint({
102
+ perChainSync: params.perChainSync,
103
+ tag: "finalized",
104
+ }),
105
+ getOmnichainCheckpoint({
106
+ perChainSync: params.perChainSync,
107
+ tag: "end",
108
+ }),
109
+ );
110
+ let from: string;
111
+
112
+ if (isCatchup === false) {
113
+ // In order to speed up the "extract" phase when there is a crash recovery,
114
+ // the beginning cursor is moved forwards. This only works when `crashRecoveryCheckpoint`
115
+ // is defined.
116
+
117
+ if (crashRecoveryCheckpoint === undefined) {
118
+ from = syncProgress.getCheckpoint({ tag: "start" });
119
+ } else if (
120
+ Number(decodeCheckpoint(crashRecoveryCheckpoint).chainId) ===
121
+ chain.id
122
+ ) {
123
+ from = crashRecoveryCheckpoint;
124
+ } else {
125
+ const fromBlock = await createSyncStore({
126
+ common: params.common,
127
+ qb: params.database.syncQB,
128
+ }).getSafeCrashRecoveryBlock({
129
+ chainId: chain.id,
130
+ timestamp: Number(
131
+ decodeCheckpoint(crashRecoveryCheckpoint).blockTimestamp,
132
+ ),
133
+ });
134
+
135
+ if (fromBlock === undefined) {
136
+ from = syncProgress.getCheckpoint({ tag: "start" });
137
+ } else {
138
+ from = encodeCheckpoint({
139
+ ...ZERO_CHECKPOINT,
140
+ blockNumber: fromBlock.number,
141
+ blockTimestamp: fromBlock.timestamp,
142
+ chainId: BigInt(chain.id),
143
+ });
144
+ }
145
+ }
146
+ } else {
147
+ // Previous iterations `to` value
148
+ const cursor = perChainCursor.get(chain)!;
149
+
150
+ // Yield pending events from previous iterations. Note that it is possible for
151
+ // previous pending events to still be pending after the catchup.
152
+
153
+ const events = pendingEvents.filter(
154
+ (event) =>
155
+ event.chain.id === chain.id && event.checkpoint <= omnichainTo,
156
+ );
157
+
158
+ pendingEvents = pendingEvents.filter(
159
+ (event) =>
160
+ (event.chain.id === chain.id &&
161
+ event.checkpoint <= omnichainTo) === false,
162
+ );
163
+
164
+ if (events.length > 0) {
165
+ if (omnichainTo >= cursor) {
166
+ const blockRange = [
167
+ Number(decodeCheckpoint(events[0]!.checkpoint).blockNumber),
168
+ Number(decodeCheckpoint(cursor).blockNumber),
169
+ ] satisfies [number, number];
170
+
171
+ yield { events, checkpoint: cursor, blockRange };
172
+ } else {
173
+ const checkpoint = events[events.length - 1]!.checkpoint;
174
+
175
+ const blockRange = [
176
+ Number(decodeCheckpoint(events[0]!.checkpoint).blockNumber),
177
+ Number(decodeCheckpoint(checkpoint).blockNumber),
178
+ ] satisfies [number, number];
179
+
180
+ yield { events, checkpoint, blockRange };
181
+ }
182
+ }
183
+
184
+ from = encodeCheckpoint({
185
+ ...ZERO_CHECKPOINT,
186
+ blockTimestamp: decodeCheckpoint(cursor).blockTimestamp,
187
+ chainId: decodeCheckpoint(cursor).chainId,
188
+ blockNumber: decodeCheckpoint(cursor).blockNumber + 1n,
189
+ });
190
+
191
+ if (from > to) return;
192
+ }
193
+
194
+ params.common.logger.info({
195
+ msg: "Started backfill indexing",
196
+ chain: chain.name,
197
+ chain_id: chain.id,
198
+ block_range: JSON.stringify([
199
+ Number(decodeCheckpoint(from).blockNumber),
200
+ Number(decodeCheckpoint(to).blockNumber),
201
+ ]),
202
+ });
203
+
204
+ const eventGenerator = getLocalEventGenerator({
205
+ common: params.common,
206
+ chain,
207
+ rpc,
208
+ eventCallbacks,
209
+ childAddresses,
210
+ syncProgress,
211
+ cachedIntervals,
212
+ from,
213
+ to,
214
+ limit:
215
+ Math.round(
216
+ params.common.options.syncEventsQuerySize /
217
+ (params.indexingBuild.chains.length + 1),
218
+ ) + 6,
219
+ database: params.database,
220
+ isCatchup,
221
+ });
222
+
223
+ for await (let {
224
+ events: rawEvents,
225
+ checkpoint,
226
+ blockRange,
227
+ } of eventGenerator) {
228
+ const endClock = startClock();
229
+
230
+ let events = decodeEvents(
231
+ params.common,
232
+ chain,
233
+ eventCallbacks,
234
+ rawEvents,
235
+ );
236
+
237
+ params.common.logger.trace({
238
+ msg: "Decoded events",
239
+ chain: chain.name,
240
+ chain_id: chain.id,
241
+ event_count: events.length,
242
+ duration: endClock(),
243
+ });
244
+
245
+ params.common.metrics.ponder_historical_extract_duration.inc(
246
+ { step: "decode" },
247
+ endClock(),
248
+ );
249
+
250
+ // Removes events that have a checkpoint earlier than (or equal to)
251
+ // the crash recovery checkpoint.
252
+
253
+ if (crashRecoveryCheckpoint) {
254
+ const [left, right] = partition(
255
+ events,
256
+ (event) => event.checkpoint <= crashRecoveryCheckpoint,
257
+ );
258
+ events = right;
259
+
260
+ if (left.length > 0) {
261
+ params.common.logger.trace({
262
+ msg: "Filtered events before crash recovery checkpoint",
263
+ chain: chain.name,
264
+ chain_id: chain.id,
265
+ event_count: left.length,
266
+ checkpoint: crashRecoveryCheckpoint,
267
+ });
268
+ }
269
+ }
270
+
271
+ // Sort out any events between the omnichain finalized checkpoint and the single-chain
272
+ // finalized checkpoint and add them to pendingEvents. These events are synced during
273
+ // the historical phase, but must be indexed in the realtime phase because events
274
+ // synced in realtime on other chains might be ordered before them.
275
+
276
+ if (checkpoint > omnichainTo) {
277
+ const [left, right] = partition(
278
+ events,
279
+ (event) => event.checkpoint <= omnichainTo,
280
+ );
281
+ events = left;
282
+ pendingEvents = pendingEvents.concat(right);
283
+
284
+ params.common.logger.trace({
285
+ msg: "Filtered pending events",
286
+ chain: chain.name,
287
+ chain_id: chain.id,
288
+ event_count: right.length,
289
+ checkpoint: omnichainTo,
290
+ });
291
+
292
+ if (left.length > 0) {
293
+ checkpoint = left[left.length - 1]!.checkpoint;
294
+ blockRange[1] = Number(
295
+ decodeCheckpoint(left[left.length - 1]!.checkpoint).blockNumber,
296
+ );
297
+
298
+ yield { events, checkpoint, blockRange };
299
+ }
300
+ } else {
301
+ yield { events, checkpoint, blockRange };
302
+ }
303
+ }
304
+
305
+ perChainCursor.set(chain, to);
306
+ },
307
+ );
308
+
309
+ const eventGenerator = mergeAsyncGeneratorsWithEventOrder(eventGenerators);
310
+
311
+ for await (const mergeResults of eventGenerator) {
312
+ yield { type: "events", result: mergeResults };
313
+ }
314
+
315
+ const context = {
316
+ logger: params.common.logger.child({ action: "refetch_finalized_block" }),
317
+ retryNullBlockRequest: true,
318
+ };
319
+
320
+ const endClock = startClock();
321
+
322
+ const finalizedBlocks = await Promise.all(
323
+ params.indexingBuild.chains.map((chain, i) => {
324
+ const rpc = params.indexingBuild.rpcs[i]!;
325
+
326
+ return eth_getBlockByNumber(rpc, ["latest", false], context)
327
+ .then((latest) =>
328
+ eth_getBlockByNumber(
329
+ rpc,
330
+ [
331
+ numberToHex(
332
+ Math.max(
333
+ hexToNumber(latest.number) - chain.finalityBlockCount,
334
+ 0,
335
+ ),
336
+ ),
337
+ false,
338
+ ],
339
+ context,
340
+ ),
341
+ )
342
+ .then((finalizedBlock) => {
343
+ const finalizedBlockNumber = hexToNumber(finalizedBlock.number);
344
+ params.common.logger.debug({
345
+ msg: "Refetched finalized block for backfill cutover",
346
+ chain: chain.name,
347
+ chain_id: chain.id,
348
+ finalized_block: finalizedBlockNumber,
349
+ duration: endClock(),
350
+ });
351
+
352
+ return finalizedBlock;
353
+ });
354
+ }),
355
+ );
356
+
357
+ let shouldCatchup = false;
358
+
359
+ for (let i = 0; i < params.indexingBuild.chains.length; i++) {
360
+ const chain = params.indexingBuild.chains[i]!;
361
+ const oldFinalizedBlock =
362
+ params.perChainSync.get(chain)!.syncProgress.finalized;
363
+ const newFinalizedBlock = finalizedBlocks[i]!;
364
+
365
+ if (
366
+ hexToNumber(newFinalizedBlock.number) -
367
+ hexToNumber(oldFinalizedBlock.number) >
368
+ chain.finalityBlockCount
369
+ ) {
370
+ shouldCatchup = true;
371
+ break;
372
+ }
373
+ }
374
+
375
+ if (shouldCatchup === false) break;
376
+
377
+ for (let i = 0; i < params.indexingBuild.chains.length; i++) {
378
+ const chain = params.indexingBuild.chains[i]!;
379
+ const finalizedBlock = finalizedBlocks[i]!;
380
+
381
+ params.perChainSync.get(chain)!.syncProgress.finalized = finalizedBlock;
382
+ }
383
+
384
+ isCatchup = true;
385
+ }
386
+
387
+ yield { type: "pending", result: pendingEvents };
388
+ }
389
+
390
+ export async function* getHistoricalEventsMultichain(params: {
391
+ common: Common;
392
+ indexingBuild: Pick<IndexingBuild, "eventCallbacks" | "chains" | "rpcs">;
393
+ crashRecoveryCheckpoint: CrashRecoveryCheckpoint;
394
+ perChainSync: Map<
395
+ Chain,
396
+ {
397
+ syncProgress: SyncProgress;
398
+ childAddresses: ChildAddresses;
399
+ cachedIntervals: CachedIntervals;
400
+ }
401
+ >;
402
+ database: Database;
403
+ }) {
404
+ let isCatchup = false;
405
+ let lastUnfinalizedRefetch = Date.now();
406
+ const perChainCursor = new Map<Chain, string>();
407
+
408
+ while (true) {
409
+ const eventGenerators = Array.from(params.perChainSync.entries()).map(
410
+ async function* ([
411
+ chain,
412
+ { syncProgress, childAddresses, cachedIntervals },
413
+ ]) {
414
+ const rpc =
415
+ params.indexingBuild.rpcs[
416
+ params.indexingBuild.chains.findIndex((c) => c.id === chain.id)
417
+ ]!;
418
+
419
+ const eventCallbacks =
420
+ params.indexingBuild.eventCallbacks[
421
+ params.indexingBuild.chains.findIndex((c) => c.id === chain.id)
422
+ ]!;
423
+
424
+ const crashRecoveryCheckpoint = params.crashRecoveryCheckpoint?.find(
425
+ ({ chainId }) => chainId === chain.id,
426
+ )?.checkpoint;
427
+
428
+ const to = min(
429
+ syncProgress.getCheckpoint({ tag: "finalized" }),
430
+ syncProgress.getCheckpoint({ tag: "end" }),
431
+ );
432
+ let from: string;
433
+
434
+ if (isCatchup === false) {
435
+ // In order to speed up the "extract" phase when there is a crash recovery,
436
+ // the beginning cursor is moved forwards. This only works when `crashRecoveryCheckpoint`
437
+ // is defined.
438
+
439
+ if (crashRecoveryCheckpoint === undefined) {
440
+ from = syncProgress.getCheckpoint({ tag: "start" });
441
+ } else if (
442
+ Number(decodeCheckpoint(crashRecoveryCheckpoint).chainId) ===
443
+ chain.id
444
+ ) {
445
+ from = crashRecoveryCheckpoint;
446
+ } else {
447
+ const fromBlock = await createSyncStore({
448
+ common: params.common,
449
+ qb: params.database.syncQB,
450
+ }).getSafeCrashRecoveryBlock({
451
+ chainId: chain.id,
452
+ timestamp: Number(
453
+ decodeCheckpoint(crashRecoveryCheckpoint).blockTimestamp,
454
+ ),
455
+ });
456
+
457
+ if (fromBlock === undefined) {
458
+ from = syncProgress.getCheckpoint({ tag: "start" });
459
+ } else {
460
+ from = encodeCheckpoint({
461
+ ...ZERO_CHECKPOINT,
462
+ blockNumber: fromBlock.number,
463
+ blockTimestamp: fromBlock.timestamp,
464
+ chainId: BigInt(chain.id),
465
+ });
466
+ }
467
+ }
468
+ } else {
469
+ const cursor = perChainCursor.get(chain)!;
470
+
471
+ from = encodeCheckpoint({
472
+ ...ZERO_CHECKPOINT,
473
+ blockTimestamp: decodeCheckpoint(cursor).blockTimestamp,
474
+ chainId: decodeCheckpoint(cursor).chainId,
475
+ blockNumber: decodeCheckpoint(cursor).blockNumber + 1n,
476
+ });
477
+
478
+ if (from > to) return;
479
+ }
480
+
481
+ params.common.logger.info({
482
+ msg: "Started backfill indexing",
483
+ chain: chain.name,
484
+ chain_id: chain.id,
485
+ block_range: JSON.stringify([
486
+ Number(decodeCheckpoint(from).blockNumber),
487
+ Number(decodeCheckpoint(to).blockNumber),
488
+ ]),
489
+ });
490
+
491
+ const eventGenerator = getLocalEventGenerator({
492
+ common: params.common,
493
+ chain,
494
+ rpc,
495
+ eventCallbacks,
496
+ childAddresses,
497
+ syncProgress,
498
+ cachedIntervals,
499
+ from,
500
+ to,
501
+ limit:
502
+ Math.round(
503
+ params.common.options.syncEventsQuerySize /
504
+ (params.indexingBuild.chains.length + 1),
505
+ ) + 6,
506
+ database: params.database,
507
+ isCatchup,
508
+ });
509
+
510
+ for await (const {
511
+ events: rawEvents,
512
+ checkpoint,
513
+ blockRange,
514
+ } of eventGenerator) {
515
+ const endClock = startClock();
516
+
517
+ let events = decodeEvents(
518
+ params.common,
519
+ chain,
520
+ eventCallbacks,
521
+ rawEvents,
522
+ );
523
+
524
+ params.common.logger.trace({
525
+ msg: "Decoded events",
526
+ chain: chain.name,
527
+ chain_id: chain.id,
528
+ event_count: events.length,
529
+ duration: endClock(),
530
+ });
531
+
532
+ params.common.metrics.ponder_historical_extract_duration.inc(
533
+ { step: "decode" },
534
+ endClock(),
535
+ );
536
+
537
+ // Removes events that have a checkpoint earlier than (or equal to)
538
+ // the crash recovery checkpoint.
539
+
540
+ if (crashRecoveryCheckpoint) {
541
+ const [left, right] = partition(
542
+ events,
543
+ (event) => event.checkpoint <= crashRecoveryCheckpoint,
544
+ );
545
+ events = right;
546
+
547
+ if (left.length > 0) {
548
+ params.common.logger.trace({
549
+ msg: "Filtered events before crash recovery checkpoint",
550
+ chain: chain.name,
551
+ chain_id: chain.id,
552
+ event_count: left.length,
553
+ checkpoint: crashRecoveryCheckpoint,
554
+ });
555
+ }
556
+ }
557
+
558
+ yield { chainId: chain.id, events, checkpoint, blockRange };
559
+ }
560
+
561
+ perChainCursor.set(chain, to);
562
+ },
563
+ );
564
+
565
+ yield* mergeAsyncGenerators(eventGenerators);
566
+
567
+ if (Date.now() - lastUnfinalizedRefetch < 30_000) {
568
+ break;
569
+ }
570
+ lastUnfinalizedRefetch = Date.now();
571
+
572
+ const context = {
573
+ logger: params.common.logger.child({ action: "refetch_finalized_block" }),
574
+ retryNullBlockRequest: true,
575
+ };
576
+
577
+ const endClock = startClock();
578
+
579
+ const finalizedBlocks = await Promise.all(
580
+ params.indexingBuild.chains.map((chain, i) => {
581
+ const rpc = params.indexingBuild.rpcs[i]!;
582
+
583
+ return eth_getBlockByNumber(rpc, ["latest", false], context)
584
+ .then((latest) =>
585
+ eth_getBlockByNumber(
586
+ rpc,
587
+ [
588
+ numberToHex(
589
+ Math.max(
590
+ hexToNumber(latest.number) - chain.finalityBlockCount,
591
+ 0,
592
+ ),
593
+ ),
594
+ false,
595
+ ],
596
+ context,
597
+ ),
598
+ )
599
+ .then((finalizedBlock) => {
600
+ const finalizedBlockNumber = hexToNumber(finalizedBlock.number);
601
+ params.common.logger.debug({
602
+ msg: "Refetched finalized block for backfill cutover",
603
+ chain: chain.name,
604
+ chain_id: chain.id,
605
+ finalized_block: finalizedBlockNumber,
606
+ duration: endClock(),
607
+ });
608
+
609
+ return finalizedBlock;
610
+ });
611
+ }),
612
+ );
613
+
614
+ let shouldCatchup = false;
615
+
616
+ for (let i = 0; i < params.indexingBuild.chains.length; i++) {
617
+ const chain = params.indexingBuild.chains[i]!;
618
+ const oldFinalizedBlock =
619
+ params.perChainSync.get(chain)!.syncProgress.finalized;
620
+ const newFinalizedBlock = finalizedBlocks[i]!;
621
+
622
+ if (
623
+ hexToNumber(newFinalizedBlock.number) -
624
+ hexToNumber(oldFinalizedBlock.number) >
625
+ chain.finalityBlockCount
626
+ ) {
627
+ shouldCatchup = true;
628
+ break;
629
+ }
630
+ }
631
+
632
+ if (shouldCatchup === false) break;
633
+
634
+ for (let i = 0; i < params.indexingBuild.chains.length; i++) {
635
+ const chain = params.indexingBuild.chains[i]!;
636
+ const finalizedBlock = finalizedBlocks[i]!;
637
+
638
+ params.perChainSync.get(chain)!.syncProgress.finalized = finalizedBlock;
639
+ }
640
+
641
+ isCatchup = true;
642
+ }
643
+ }
644
+
645
+ export async function* getHistoricalEventsIsolated(params: {
646
+ common: Common;
647
+ indexingBuild: Pick<IndexingBuild, "eventCallbacks" | "chains" | "rpcs">;
648
+ crashRecoveryCheckpoint: CrashRecoveryCheckpoint;
649
+ chain: Chain;
650
+ syncProgress: SyncProgress;
651
+ childAddresses: ChildAddresses;
652
+ cachedIntervals: CachedIntervals;
653
+ database: Database;
654
+ }) {
655
+ let isCatchup = false;
656
+ let lastUnfinalizedRefetch = Date.now();
657
+ let cursor: string | undefined;
658
+
659
+ while (true) {
660
+ const rpc =
661
+ params.indexingBuild.rpcs[
662
+ params.indexingBuild.chains.findIndex((c) => c.id === params.chain.id)
663
+ ]!;
664
+
665
+ const eventCallbacks =
666
+ params.indexingBuild.eventCallbacks[
667
+ params.indexingBuild.chains.findIndex((c) => c.id === params.chain.id)
668
+ ]!;
669
+
670
+ const crashRecoveryCheckpoint = params.crashRecoveryCheckpoint?.find(
671
+ ({ chainId }) => chainId === params.chain.id,
672
+ )?.checkpoint;
673
+
674
+ const to = min(
675
+ params.syncProgress.getCheckpoint({ tag: "finalized" }),
676
+ params.syncProgress.getCheckpoint({ tag: "end" }),
677
+ );
678
+ let from: string;
679
+
680
+ if (isCatchup === false) {
681
+ // In order to speed up the "extract" phase when there is a crash recovery,
682
+ // the beginning cursor is moved forwards. This only works when `crashRecoveryCheckpoint`
683
+ // is defined.
684
+
685
+ if (crashRecoveryCheckpoint === undefined) {
686
+ from = params.syncProgress.getCheckpoint({ tag: "start" });
687
+ } else if (
688
+ Number(decodeCheckpoint(crashRecoveryCheckpoint).chainId) ===
689
+ params.chain.id
690
+ ) {
691
+ from = crashRecoveryCheckpoint;
692
+ } else {
693
+ from = params.syncProgress.getCheckpoint({ tag: "start" });
694
+ }
695
+ } else {
696
+ from = encodeCheckpoint({
697
+ ...ZERO_CHECKPOINT,
698
+ blockTimestamp: decodeCheckpoint(cursor!).blockTimestamp,
699
+ chainId: decodeCheckpoint(cursor!).chainId,
700
+ blockNumber: decodeCheckpoint(cursor!).blockNumber + 1n,
701
+ });
702
+
703
+ if (from > to) return;
704
+ }
705
+
706
+ params.common.logger.info({
707
+ msg: "Started backfill indexing",
708
+ chain: params.chain.name,
709
+ chain_id: params.chain.id,
710
+ block_range: JSON.stringify([
711
+ Number(decodeCheckpoint(from).blockNumber),
712
+ Number(decodeCheckpoint(to).blockNumber),
713
+ ]),
714
+ });
715
+
716
+ const eventGenerator = getLocalEventGenerator({
717
+ common: params.common,
718
+ chain: params.chain,
719
+ rpc,
720
+ eventCallbacks,
721
+ childAddresses: params.childAddresses,
722
+ syncProgress: params.syncProgress,
723
+ cachedIntervals: params.cachedIntervals,
724
+ from,
725
+ to,
726
+ limit:
727
+ Math.round(
728
+ params.common.options.syncEventsQuerySize /
729
+ (params.indexingBuild.chains.length + 1),
730
+ ) + 6,
731
+ database: params.database,
732
+ isCatchup,
733
+ });
734
+
735
+ for await (const {
736
+ events: rawEvents,
737
+ checkpoint,
738
+ blockRange,
739
+ } of eventGenerator) {
740
+ const endClock = startClock();
741
+
742
+ let events = decodeEvents(
743
+ params.common,
744
+ params.chain,
745
+ eventCallbacks,
746
+ rawEvents,
747
+ );
748
+
749
+ params.common.logger.trace({
750
+ msg: "Decoded events",
751
+ chain: params.chain.name,
752
+ chain_id: params.chain.id,
753
+ event_count: events.length,
754
+ duration: endClock(),
755
+ });
756
+
757
+ params.common.metrics.ponder_historical_extract_duration.inc(
758
+ { step: "decode" },
759
+ endClock(),
760
+ );
761
+
762
+ // Removes events that have a checkpoint earlier than (or equal to)
763
+ // the crash recovery checkpoint.
764
+
765
+ if (crashRecoveryCheckpoint) {
766
+ const [left, right] = partition(
767
+ events,
768
+ (event) => event.checkpoint <= crashRecoveryCheckpoint,
769
+ );
770
+ events = right;
771
+
772
+ if (left.length > 0) {
773
+ params.common.logger.trace({
774
+ msg: "Filtered events before crash recovery checkpoint",
775
+ chain: params.chain.name,
776
+ chain_id: params.chain.id,
777
+ event_count: left.length,
778
+ checkpoint: crashRecoveryCheckpoint,
779
+ });
780
+ }
781
+ }
782
+
783
+ yield { chainId: params.chain.id, events, checkpoint, blockRange };
784
+ }
785
+
786
+ cursor = to;
787
+
788
+ if (Date.now() - lastUnfinalizedRefetch < 30_000) {
789
+ break;
790
+ }
791
+ lastUnfinalizedRefetch = Date.now();
792
+
793
+ const context = {
794
+ logger: params.common.logger.child({ action: "refetch_finalized_block" }),
795
+ };
796
+
797
+ const endClock = startClock();
798
+
799
+ const finalizedBlock = await eth_getBlockByNumber(
800
+ rpc,
801
+ ["latest", false],
802
+ context,
803
+ ).then((latest) =>
804
+ eth_getBlockByNumber(
805
+ rpc,
806
+ [
807
+ numberToHex(
808
+ Math.max(
809
+ hexToNumber(latest.number) - params.chain.finalityBlockCount,
810
+ 0,
811
+ ),
812
+ ),
813
+ false,
814
+ ],
815
+ context,
816
+ ),
817
+ );
818
+
819
+ const finalizedBlockNumber = hexToNumber(finalizedBlock.number);
820
+ params.common.logger.debug({
821
+ msg: "Refetched finalized block for backfill cutover",
822
+ chain: params.chain.name,
823
+ chain_id: params.chain.id,
824
+ finalized_block: finalizedBlockNumber,
825
+ duration: endClock(),
826
+ });
827
+
828
+ if (
829
+ hexToNumber(finalizedBlock.number) -
830
+ hexToNumber(params.syncProgress.finalized.number) <=
831
+ params.chain.finalityBlockCount
832
+ ) {
833
+ break;
834
+ }
835
+
836
+ params.syncProgress.finalized = finalizedBlock;
837
+ isCatchup = true;
838
+ }
839
+ }
840
+
841
+ export async function refetchHistoricalEvents(params: {
842
+ common: Common;
843
+ indexingBuild: Pick<IndexingBuild, "eventCallbacks" | "chains">;
844
+ perChainSync: Map<Chain, { childAddresses: ChildAddresses }>;
845
+ events: Event[];
846
+ syncStore: SyncStore;
847
+ }): Promise<Event[]> {
848
+ const events: Event[] = new Array(params.events.length);
849
+
850
+ for (const chain of params.indexingBuild.chains) {
851
+ const { childAddresses } = params.perChainSync.get(chain)!;
852
+
853
+ // Note: All filters are refetched, no matter if they are resolved or not.
854
+ const eventCallbacks =
855
+ params.indexingBuild.eventCallbacks[
856
+ params.indexingBuild.chains.findIndex((c) => c.id === chain.id)
857
+ ]!;
858
+
859
+ const chainEvents = params.events.filter(
860
+ (event) => event.chain.id === chain.id,
861
+ );
862
+
863
+ if (chainEvents.length === 0) continue;
864
+
865
+ const rawEvents = await refetchLocalEvents({
866
+ common: params.common,
867
+ chain,
868
+ childAddresses,
869
+ eventCallbacks,
870
+ events: chainEvents,
871
+ syncStore: params.syncStore,
872
+ });
873
+
874
+ const endClock = startClock();
875
+
876
+ const refetchedEvents = decodeEvents(
877
+ params.common,
878
+ chain,
879
+ eventCallbacks,
880
+ rawEvents,
881
+ );
882
+
883
+ params.common.logger.trace({
884
+ msg: "Decoded events",
885
+ chain: chain.name,
886
+ chain_id: chain.id,
887
+ event_count: events.length,
888
+ duration: endClock(),
889
+ });
890
+
891
+ params.common.metrics.ponder_historical_extract_duration.inc(
892
+ { step: "decode" },
893
+ endClock(),
894
+ );
895
+
896
+ let i = 0;
897
+ let j = 0;
898
+
899
+ while (i < params.events.length && j < refetchedEvents.length) {
900
+ if (params.events[i]?.chain.id === chain.id) {
901
+ events[i] = refetchedEvents[j]!;
902
+ i++;
903
+ j++;
904
+ } else {
905
+ i++;
906
+ }
907
+ }
908
+ }
909
+
910
+ return events;
911
+ }
912
+
913
+ export async function refetchLocalEvents(params: {
914
+ common: Common;
915
+ chain: Chain;
916
+ childAddresses: ChildAddresses;
917
+ eventCallbacks: EventCallback[];
918
+ events: Event[];
919
+ syncStore: SyncStore;
920
+ }): Promise<RawEvent[]> {
921
+ const from = params.events[0]!.checkpoint;
922
+ const to = params.events[params.events.length - 1]!.checkpoint;
923
+
924
+ const fromBlock = Number(decodeCheckpoint(from).blockNumber);
925
+ const toBlock = Number(decodeCheckpoint(to).blockNumber);
926
+ let cursor = fromBlock;
927
+
928
+ let events: RawEvent[] | undefined;
929
+ while (cursor <= toBlock) {
930
+ const queryEndClock = startClock();
931
+
932
+ const {
933
+ blocks,
934
+ logs,
935
+ transactions,
936
+ transactionReceipts,
937
+ traces,
938
+ cursor: queryCursor,
939
+ } = await params.syncStore.getEventData({
940
+ filters: params.eventCallbacks.map(({ filter }) => filter),
941
+ fromBlock: cursor,
942
+ toBlock,
943
+ chainId: params.chain.id,
944
+ limit: params.events.length,
945
+ });
946
+
947
+ const endClock = startClock();
948
+ const rawEvents = buildEvents({
949
+ eventCallbacks: params.eventCallbacks,
950
+ blocks,
951
+ logs,
952
+ transactions,
953
+ transactionReceipts,
954
+ traces,
955
+ childAddresses: params.childAddresses,
956
+ chainId: params.chain.id,
957
+ });
958
+
959
+ params.common.logger.trace({
960
+ msg: "Constructed events from block data",
961
+ chain: params.chain.name,
962
+ chain_id: params.chain.id,
963
+ block_range: JSON.stringify([cursor, queryCursor]),
964
+ event_count: rawEvents.length,
965
+ duration: endClock(),
966
+ });
967
+
968
+ params.common.metrics.ponder_historical_extract_duration.inc(
969
+ { step: "build" },
970
+ endClock(),
971
+ );
972
+
973
+ params.common.logger.debug({
974
+ msg: "Queried backfill JSON-RPC data from database",
975
+ chain: params.chain.name,
976
+ chain_id: params.chain.id,
977
+ block_range: JSON.stringify([cursor, queryCursor]),
978
+ event_count: rawEvents.length,
979
+ duration: queryEndClock(),
980
+ });
981
+
982
+ await new Promise(setImmediate);
983
+
984
+ if (events === undefined) {
985
+ events = rawEvents;
986
+ } else {
987
+ events.push(...rawEvents);
988
+ }
989
+
990
+ cursor = queryCursor + 1;
991
+ }
992
+
993
+ return events!;
994
+ }
995
+
996
+ export async function* getLocalEventGenerator(params: {
997
+ common: Common;
998
+ chain: Chain;
999
+ rpc: Rpc;
1000
+ eventCallbacks: EventCallback[];
1001
+ childAddresses: ChildAddresses;
1002
+ syncProgress: SyncProgress;
1003
+ cachedIntervals: CachedIntervals;
1004
+ from: string;
1005
+ to: string;
1006
+ limit: number;
1007
+ database: Database;
1008
+ isCatchup: boolean;
1009
+ }) {
1010
+ const syncStore = createSyncStore({
1011
+ common: params.common,
1012
+ qb: params.database.syncQB,
1013
+ });
1014
+
1015
+ const fromBlock = Number(decodeCheckpoint(params.from).blockNumber);
1016
+ const toBlock = Number(decodeCheckpoint(params.to).blockNumber);
1017
+ let cursor = fromBlock;
1018
+
1019
+ const localSyncGenerator = getLocalSyncGenerator(params);
1020
+
1021
+ for await (const syncCursor of bufferAsyncGenerator(
1022
+ localSyncGenerator,
1023
+ Number.POSITIVE_INFINITY,
1024
+ )) {
1025
+ while (cursor <= Math.min(syncCursor, toBlock)) {
1026
+ const queryEndClock = startClock();
1027
+
1028
+ const {
1029
+ blocks,
1030
+ logs,
1031
+ transactions,
1032
+ transactionReceipts,
1033
+ traces,
1034
+ cursor: queryCursor,
1035
+ } = await syncStore.getEventData({
1036
+ filters: params.eventCallbacks.map(({ filter }) => filter),
1037
+ fromBlock: cursor,
1038
+ toBlock: Math.min(syncCursor, toBlock),
1039
+ chainId: params.chain.id,
1040
+ limit: params.limit,
1041
+ });
1042
+
1043
+ const endClock = startClock();
1044
+ const events = buildEvents({
1045
+ eventCallbacks: params.eventCallbacks,
1046
+ blocks,
1047
+ logs,
1048
+ transactions,
1049
+ transactionReceipts,
1050
+ traces,
1051
+ childAddresses: params.childAddresses,
1052
+ chainId: params.chain.id,
1053
+ });
1054
+
1055
+ params.common.logger.trace({
1056
+ msg: "Constructed events from block data",
1057
+ chain: params.chain.name,
1058
+ chain_id: params.chain.id,
1059
+ block_range: JSON.stringify([cursor, queryCursor]),
1060
+ event_count: events.length,
1061
+ duration: endClock(),
1062
+ });
1063
+
1064
+ params.common.metrics.ponder_historical_extract_duration.inc(
1065
+ { step: "build" },
1066
+ endClock(),
1067
+ );
1068
+
1069
+ params.common.logger.debug({
1070
+ msg: "Queried backfill JSON-RPC data from database",
1071
+ chain: params.chain.name,
1072
+ chain_id: params.chain.id,
1073
+ block_range: JSON.stringify([cursor, queryCursor]),
1074
+ event_count: events.length,
1075
+ duration: queryEndClock(),
1076
+ });
1077
+
1078
+ await new Promise(setImmediate);
1079
+
1080
+ const blockRange = [cursor, queryCursor] satisfies [number, number];
1081
+
1082
+ cursor = queryCursor + 1;
1083
+ if (cursor >= toBlock) {
1084
+ yield { events, checkpoint: params.to, blockRange };
1085
+ } else if (blocks.length > 0) {
1086
+ const checkpoint = encodeCheckpoint({
1087
+ ...MAX_CHECKPOINT,
1088
+ blockTimestamp: blocks[blocks.length - 1]!.timestamp,
1089
+ chainId: BigInt(params.chain.id),
1090
+ blockNumber: blocks[blocks.length - 1]!.number,
1091
+ });
1092
+ yield { events, checkpoint, blockRange };
1093
+ }
1094
+ }
1095
+ }
1096
+ }
1097
+
1098
+ export async function* getLocalSyncGenerator(params: {
1099
+ common: Common;
1100
+ chain: Chain;
1101
+ rpc: Rpc;
1102
+ eventCallbacks: EventCallback[];
1103
+ syncProgress: SyncProgress;
1104
+ childAddresses: ChildAddresses;
1105
+ cachedIntervals: CachedIntervals;
1106
+ database: Database;
1107
+ isCatchup: boolean;
1108
+ }) {
1109
+ const backfillEndClock = startClock();
1110
+ const label = { chain: params.chain.name };
1111
+
1112
+ let first = hexToNumber(params.syncProgress.start.number);
1113
+ const last =
1114
+ params.syncProgress.end === undefined
1115
+ ? params.syncProgress.finalized
1116
+ : hexToNumber(params.syncProgress.end.number) >
1117
+ hexToNumber(params.syncProgress.finalized.number)
1118
+ ? params.syncProgress.finalized
1119
+ : params.syncProgress.end;
1120
+
1121
+ // Estimate optimal range (blocks) to sync at a time, eventually to be used to
1122
+ // determine `interval` passed to `historicalSync.sync()`.
1123
+ let estimateRange = 25;
1124
+
1125
+ // Handle two special cases:
1126
+ // 1. `syncProgress.start` > `syncProgress.finalized`
1127
+ // 2. `cached` is defined
1128
+
1129
+ if (
1130
+ hexToNumber(params.syncProgress.start.number) >
1131
+ hexToNumber(params.syncProgress.finalized.number)
1132
+ ) {
1133
+ params.syncProgress.current = params.syncProgress.finalized;
1134
+
1135
+ params.common.logger.info({
1136
+ msg: "Skipped fetching backfill JSON-RPC data (chain only requires live indexing)",
1137
+ chain: params.chain.name,
1138
+ chain_id: params.chain.id,
1139
+ finalized_block: hexToNumber(params.syncProgress.finalized.number),
1140
+ start_block: hexToNumber(params.syncProgress.start.number),
1141
+ });
1142
+
1143
+ params.common.metrics.ponder_sync_block.set(
1144
+ label,
1145
+ hexToNumber(params.syncProgress.current.number),
1146
+ );
1147
+ params.common.metrics.ponder_sync_block_timestamp.set(
1148
+ label,
1149
+ hexToNumber(params.syncProgress.current.timestamp),
1150
+ );
1151
+ params.common.metrics.ponder_historical_total_blocks.set(label, 0);
1152
+ params.common.metrics.ponder_historical_cached_blocks.set(label, 0);
1153
+
1154
+ return;
1155
+ }
1156
+
1157
+ const totalInterval = [
1158
+ hexToNumber(params.syncProgress.start.number),
1159
+ hexToNumber(last!.number),
1160
+ ] satisfies Interval;
1161
+
1162
+ const requiredIntervals = getRequiredIntervals({
1163
+ filters: params.eventCallbacks.map(({ filter }) => filter),
1164
+ interval: totalInterval,
1165
+ cachedIntervals: params.cachedIntervals,
1166
+ });
1167
+
1168
+ const required = intervalSum(requiredIntervals);
1169
+ const total = totalInterval[1] - totalInterval[0] + 1;
1170
+
1171
+ params.common.metrics.ponder_historical_total_blocks.set(label, total);
1172
+ params.common.metrics.ponder_historical_cached_blocks.set(
1173
+ label,
1174
+ total - required,
1175
+ );
1176
+
1177
+ // Handle cache hit
1178
+ if (params.syncProgress.current !== undefined) {
1179
+ params.common.metrics.ponder_sync_block.set(
1180
+ label,
1181
+ hexToNumber(params.syncProgress.current.number),
1182
+ );
1183
+ params.common.metrics.ponder_sync_block_timestamp.set(
1184
+ label,
1185
+ hexToNumber(params.syncProgress.current.timestamp),
1186
+ );
1187
+
1188
+ // `getEvents` can make progress without calling `sync`, so immediately "yield"
1189
+ yield hexToNumber(params.syncProgress.current.number);
1190
+
1191
+ if (
1192
+ hexToNumber(params.syncProgress.current.number) ===
1193
+ hexToNumber(last!.number)
1194
+ ) {
1195
+ if (params.isCatchup === false) {
1196
+ params.common.logger.info({
1197
+ msg: "Skipped fetching backfill JSON-RPC data (cache contains all required data)",
1198
+ chain: params.chain.name,
1199
+ chain_id: params.chain.id,
1200
+ cached_block: hexToNumber(params.syncProgress.current.number),
1201
+ cache_rate: "100%",
1202
+ });
1203
+ }
1204
+ return;
1205
+ } else if (params.isCatchup === false) {
1206
+ params.common.logger.info({
1207
+ msg: "Started fetching backfill JSON-RPC data",
1208
+ chain: params.chain.name,
1209
+ chain_id: params.chain.id,
1210
+ cached_block: hexToNumber(params.syncProgress.current.number),
1211
+ cache_rate: formatPercentage((total - required) / total),
1212
+ });
1213
+ }
1214
+
1215
+ first = hexToNumber(params.syncProgress.current.number) + 1;
1216
+ } else {
1217
+ params.common.logger.info({
1218
+ msg: "Started fetching backfill JSON-RPC data",
1219
+ chain: params.chain.name,
1220
+ chain_id: params.chain.id,
1221
+ cache_rate: "0%",
1222
+ });
1223
+ }
1224
+
1225
+ const historicalSync = params.chain.portal
1226
+ ? createPortalHistoricalSync(params)
1227
+ : createHistoricalSync(params);
1228
+
1229
+ const { callback: intervalCallback, generator: intervalGenerator } =
1230
+ createCallbackGenerator<{
1231
+ interval: Interval;
1232
+ promise: Promise<void>;
1233
+ }>();
1234
+
1235
+ intervalCallback({
1236
+ interval: [
1237
+ first,
1238
+ Math.min(first + estimateRange, hexToNumber(last.number)),
1239
+ ],
1240
+ promise: Promise.resolve(),
1241
+ });
1242
+
1243
+ /**
1244
+ * @returns `true` if any data was inserted into the database.
1245
+ */
1246
+ async function syncInterval({
1247
+ interval,
1248
+ promise,
1249
+ }: { interval: Interval; promise: Promise<void> }): Promise<boolean> {
1250
+ const endClock = startClock();
1251
+
1252
+ const isSyncComplete = interval[1] === hexToNumber(last.number);
1253
+ const {
1254
+ intervals: requiredIntervals,
1255
+ factoryIntervals: requiredFactoryIntervals,
1256
+ } = getRequiredIntervalsWithFilters({
1257
+ interval,
1258
+ filters: params.eventCallbacks.map(({ filter }) => filter),
1259
+ cachedIntervals: params.cachedIntervals,
1260
+ });
1261
+
1262
+ let closestToTipBlock: SyncBlock | undefined;
1263
+ if (requiredIntervals.length > 0 || requiredFactoryIntervals.length > 0) {
1264
+ const pwr = promiseWithResolvers<void>();
1265
+
1266
+ const durationTimer = setTimeout(
1267
+ () => {
1268
+ params.common.logger.warn({
1269
+ msg: "Fetching backfill JSON-RPC data is taking longer than expected",
1270
+ chain: params.chain.name,
1271
+ chain_id: params.chain.id,
1272
+ block_range: JSON.stringify(interval),
1273
+ duration: endClock(),
1274
+ });
1275
+ },
1276
+ params.common.options.command === "dev" ? 10_000 : 50_000,
1277
+ );
1278
+
1279
+ closestToTipBlock = await params.database.syncQB
1280
+ .transaction(async (tx) => {
1281
+ const syncStore = createSyncStore({ common: params.common, qb: tx });
1282
+ const logs = await historicalSync.syncBlockRangeData({
1283
+ interval,
1284
+ requiredIntervals,
1285
+ requiredFactoryIntervals,
1286
+ syncStore,
1287
+ });
1288
+
1289
+ // Wait for the previous interval to complete `syncBlockData`.
1290
+ await promise;
1291
+
1292
+ if (isSyncComplete === false) {
1293
+ // Queue the next interval
1294
+ intervalCallback({
1295
+ interval: [
1296
+ Math.min(interval[1] + 1, hexToNumber(last.number)),
1297
+ Math.min(
1298
+ interval[1] + 1 + estimateRange,
1299
+ hexToNumber(last.number),
1300
+ ),
1301
+ ],
1302
+ promise: pwr.promise,
1303
+ });
1304
+ }
1305
+
1306
+ const closestToTipBlock = await historicalSync.syncBlockData({
1307
+ interval,
1308
+ requiredIntervals,
1309
+ logs,
1310
+ syncStore,
1311
+ });
1312
+ if (params.chain.disableCache === false) {
1313
+ await syncStore.insertIntervals({
1314
+ intervals: requiredIntervals,
1315
+ factoryIntervals: requiredFactoryIntervals,
1316
+ chainId: params.chain.id,
1317
+ });
1318
+ }
1319
+
1320
+ return closestToTipBlock;
1321
+ })
1322
+ .catch((error) => {
1323
+ if (error instanceof ShutdownError) {
1324
+ throw error;
1325
+ }
1326
+
1327
+ params.common.logger.warn({
1328
+ msg: "Failed to fetch backfill JSON-RPC data",
1329
+ chain: params.chain.name,
1330
+ chain_id: params.chain.id,
1331
+ block_range: JSON.stringify(interval),
1332
+ duration: endClock(),
1333
+ error,
1334
+ });
1335
+ throw error;
1336
+ });
1337
+
1338
+ clearTimeout(durationTimer);
1339
+
1340
+ const duration = endClock();
1341
+
1342
+ // Use the duration and interval of the last call to `sync` to update estimate
1343
+ estimateRange = estimate({
1344
+ from: interval[0],
1345
+ to: interval[1],
1346
+ target: params.common.options.command === "dev" ? 2_000 : 10_000,
1347
+ result: duration,
1348
+ min: 25,
1349
+ max: 100_000,
1350
+ prev: estimateRange,
1351
+ maxIncrease: 1.5,
1352
+ });
1353
+
1354
+ params.common.logger.trace({
1355
+ msg: "Updated block range estimate for fetching backfill JSON-RPC data",
1356
+ chain: params.chain.name,
1357
+ chain_id: params.chain.id,
1358
+ range: estimateRange,
1359
+ });
1360
+
1361
+ // Resolve promise so the next interval can continue.
1362
+ pwr.resolve();
1363
+ } else {
1364
+ // Wait for the previous interval to complete `syncBlockData`.
1365
+ await promise;
1366
+
1367
+ if (isSyncComplete === false) {
1368
+ // Queue the next interval
1369
+ intervalCallback({
1370
+ interval: [
1371
+ Math.min(interval[1] + 1, hexToNumber(last.number)),
1372
+ Math.min(interval[1] + 1 + estimateRange, hexToNumber(last.number)),
1373
+ ],
1374
+ promise: Promise.resolve(),
1375
+ });
1376
+ }
1377
+ }
1378
+
1379
+ if (interval[1] === hexToNumber(last.number)) {
1380
+ params.syncProgress.current = last;
1381
+ }
1382
+
1383
+ if (closestToTipBlock) {
1384
+ params.common.metrics.ponder_sync_block.set(
1385
+ label,
1386
+ hexToNumber(closestToTipBlock.number),
1387
+ );
1388
+ params.common.metrics.ponder_sync_block_timestamp.set(
1389
+ label,
1390
+ hexToNumber(closestToTipBlock.timestamp),
1391
+ );
1392
+ } else {
1393
+ params.common.metrics.ponder_sync_block.set(label, interval[1]);
1394
+ }
1395
+
1396
+ params.common.metrics.ponder_historical_completed_blocks.inc(
1397
+ label,
1398
+ interval[1] - interval[0] + 1,
1399
+ );
1400
+
1401
+ return requiredIntervals.length > 0;
1402
+ }
1403
+
1404
+ const { callback, generator } =
1405
+ createCallbackGenerator<IteratorResult<number>>();
1406
+
1407
+ (async () => {
1408
+ for await (const { interval, promise } of intervalGenerator) {
1409
+ // Note: this relies on the invariant that `syncInterval`
1410
+ // will always resolve promises in the order it was called.
1411
+ syncInterval({ interval, promise }).then((didInsertData) => {
1412
+ const isDone = interval[1] === hexToNumber(last.number);
1413
+ if (didInsertData || isDone) {
1414
+ callback({ value: interval[1], done: false });
1415
+ }
1416
+
1417
+ if (isDone) {
1418
+ callback({ value: undefined, done: true });
1419
+ }
1420
+ });
1421
+ }
1422
+ })();
1423
+
1424
+ for await (const result of generator) {
1425
+ if (result.done) break;
1426
+ yield result.value;
1427
+ }
1428
+
1429
+ params.common.logger.info({
1430
+ msg: "Finished fetching backfill JSON-RPC data",
1431
+ chain: params.chain.name,
1432
+ chain_id: params.chain.id,
1433
+ duration: backfillEndClock(),
1434
+ });
1435
+ }
1436
+
1437
+ /**
1438
+ * Merges multiple event generators into a single generator while preserving
1439
+ * the order of events.
1440
+ *
1441
+ * @param generators - Generators to merge.
1442
+ * @returns A single generator that yields events from all generators.
1443
+ */
1444
+ export async function* mergeAsyncGeneratorsWithEventOrder(
1445
+ generators: AsyncGenerator<{
1446
+ events: Event[];
1447
+ checkpoint: string;
1448
+ blockRange: [number, number];
1449
+ }>[],
1450
+ ): AsyncGenerator<
1451
+ {
1452
+ chainId: number;
1453
+ events: Event[];
1454
+ checkpoint: string;
1455
+ blockRange: [number, number];
1456
+ }[]
1457
+ > {
1458
+ const results = await Promise.all(generators.map((gen) => gen.next()));
1459
+
1460
+ while (results.some((res) => res.done !== true)) {
1461
+ const supremum = min(
1462
+ ...results.map((res) => (res.done ? undefined : res.value.checkpoint)),
1463
+ );
1464
+
1465
+ const mergedResults: {
1466
+ chainId: number;
1467
+ events: Event[];
1468
+ checkpoint: string;
1469
+ blockRange: [number, number];
1470
+ }[] = [];
1471
+
1472
+ for (const result of results) {
1473
+ if (result.done === false) {
1474
+ const [left, right] = partition(
1475
+ result.value.events,
1476
+ (event) => event.checkpoint <= supremum,
1477
+ );
1478
+
1479
+ const event = left[left.length - 1];
1480
+
1481
+ if (event) {
1482
+ const blockRange = [
1483
+ result.value.blockRange[0],
1484
+ right.length > 0
1485
+ ? Number(decodeCheckpoint(event.checkpoint).blockNumber)
1486
+ : result.value.blockRange[1],
1487
+ ] satisfies [number, number];
1488
+
1489
+ mergedResults.push({
1490
+ events: left,
1491
+ chainId: event.chain.id,
1492
+ checkpoint:
1493
+ right.length > 0 ? event.checkpoint : result.value.checkpoint,
1494
+ blockRange,
1495
+ });
1496
+ }
1497
+
1498
+ result.value.events = right;
1499
+ }
1500
+ }
1501
+
1502
+ const index = results.findIndex(
1503
+ (res) => res.done === false && res.value.checkpoint === supremum,
1504
+ );
1505
+
1506
+ const resultPromise = generators[index]!.next();
1507
+ if (mergedResults.length > 0) {
1508
+ yield mergedResults;
1509
+ }
1510
+ results[index] = await resultPromise;
1511
+ }
1512
+ }