envio 3.0.0-alpha.0 → 3.0.0-alpha.10

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 (136) hide show
  1. package/README.md +2 -2
  2. package/evm.schema.json +53 -57
  3. package/fuel.schema.json +35 -31
  4. package/index.d.ts +446 -1
  5. package/index.js +4 -0
  6. package/package.json +23 -11
  7. package/rescript.json +4 -1
  8. package/src/Batch.res.mjs +1 -1
  9. package/src/Benchmark.res +394 -0
  10. package/src/Benchmark.res.mjs +398 -0
  11. package/src/ChainFetcher.res +526 -0
  12. package/src/ChainFetcher.res.mjs +343 -0
  13. package/src/ChainManager.res +182 -0
  14. package/src/ChainManager.res.mjs +150 -0
  15. package/src/Config.res +367 -27
  16. package/src/Config.res.mjs +338 -28
  17. package/src/{Indexer.res → Ctx.res} +1 -1
  18. package/src/Ecosystem.res +25 -0
  19. package/src/Ecosystem.res.mjs +29 -0
  20. package/src/Env.res +252 -0
  21. package/src/Env.res.mjs +271 -0
  22. package/src/Envio.gen.ts +9 -1
  23. package/src/Envio.res +12 -9
  24. package/src/EventProcessing.res +476 -0
  25. package/src/EventProcessing.res.mjs +341 -0
  26. package/src/EventRegister.res +4 -15
  27. package/src/EventRegister.res.mjs +3 -9
  28. package/src/EventRegister.resi +2 -8
  29. package/src/FetchState.res +54 -29
  30. package/src/FetchState.res.mjs +62 -35
  31. package/src/GlobalState.res +1163 -0
  32. package/src/GlobalState.res.mjs +1196 -0
  33. package/src/GlobalStateManager.res +68 -0
  34. package/src/GlobalStateManager.res.mjs +75 -0
  35. package/src/GlobalStateManager.resi +7 -0
  36. package/src/HandlerLoader.res +89 -0
  37. package/src/HandlerLoader.res.mjs +79 -0
  38. package/src/Internal.gen.ts +3 -14
  39. package/src/Internal.res +45 -13
  40. package/src/LoadLayer.res +444 -0
  41. package/src/LoadLayer.res.mjs +296 -0
  42. package/src/LoadLayer.resi +32 -0
  43. package/src/LogSelection.res +33 -27
  44. package/src/LogSelection.res.mjs +6 -0
  45. package/src/Logging.res +11 -4
  46. package/src/Logging.res.mjs +14 -6
  47. package/src/Main.res +351 -0
  48. package/src/Main.res.mjs +312 -0
  49. package/src/Persistence.res +1 -2
  50. package/src/PgStorage.gen.ts +10 -0
  51. package/src/PgStorage.res +28 -34
  52. package/src/PgStorage.res.d.mts +5 -0
  53. package/src/PgStorage.res.mjs +27 -27
  54. package/src/Prometheus.res +8 -8
  55. package/src/Prometheus.res.mjs +10 -10
  56. package/src/ReorgDetection.res +6 -10
  57. package/src/ReorgDetection.res.mjs +6 -6
  58. package/src/TestIndexer.res +536 -0
  59. package/src/TestIndexer.res.mjs +412 -0
  60. package/src/TestIndexerProxyStorage.res +210 -0
  61. package/src/TestIndexerProxyStorage.res.mjs +157 -0
  62. package/src/Types.ts +1 -1
  63. package/src/UserContext.res +355 -0
  64. package/src/UserContext.res.mjs +236 -0
  65. package/src/Utils.res +28 -0
  66. package/src/Utils.res.mjs +18 -0
  67. package/src/bindings/ClickHouse.res +31 -1
  68. package/src/bindings/ClickHouse.res.mjs +27 -1
  69. package/src/bindings/DateFns.res +71 -0
  70. package/src/bindings/DateFns.res.mjs +22 -0
  71. package/src/bindings/Ethers.res +27 -67
  72. package/src/bindings/Ethers.res.mjs +18 -70
  73. package/src/bindings/EventSource.res +13 -0
  74. package/src/bindings/EventSource.res.mjs +2 -0
  75. package/src/bindings/NodeJs.res +44 -3
  76. package/src/bindings/NodeJs.res.mjs +11 -3
  77. package/src/bindings/Pino.res +21 -7
  78. package/src/bindings/Pino.res.mjs +11 -5
  79. package/src/bindings/Postgres.gen.ts +8 -0
  80. package/src/bindings/Postgres.res +3 -0
  81. package/src/bindings/Postgres.res.d.mts +5 -0
  82. package/src/bindings/RescriptMocha.res +123 -0
  83. package/src/bindings/RescriptMocha.res.mjs +18 -0
  84. package/src/bindings/Vitest.res +134 -0
  85. package/src/bindings/Vitest.res.mjs +9 -0
  86. package/src/bindings/Yargs.res +8 -0
  87. package/src/bindings/Yargs.res.mjs +2 -0
  88. package/src/db/InternalTable.res +2 -0
  89. package/src/db/InternalTable.res.mjs +1 -1
  90. package/src/sources/Evm.res +87 -0
  91. package/src/sources/Evm.res.mjs +105 -0
  92. package/src/sources/EvmChain.res +90 -0
  93. package/src/sources/EvmChain.res.mjs +57 -0
  94. package/src/sources/Fuel.res +19 -34
  95. package/src/sources/Fuel.res.mjs +34 -16
  96. package/src/sources/FuelSDK.res +38 -0
  97. package/src/sources/FuelSDK.res.mjs +29 -0
  98. package/src/sources/HyperFuel.res +2 -2
  99. package/src/sources/HyperFuel.resi +1 -1
  100. package/src/sources/HyperFuelClient.res +2 -2
  101. package/src/sources/HyperFuelSource.res +8 -8
  102. package/src/sources/HyperFuelSource.res.mjs +5 -5
  103. package/src/sources/HyperSyncHeightStream.res +97 -0
  104. package/src/sources/HyperSyncHeightStream.res.mjs +94 -0
  105. package/src/sources/HyperSyncSource.res +64 -172
  106. package/src/sources/HyperSyncSource.res.mjs +73 -155
  107. package/src/sources/Rpc.res +43 -0
  108. package/src/sources/Rpc.res.mjs +31 -0
  109. package/src/sources/RpcSource.res +32 -130
  110. package/src/sources/RpcSource.res.mjs +47 -121
  111. package/src/sources/Source.res +3 -2
  112. package/src/sources/SourceManager.res +183 -108
  113. package/src/sources/SourceManager.res.mjs +162 -99
  114. package/src/sources/SourceManager.resi +4 -5
  115. package/src/sources/Svm.res +59 -0
  116. package/src/sources/Svm.res.mjs +79 -0
  117. package/src/tui/Tui.res +266 -0
  118. package/src/tui/Tui.res.mjs +342 -0
  119. package/src/tui/bindings/Ink.res +376 -0
  120. package/src/tui/bindings/Ink.res.mjs +75 -0
  121. package/src/tui/bindings/Style.res +123 -0
  122. package/src/tui/bindings/Style.res.mjs +2 -0
  123. package/src/tui/components/BufferedProgressBar.res +40 -0
  124. package/src/tui/components/BufferedProgressBar.res.mjs +57 -0
  125. package/src/tui/components/CustomHooks.res +122 -0
  126. package/src/tui/components/CustomHooks.res.mjs +179 -0
  127. package/src/tui/components/Messages.res +41 -0
  128. package/src/tui/components/Messages.res.mjs +75 -0
  129. package/src/tui/components/SyncETA.res +193 -0
  130. package/src/tui/components/SyncETA.res.mjs +269 -0
  131. package/src/tui/components/TuiData.res +46 -0
  132. package/src/tui/components/TuiData.res.mjs +29 -0
  133. package/src/Platform.res +0 -140
  134. package/src/Platform.res.mjs +0 -170
  135. package/src/bindings/Ethers.gen.ts +0 -14
  136. /package/src/{Indexer.res.mjs → Ctx.res.mjs} +0 -0
@@ -0,0 +1,236 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Table from "./db/Table.res.mjs";
4
+ import * as Utils from "./Utils.res.mjs";
5
+ import * as Js_exn from "rescript/lib/es6/js_exn.js";
6
+ import * as Address from "./Address.res.mjs";
7
+ import * as Logging from "./Logging.res.mjs";
8
+ import * as Internal from "./Internal.res.mjs";
9
+ import * as LoadLayer from "./LoadLayer.res.mjs";
10
+ import * as Belt_Option from "rescript/lib/es6/belt_Option.js";
11
+ import * as ErrorHandling from "./ErrorHandling.res.mjs";
12
+ import * as InMemoryStore from "./InMemoryStore.res.mjs";
13
+ import * as InMemoryTable from "./InMemoryTable.res.mjs";
14
+ import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
15
+
16
+ var codegenHelpMessage = "Rerun 'pnpm dev' to update generated code after schema.graphql changes.";
17
+
18
+ var paramsByThis = new WeakMap();
19
+
20
+ var effectContextPrototype = (Object.create(null));
21
+
22
+ Object.defineProperty(effectContextPrototype, "log", {
23
+ get: (function () {
24
+ return Logging.getUserLogger(paramsByThis.get(this).item);
25
+ })
26
+ });
27
+
28
+ var EffectContext = function(params, defaultShouldCache, callEffect) {
29
+ paramsByThis.set(this, params);
30
+ this.effect = callEffect;
31
+ this.cache = defaultShouldCache;
32
+ };
33
+ EffectContext.prototype = effectContextPrototype;
34
+ ;
35
+
36
+ function initEffect(params) {
37
+ var callEffect = function (effect, input) {
38
+ var effectContext = new EffectContext(params, effect.defaultShouldCache, callEffect);
39
+ var effectArgs_cacheKey = Utils.Hash.makeOrThrow(S$RescriptSchema.reverseConvertOrThrow(input, effect.input));
40
+ var effectArgs = {
41
+ input: input,
42
+ context: effectContext,
43
+ cacheKey: effectArgs_cacheKey
44
+ };
45
+ return LoadLayer.loadEffect(params.loadManager, params.persistence, effect, effectArgs, params.inMemoryStore, params.isPreload, params.item);
46
+ };
47
+ return callEffect;
48
+ }
49
+
50
+ var getWhereTraps = {
51
+ get: (function (params, prop) {
52
+ var entityConfig = params.entityConfig;
53
+ if (typeof prop !== "string") {
54
+ return Js_exn.raiseError("Invalid context." + entityConfig.name + ".getWhere access by a non-string property.");
55
+ }
56
+ var field = Table.getFieldByDbName(entityConfig.table, prop);
57
+ if (field === undefined) {
58
+ return Js_exn.raiseError("Invalid context." + entityConfig.name + ".getWhere." + prop + " - the field doesn't exist. " + codegenHelpMessage);
59
+ }
60
+ var fieldValueSchema;
61
+ fieldValueSchema = field.TAG === "Field" ? field._0.fieldSchema : S$RescriptSchema.string;
62
+ return {
63
+ eq: (function (fieldValue) {
64
+ return LoadLayer.loadByField(params.loadManager, params.persistence, "Eq", entityConfig, params.inMemoryStore, prop, fieldValueSchema, params.isPreload, params.item, fieldValue);
65
+ }),
66
+ gt: (function (fieldValue) {
67
+ return LoadLayer.loadByField(params.loadManager, params.persistence, "Gt", entityConfig, params.inMemoryStore, prop, fieldValueSchema, params.isPreload, params.item, fieldValue);
68
+ }),
69
+ lt: (function (fieldValue) {
70
+ return LoadLayer.loadByField(params.loadManager, params.persistence, "Lt", entityConfig, params.inMemoryStore, prop, fieldValueSchema, params.isPreload, params.item, fieldValue);
71
+ })
72
+ };
73
+ })
74
+ };
75
+
76
+ function noopSet(_entity) {
77
+
78
+ }
79
+
80
+ function noopDeleteUnsafe(_entityId) {
81
+
82
+ }
83
+
84
+ var entityTraps = {
85
+ get: (function (params, prop) {
86
+ var set = params.isPreload ? noopSet : (function (entity) {
87
+ InMemoryTable.Entity.set(InMemoryStore.getInMemTable(params.inMemoryStore, params.entityConfig), {
88
+ type: "SET",
89
+ entityId: entity.id,
90
+ entity: entity,
91
+ checkpointId: params.checkpointId
92
+ }, params.shouldSaveHistory, undefined);
93
+ });
94
+ switch (prop) {
95
+ case "deleteUnsafe" :
96
+ if (params.isPreload) {
97
+ return noopDeleteUnsafe;
98
+ } else {
99
+ return function (entityId) {
100
+ InMemoryTable.Entity.set(InMemoryStore.getInMemTable(params.inMemoryStore, params.entityConfig), {
101
+ type: "DELETE",
102
+ entityId: entityId,
103
+ checkpointId: params.checkpointId
104
+ }, params.shouldSaveHistory, undefined);
105
+ };
106
+ }
107
+ case "get" :
108
+ return function (entityId) {
109
+ return LoadLayer.loadById(params.loadManager, params.persistence, params.entityConfig, params.inMemoryStore, params.isPreload, params.item, entityId);
110
+ };
111
+ case "getOrCreate" :
112
+ return function (entity) {
113
+ return LoadLayer.loadById(params.loadManager, params.persistence, params.entityConfig, params.inMemoryStore, params.isPreload, params.item, entity.id).then(function (storageEntity) {
114
+ if (storageEntity !== undefined) {
115
+ return storageEntity;
116
+ } else {
117
+ set(entity);
118
+ return entity;
119
+ }
120
+ });
121
+ };
122
+ case "getOrThrow" :
123
+ return function (entityId, message) {
124
+ return LoadLayer.loadById(params.loadManager, params.persistence, params.entityConfig, params.inMemoryStore, params.isPreload, params.item, entityId).then(function (entity) {
125
+ if (entity !== undefined) {
126
+ return entity;
127
+ } else {
128
+ return Js_exn.raiseError(Belt_Option.getWithDefault(message, "Entity '" + params.entityConfig.name + "' with ID '" + entityId + "' is expected to exist."));
129
+ }
130
+ });
131
+ };
132
+ case "getWhere" :
133
+ return new Proxy(params, getWhereTraps);
134
+ case "set" :
135
+ return set;
136
+ default:
137
+ return Js_exn.raiseError("Invalid context." + params.entityConfig.name + "." + prop + " operation.");
138
+ }
139
+ })
140
+ };
141
+
142
+ var handlerTraps = {
143
+ get: (function (params, prop) {
144
+ if (params.isResolved) {
145
+ ErrorHandling.mkLogAndRaise(Logging.getItemLogger(params.item), undefined, new Error("Impossible to access context." + prop + " after the handler is resolved. Make sure you didn't miss an await in the handler."));
146
+ }
147
+ switch (prop) {
148
+ case "chain" :
149
+ var chainId = Internal.getItemChainId(params.item);
150
+ return params.chains[chainId];
151
+ case "effect" :
152
+ return initEffect(params);
153
+ case "isPreload" :
154
+ return params.isPreload;
155
+ case "log" :
156
+ if (params.isPreload) {
157
+ return Logging.noopLogger;
158
+ } else {
159
+ return Logging.getUserLogger(params.item);
160
+ }
161
+ default:
162
+ var entityConfig = params.config.userEntitiesByName[prop];
163
+ if (entityConfig !== undefined) {
164
+ return new Proxy({
165
+ item: params.item,
166
+ checkpointId: params.checkpointId,
167
+ inMemoryStore: params.inMemoryStore,
168
+ loadManager: params.loadManager,
169
+ persistence: params.persistence,
170
+ isPreload: params.isPreload,
171
+ shouldSaveHistory: params.shouldSaveHistory,
172
+ chains: params.chains,
173
+ config: params.config,
174
+ isResolved: params.isResolved,
175
+ entityConfig: entityConfig
176
+ }, entityTraps);
177
+ } else {
178
+ return Js_exn.raiseError("Invalid context access by '" + prop + "' property. " + codegenHelpMessage);
179
+ }
180
+ }
181
+ })
182
+ };
183
+
184
+ function getHandlerContext(params) {
185
+ return new Proxy(params, handlerTraps);
186
+ }
187
+
188
+ var contractRegisterTraps = {
189
+ get: (function (params, prop) {
190
+ if (params.isResolved) {
191
+ ErrorHandling.mkLogAndRaise(Logging.getItemLogger(params.item), undefined, new Error("Impossible to access context." + prop + " after the contract register is resolved. Make sure you didn't miss an await in the handler."));
192
+ }
193
+ if (prop === "log") {
194
+ return Logging.getUserLogger(params.item);
195
+ }
196
+ var contractName = params.config.addContractNameToContractNameMapping[prop];
197
+ if (contractName !== undefined) {
198
+ return function (contractAddress) {
199
+ var validatedAddress = params.config.ecosystem.name === "evm" ? (
200
+ params.config.lowercaseAddresses ? Address.Evm.fromAddressLowercaseOrThrow(contractAddress) : Address.Evm.fromAddressOrThrow(contractAddress)
201
+ ) : contractAddress;
202
+ params.onRegister(params.item, validatedAddress, contractName);
203
+ };
204
+ } else {
205
+ return Js_exn.raiseError("Invalid context access by '" + prop + "' property. " + codegenHelpMessage);
206
+ }
207
+ })
208
+ };
209
+
210
+ function getContractRegisterContext(params) {
211
+ return new Proxy(params, contractRegisterTraps);
212
+ }
213
+
214
+ function getContractRegisterArgs(params) {
215
+ return {
216
+ event: params.item.event,
217
+ context: new Proxy(params, contractRegisterTraps)
218
+ };
219
+ }
220
+
221
+ export {
222
+ codegenHelpMessage ,
223
+ paramsByThis ,
224
+ effectContextPrototype ,
225
+ initEffect ,
226
+ getWhereTraps ,
227
+ noopSet ,
228
+ noopDeleteUnsafe ,
229
+ entityTraps ,
230
+ handlerTraps ,
231
+ getHandlerContext ,
232
+ contractRegisterTraps ,
233
+ getContractRegisterContext ,
234
+ getContractRegisterArgs ,
235
+ }
236
+ /* paramsByThis Not a pure module */
package/src/Utils.res CHANGED
@@ -32,6 +32,19 @@ module Object = {
32
32
 
33
33
  @val @scope("Object")
34
34
  external defineProperty: ('obj, string, propertyDescriptor<'a>) => 'obj = "defineProperty"
35
+
36
+ // Property descriptor with required value field (no boxing)
37
+ type enumerablePropertyDescriptor<'a> = {
38
+ enumerable: bool,
39
+ value: 'a,
40
+ }
41
+
42
+ @val @scope("Object")
43
+ external definePropertyWithValue: ('obj, string, enumerablePropertyDescriptor<'a>) => 'obj =
44
+ "defineProperty"
45
+
46
+ @val @scope("Object")
47
+ external createNullObject: (@as(json`null`) _, unit) => 'a = "create"
35
48
  }
36
49
 
37
50
  module Error = {
@@ -175,6 +188,15 @@ module Dict = {
175
188
  }
176
189
  `)
177
190
 
191
+ let unsafeDeleteUndefinedFieldsInPlace: 'a => unit = %raw(`(dict) => {
192
+ for (var key in dict) {
193
+ if (dict[key] === undefined) {
194
+ delete dict[key];
195
+ }
196
+ }
197
+ }
198
+ `)
199
+
178
200
  let updateImmutable: (
179
201
  dict<'a>,
180
202
  string,
@@ -472,6 +494,12 @@ module Schema = {
472
494
  ->(magic: S.t<Js.Json.t> => S.t<Js.Date.t>)
473
495
  ->S.preprocess(_ => {serializer: date => date->magic->Js.Date.toISOString})
474
496
 
497
+ // ClickHouse expects timestamps as numbers (milliseconds), not ISO strings
498
+ let clickHouseDate =
499
+ S.json(~validate=false)
500
+ ->(magic: S.t<Js.Json.t> => S.t<Js.Date.t>)
501
+ ->S.preprocess(_ => {serializer: date => date->magic->Js.Date.getTime})
502
+
475
503
  // When trying to serialize data to Json pg type, it will fail with
476
504
  // PostgresError: column "params" is of type json but expression is of type boolean
477
505
  // If there's bool or null on the root level. It works fine as object field values.
package/src/Utils.res.mjs CHANGED
@@ -151,6 +151,14 @@ var deleteInPlace = ((dict, key) => {
151
151
  delete dict[key];
152
152
  });
153
153
 
154
+ var unsafeDeleteUndefinedFieldsInPlace = ((dict) => {
155
+ for (var key in dict) {
156
+ if (dict[key] === undefined) {
157
+ delete dict[key];
158
+ }
159
+ }
160
+ });
161
+
154
162
  var updateImmutable = ((dict, key, value) => ({...dict, [key]: value}));
155
163
 
156
164
  var shallowCopy = ((dict) => ({...dict}));
@@ -172,6 +180,7 @@ var Dict = {
172
180
  size: size,
173
181
  isEmpty: isEmpty,
174
182
  deleteInPlace: deleteInPlace,
183
+ unsafeDeleteUndefinedFieldsInPlace: unsafeDeleteUndefinedFieldsInPlace,
175
184
  updateImmutable: updateImmutable,
176
185
  shallowCopy: shallowCopy,
177
186
  incrementByInt: incrementByInt
@@ -449,6 +458,14 @@ var dbDate = S$RescriptSchema.preprocess(S$RescriptSchema.json(false), (function
449
458
  };
450
459
  }));
451
460
 
461
+ var clickHouseDate = S$RescriptSchema.preprocess(S$RescriptSchema.json(false), (function (param) {
462
+ return {
463
+ s: (function (date) {
464
+ return date.getTime();
465
+ })
466
+ };
467
+ }));
468
+
452
469
  function coerceToJsonPgType(schema) {
453
470
  return S$RescriptSchema.preprocess(schema, (function (s) {
454
471
  var match = s.schema.t;
@@ -485,6 +502,7 @@ var Schema = {
485
502
  getNonOptionalFieldNames: getNonOptionalFieldNames,
486
503
  getCapitalizedFieldNames: getCapitalizedFieldNames,
487
504
  dbDate: dbDate,
505
+ clickHouseDate: clickHouseDate,
488
506
  coerceToJsonPgType: coerceToJsonPgType
489
507
  };
490
508
 
@@ -98,6 +98,36 @@ let getClickHouseFieldType = (
98
98
  isNullable ? `Nullable(${baseType})` : baseType
99
99
  }
100
100
 
101
+ // Creates an entity schema from table definition, using clickHouseDate for Date fields
102
+ let makeClickHouseEntitySchema = (table: Table.table): S.t<Internal.entity> => {
103
+ S.schema(s => {
104
+ let dict = Js.Dict.empty()
105
+ table.fields->Belt.Array.forEach(field => {
106
+ switch field {
107
+ | Field(f) => {
108
+ let fieldName = f->Table.getDbFieldName
109
+ let fieldSchema = switch f.fieldType {
110
+ | Date => {
111
+ let dateSchema = Utils.Schema.clickHouseDate->S.toUnknown
112
+ if f.isNullable {
113
+ S.null(dateSchema)->S.toUnknown
114
+ } else if f.isArray {
115
+ S.array(dateSchema)->S.toUnknown
116
+ } else {
117
+ dateSchema
118
+ }
119
+ }
120
+ | _ => f.fieldSchema
121
+ }
122
+ dict->Js.Dict.set(fieldName, s.matches(fieldSchema))
123
+ }
124
+ | DerivedFrom(_) => () // Skip derived fields
125
+ }
126
+ })
127
+ dict->Utils.magic
128
+ })
129
+ }
130
+
101
131
  let setCheckpointsOrThrow = async (client, ~batch: Batch.t, ~database: string) => {
102
132
  let checkpointsCount = batch.checkpointIds->Array.length
103
133
  if checkpointsCount === 0 {
@@ -154,7 +184,7 @@ let setUpdatesOrThrow = async (
154
184
  )}\``,
155
185
  convertOrThrow: S.compile(
156
186
  S.union([
157
- EntityHistory.makeSetUpdateSchema(entityConfig.schema),
187
+ EntityHistory.makeSetUpdateSchema(makeClickHouseEntitySchema(entityConfig.table)),
158
188
  S.object(s => {
159
189
  s.tag(EntityHistory.changeFieldName, EntityHistory.RowAction.DELETE)
160
190
  Change.Delete({
@@ -76,6 +76,31 @@ function getClickHouseFieldType(fieldType, isNullable, isArray) {
76
76
  }
77
77
  }
78
78
 
79
+ function makeClickHouseEntitySchema(table) {
80
+ return S$RescriptSchema.schema(function (s) {
81
+ var dict = {};
82
+ Belt_Array.forEach(table.fields, (function (field) {
83
+ if (field.TAG !== "Field") {
84
+ return ;
85
+ }
86
+ var f = field._0;
87
+ var fieldName = Table.getDbFieldName(f);
88
+ var match = f.fieldType;
89
+ var fieldSchema;
90
+ if (typeof match !== "object" && match === "Date") {
91
+ var dateSchema = Utils.Schema.clickHouseDate;
92
+ fieldSchema = f.isNullable ? S$RescriptSchema.$$null(dateSchema) : (
93
+ f.isArray ? S$RescriptSchema.array(dateSchema) : dateSchema
94
+ );
95
+ } else {
96
+ fieldSchema = f.fieldSchema;
97
+ }
98
+ dict[fieldName] = s.m(fieldSchema);
99
+ }));
100
+ return dict;
101
+ });
102
+ }
103
+
79
104
  async function setCheckpointsOrThrow(client, batch, database) {
80
105
  var checkpointsCount = batch.checkpointIds.length;
81
106
  if (checkpointsCount === 0) {
@@ -120,7 +145,7 @@ async function setUpdatesOrThrow(client, updates, entityConfig, database) {
120
145
  } else {
121
146
  var cache_tableName = database + ".\`" + EntityHistory.historyTableName(entityConfig.name, entityConfig.index) + "\`";
122
147
  var cache_convertOrThrow = S$RescriptSchema.compile(S$RescriptSchema.union([
123
- EntityHistory.makeSetUpdateSchema(entityConfig.schema),
148
+ EntityHistory.makeSetUpdateSchema(makeClickHouseEntitySchema(entityConfig.table)),
124
149
  S$RescriptSchema.object(function (s) {
125
150
  s.tag(EntityHistory.changeFieldName, "DELETE");
126
151
  return {
@@ -264,6 +289,7 @@ async function resume(client, database, checkpointId) {
264
289
 
265
290
  export {
266
291
  getClickHouseFieldType ,
292
+ makeClickHouseEntitySchema ,
267
293
  setCheckpointsOrThrow ,
268
294
  setUpdatesOrThrow ,
269
295
  makeCreateHistoryTableQuery ,
@@ -0,0 +1,71 @@
1
+ /**
2
+ Formats:
3
+ hh:mm:ss | 00:00:00
4
+ do MMM ''yy | 1st Jan '21
5
+ ha do MMM ''yy | 8PM 1st Jan '21
6
+ ha | 8PM
7
+ iii | Tues
8
+ iii MMM | Tues Jan
9
+ MMM | Jan
10
+ `)
11
+ */
12
+ type dateFormats =
13
+ | @as("HH:mm:ss") HoursMinSec
14
+ | @as("ha") Hour
15
+ | @as("do MMM ''yy") DayMonthYear
16
+ | @as("ha do MMM ''yy") HourDayMonthYear
17
+ | @as("h:mma do MMM ''yy") HourMinDayMonthYear
18
+ | @as("iii") DayName
19
+ | @as("iii MMM") DayNameMonth
20
+ | @as("do MMM") DayMonth
21
+ | @as("MMM") Month
22
+ | @as("h:mma") HourMin
23
+
24
+ @module("date-fns") external format: (Js.Date.t, dateFormats) => string = "format"
25
+
26
+ type formatDistanceToNowOptions = {includeSeconds: bool}
27
+ @module("date-fns")
28
+ external formatDistanceToNow: Js.Date.t => string = "formatDistanceToNow"
29
+
30
+ @module("date-fns")
31
+ external formatDistance: (Js.Date.t, Js.Date.t) => string = "formatDistance"
32
+
33
+ @module("date-fns")
34
+ external formatDistanceWithOptions: (Js.Date.t, Js.Date.t, formatDistanceToNowOptions) => string =
35
+ "formatDistance"
36
+
37
+ @module("date-fns")
38
+ external formatDistanceToNowWithOptions: (Js.Date.t, formatDistanceToNowOptions) => string =
39
+ "formatDistanceToNow"
40
+
41
+ let formatDistanceToNowWithSeconds = (date: Js.Date.t) =>
42
+ date->formatDistanceToNowWithOptions({includeSeconds: true})
43
+
44
+ type durationTimeFormat = {
45
+ years: int,
46
+ months: int,
47
+ weeks: int,
48
+ days: int,
49
+ hours: int,
50
+ minutes: int,
51
+ seconds: int,
52
+ }
53
+
54
+ @module("date-fns")
55
+ external formatRelative: (Js.Date.t, Js.Date.t) => string = "formatRelative"
56
+
57
+ type durationFormatOutput = {format: array<string>}
58
+
59
+ @module("date-fns")
60
+ external formatDuration: (durationTimeFormat, durationFormatOutput) => string = "formatDuration"
61
+
62
+ type interval = {start: Js_date.t, end: Js_date.t}
63
+
64
+ @module("date-fns")
65
+ external intervalToDuration: interval => durationTimeFormat = "intervalToDuration"
66
+
67
+ //helper to convert millis elapsed to duration object
68
+ let durationFromMillis = (millis: int) =>
69
+ intervalToDuration({start: 0->Utils.magic, end: millis->Utils.magic})
70
+
71
+ @module("date-fns") external fromUnixTime: float => Js.Date.t = "fromUnixTime"
@@ -0,0 +1,22 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as DateFns from "date-fns";
4
+
5
+ function formatDistanceToNowWithSeconds(date) {
6
+ return DateFns.formatDistanceToNow(date, {
7
+ includeSeconds: true
8
+ });
9
+ }
10
+
11
+ function durationFromMillis(millis) {
12
+ return DateFns.intervalToDuration({
13
+ start: 0,
14
+ end: millis
15
+ });
16
+ }
17
+
18
+ export {
19
+ formatDistanceToNowWithSeconds ,
20
+ durationFromMillis ,
21
+ }
22
+ /* date-fns Not a pure module */
@@ -1,16 +1,3 @@
1
- type abi = EvmTypes.Abi.t
2
-
3
- let makeAbi = (abi: Js.Json.t): abi => abi->Utils.magic
4
-
5
- @deprecated("Use Address.t instead. The type will be removed in v3")
6
- type ethAddress = Address.t
7
- @deprecated("Use Address.Evm.fromStringOrThrow instead. The function will be removed in v3")
8
- let getAddressFromStringUnsafe = Address.Evm.fromStringOrThrow
9
- @deprecated("Use Address.toString instead. The function will be removed in v3")
10
- let ethAddressToString = Address.toString
11
- @deprecated("Use Address.schema instead. The function will be removed in v3")
12
- let ethAddressSchema = Address.schema
13
-
14
1
  type txHash = string
15
2
 
16
3
  module Constants = {
@@ -18,35 +5,6 @@ module Constants = {
18
5
  @module("ethers") @scope("ethers") external zeroAddress: Address.t = "ZeroAddress"
19
6
  }
20
7
 
21
- module Addresses = {
22
- @genType
23
- let mockAddresses = [
24
- "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
25
- "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
26
- "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC",
27
- "0x90F79bf6EB2c4f870365E785982E1f101E93b906",
28
- "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65",
29
- "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc",
30
- "0x976EA74026E726554dB657fA54763abd0C3a0aa9",
31
- "0x14dC79964da2C08b23698B3D3cc7Ca32193d9955",
32
- "0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f",
33
- "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720",
34
- "0xBcd4042DE499D14e55001CcbB24a551F3b954096",
35
- "0x71bE63f3384f5fb98995898A86B02Fb2426c5788",
36
- "0xFABB0ac9d68B0B445fB7357272Ff202C5651694a",
37
- "0x1CBd3b2770909D4e10f157cABC84C7264073C9Ec",
38
- "0xdF3e18d64BC6A983f673Ab319CCaE4f1a57C7097",
39
- "0xcd3B766CCDd6AE721141F452C550Ca635964ce71",
40
- "0x2546BcD3c84621e976D8185a91A922aE77ECEc30",
41
- "0xbDA5747bFD65F08deb54cb465eB87D40e51B197E",
42
- "0xdD2FD4581271e230360230F9337D5c0430Bf44C0",
43
- "0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199",
44
- ]->Belt.Array.map(getAddressFromStringUnsafe)
45
- @genType
46
- let defaultAddress =
47
- mockAddresses[0]
48
- }
49
-
50
8
  module Filter = {
51
9
  type t
52
10
  }
@@ -144,41 +102,43 @@ module JsonRpcProvider = {
144
102
  @send
145
103
  external getLogs: (t, ~filter: Filter.t) => promise<array<log>> = "getLogs"
146
104
 
147
- @send
148
- external getTransaction: (t, ~transactionHash: string) => promise<transaction> = "getTransaction"
149
-
150
105
  let makeGetTransactionFields = (~getTransactionByHash, ~lowercaseAddresses: bool) => async (
151
106
  log: log,
152
- ): promise<unknown> => {
153
- let transaction = await getTransactionByHash(log.transactionHash)
107
+ ): promise<Internal.evmTransactionFields> => {
108
+ let transaction: Internal.evmTransactionFields = await getTransactionByHash(log.transactionHash)
154
109
  // Mutating should be fine, since the transaction isn't used anywhere else outside the function
155
110
  let fields: {..} = transaction->Obj.magic
156
111
 
157
- // Make it compatible with HyperSync transaction fields
112
+ // RPC may return null for transactionIndex on pending transactions
158
113
  fields["transactionIndex"] = log.transactionIndex
159
- fields["input"] = fields["data"]
160
114
 
161
115
  // NOTE: this is wasteful if these fields are not selected in the users config.
162
116
  // There might be a better way to do this in the `makeThrowingGetEventTransaction` function rather based on the schema.
163
117
  // However this is not extremely expensive and good enough for now (only on rpc sync also).
164
- if lowercaseAddresses {
165
- open Js.Nullable
166
- switch fields["from"] {
167
- | Value(from) => fields["from"] = from->Js.String2.toLowerCase
168
- | Undefined => ()
169
- | Null => ()
170
- }
171
- switch fields["to"] {
172
- | Value(to) => fields["to"] = to->Js.String2.toLowerCase
173
- | Undefined => ()
174
- | Null => ()
175
- }
176
- switch fields["contractAddress"] {
177
- | Value(contractAddress) =>
178
- fields["contractAddress"] = contractAddress->Js.String2.toLowerCase
179
- | Undefined => ()
180
- | Null => ()
181
- }
118
+ open Js.Nullable
119
+ switch fields["from"] {
120
+ | Value(from) =>
121
+ fields["from"] = lowercaseAddresses
122
+ ? from->Js.String2.toLowerCase->Address.unsafeFromString
123
+ : from->Address.Evm.fromStringOrThrow
124
+ | Undefined => ()
125
+ | Null => ()
126
+ }
127
+ switch fields["to"] {
128
+ | Value(to) =>
129
+ fields["to"] = lowercaseAddresses
130
+ ? to->Js.String2.toLowerCase->Address.unsafeFromString
131
+ : to->Address.Evm.fromStringOrThrow
132
+ | Undefined => ()
133
+ | Null => ()
134
+ }
135
+ switch fields["contractAddress"] {
136
+ | Value(contractAddress) =>
137
+ fields["contractAddress"] = lowercaseAddresses
138
+ ? contractAddress->Js.String2.toLowerCase->Address.unsafeFromString
139
+ : contractAddress->Address.Evm.fromStringOrThrow
140
+ | Undefined => ()
141
+ | Null => ()
182
142
  }
183
143
 
184
144
  fields->Obj.magic