envio 3.0.2 → 3.1.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/README.md +0 -1
  2. package/evm.schema.json +15 -8
  3. package/fuel.schema.json +19 -12
  4. package/index.d.ts +0 -2
  5. package/package.json +6 -7
  6. package/rescript.json +1 -1
  7. package/src/Batch.res +4 -214
  8. package/src/Batch.res.mjs +6 -165
  9. package/src/ChainFetcher.res +12 -28
  10. package/src/ChainFetcher.res.mjs +8 -17
  11. package/src/ChainManager.res +10 -9
  12. package/src/ChainManager.res.mjs +6 -10
  13. package/src/Config.res +9 -25
  14. package/src/Config.res.mjs +17 -27
  15. package/src/Core.res +7 -0
  16. package/src/Ctx.res +1 -0
  17. package/src/Env.res +0 -8
  18. package/src/Env.res.mjs +0 -6
  19. package/src/EventConfigBuilder.res +13 -123
  20. package/src/EventConfigBuilder.res.mjs +6 -73
  21. package/src/EventProcessing.res +5 -29
  22. package/src/EventProcessing.res.mjs +11 -20
  23. package/src/EventUtils.res +0 -27
  24. package/src/EventUtils.res.mjs +0 -24
  25. package/src/FetchState.res +2 -15
  26. package/src/FetchState.res.mjs +3 -18
  27. package/src/GlobalState.res +26 -39
  28. package/src/GlobalState.res.mjs +12 -40
  29. package/src/HandlerLoader.res +6 -5
  30. package/src/HandlerLoader.res.mjs +27 -9
  31. package/src/HandlerRegister.res +1 -12
  32. package/src/HandlerRegister.res.mjs +1 -6
  33. package/src/HandlerRegister.resi +1 -1
  34. package/src/Hasura.res +96 -32
  35. package/src/Hasura.res.mjs +93 -38
  36. package/src/InMemoryStore.res +205 -45
  37. package/src/InMemoryStore.res.mjs +157 -40
  38. package/src/InMemoryTable.res +165 -249
  39. package/src/InMemoryTable.res.mjs +156 -227
  40. package/src/Internal.res +10 -34
  41. package/src/Internal.res.mjs +9 -3
  42. package/src/LoadLayer.res +5 -5
  43. package/src/LoadLayer.res.mjs +5 -5
  44. package/src/LogSelection.res +15 -19
  45. package/src/LogSelection.res.mjs +5 -6
  46. package/src/Main.res +4 -6
  47. package/src/Main.res.mjs +26 -15
  48. package/src/Persistence.res +7 -132
  49. package/src/Persistence.res.mjs +1 -102
  50. package/src/PgStorage.res +57 -40
  51. package/src/PgStorage.res.mjs +60 -34
  52. package/src/ReorgDetection.res +35 -58
  53. package/src/ReorgDetection.res.mjs +21 -29
  54. package/src/SimulateItems.res.mjs +21 -3
  55. package/src/Sink.res +2 -2
  56. package/src/Sink.res.mjs +1 -1
  57. package/src/TableIndices.res +9 -2
  58. package/src/TableIndices.res.mjs +7 -1
  59. package/src/TestIndexer.res +53 -60
  60. package/src/TestIndexer.res.mjs +77 -63
  61. package/src/TestIndexerProxyStorage.res +4 -14
  62. package/src/TestIndexerProxyStorage.res.mjs +1 -5
  63. package/src/UserContext.res +2 -4
  64. package/src/UserContext.res.mjs +4 -5
  65. package/src/Utils.res +0 -2
  66. package/src/Utils.res.mjs +0 -3
  67. package/src/bindings/ClickHouse.res +45 -38
  68. package/src/bindings/ClickHouse.res.mjs +16 -17
  69. package/src/bindings/Vitest.res +3 -0
  70. package/src/db/InternalTable.res +59 -18
  71. package/src/db/InternalTable.res.mjs +82 -51
  72. package/src/db/Table.res +9 -2
  73. package/src/db/Table.res.mjs +10 -7
  74. package/src/sources/EnvioApiClient.res +15 -0
  75. package/src/sources/EnvioApiClient.res.mjs +24 -0
  76. package/src/sources/EvmChain.res +32 -10
  77. package/src/sources/EvmChain.res.mjs +31 -5
  78. package/src/sources/HyperFuelSource.res +15 -58
  79. package/src/sources/HyperFuelSource.res.mjs +20 -39
  80. package/src/sources/HyperSync.res +54 -100
  81. package/src/sources/HyperSync.res.mjs +67 -96
  82. package/src/sources/HyperSync.resi +4 -22
  83. package/src/sources/HyperSyncClient.res +70 -247
  84. package/src/sources/HyperSyncClient.res.mjs +47 -46
  85. package/src/sources/HyperSyncSource.res +94 -166
  86. package/src/sources/HyperSyncSource.res.mjs +100 -127
  87. package/src/sources/RpcSource.res +43 -22
  88. package/src/sources/RpcSource.res.mjs +50 -35
  89. package/src/sources/SimulateSource.res +1 -7
  90. package/src/sources/SimulateSource.res.mjs +1 -7
  91. package/src/sources/Source.res +10 -1
  92. package/src/sources/Source.res.mjs +3 -0
  93. package/src/sources/SourceManager.res +177 -8
  94. package/src/sources/SourceManager.res.mjs +141 -3
  95. package/src/sources/SourceManager.resi +19 -0
  96. package/src/tui/Tui.res +44 -6
  97. package/src/tui/Tui.res.mjs +56 -8
  98. package/src/tui/components/TuiData.res +3 -0
  99. package/svm.schema.json +11 -4
  100. package/src/sources/HyperSyncJsonApi.res +0 -390
  101. package/src/sources/HyperSyncJsonApi.res.mjs +0 -237
@@ -1,8 +1,7 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
3
  import * as Utils from "./Utils.res.mjs";
4
- import * as Lodash from "./bindings/Lodash.res.mjs";
5
- import * as Belt_Array from "@rescript/runtime/lib/es6/Belt_Array.js";
4
+ import * as Internal from "./Internal.res.mjs";
6
5
  import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
7
6
  import * as TableIndices from "./TableIndices.res.mjs";
8
7
  import * as ErrorHandling from "./ErrorHandling.res.mjs";
@@ -11,44 +10,6 @@ import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
11
10
  import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
12
11
  import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
13
12
 
14
- function make(hash) {
15
- return {
16
- dict: {},
17
- hash: hash
18
- };
19
- }
20
-
21
- function set(self, key, value) {
22
- self.dict[self.hash(key)] = value;
23
- }
24
-
25
- function setByHash(self, hash, value) {
26
- self.dict[hash] = value;
27
- }
28
-
29
- function hasByHash(self, hash) {
30
- return Utils.Dict.has(self.dict, hash);
31
- }
32
-
33
- function getUnsafeByHash(self, hash) {
34
- return self.dict[hash];
35
- }
36
-
37
- function get(self, key) {
38
- return self.dict[self.hash(key)];
39
- }
40
-
41
- function values(self) {
42
- return Object.values(self.dict);
43
- }
44
-
45
- function clone(self) {
46
- return {
47
- dict: Lodash.cloneDeep(self.dict),
48
- hash: self.hash
49
- };
50
- }
51
-
52
13
  let UnexpectedIdNotDefinedOnEntity = /* @__PURE__ */Primitive_exceptions.create("InMemoryTable.Entity.UnexpectedIdNotDefinedOnEntity");
53
14
 
54
15
  function getEntityIdUnsafe(entity) {
@@ -62,171 +23,195 @@ function getEntityIdUnsafe(entity) {
62
23
  }
63
24
  }
64
25
 
26
+ function getOrCreateEntityIndices(self, entityId) {
27
+ let s = self.indicesByEntityId[entityId];
28
+ if (s !== undefined) {
29
+ return Primitive_option.valFromOption(s);
30
+ }
31
+ let s$1 = new Set();
32
+ self.indicesByEntityId[entityId] = s$1;
33
+ return s$1;
34
+ }
35
+
65
36
  function makeIndicesSerializedToValue(index, relatedEntityIdsOpt) {
66
37
  let relatedEntityIds = relatedEntityIdsOpt !== undefined ? Primitive_option.valFromOption(relatedEntityIdsOpt) : new Set();
67
- let empty_dict = {};
68
- let empty_hash = TableIndices.Index.toString;
69
- let empty = {
70
- dict: empty_dict,
71
- hash: empty_hash
72
- };
73
- set(empty, index, [
38
+ let empty = {};
39
+ empty[TableIndices.Index.toString(index)] = [
74
40
  index,
75
41
  relatedEntityIds
76
- ]);
42
+ ];
77
43
  return empty;
78
44
  }
79
45
 
80
- function make$1() {
46
+ function make() {
81
47
  return {
82
- table: {
83
- dict: {},
84
- hash: str => str
85
- },
86
- fieldNameIndices: {
87
- dict: {},
88
- hash: TableIndices.Index.getFieldName
89
- }
48
+ latestEntityChangeById: {},
49
+ changesCount: 0,
50
+ prevEntityChanges: [],
51
+ indicesByEntityId: {},
52
+ fieldNameIndices: {}
90
53
  };
91
54
  }
92
55
 
93
- function updateIndices(self, entity, entityIndices) {
94
- entityIndices.forEach(index => {
95
- let fieldName = TableIndices.Index.getFieldName(index);
96
- let fieldValue = entity[fieldName];
97
- if (!TableIndices.Index.evaluate(index, fieldName, fieldValue)) {
98
- entityIndices.delete(index);
56
+ function resetButKeepLatestChanges(self) {
57
+ let init = {
58
+ latestEntityChangeById: {},
59
+ changesCount: 0,
60
+ prevEntityChanges: [],
61
+ indicesByEntityId: {},
62
+ fieldNameIndices: {}
63
+ };
64
+ return {
65
+ latestEntityChangeById: self.latestEntityChangeById,
66
+ changesCount: self.changesCount,
67
+ prevEntityChanges: init.prevEntityChanges,
68
+ indicesByEntityId: init.indicesByEntityId,
69
+ fieldNameIndices: init.fieldNameIndices
70
+ };
71
+ }
72
+
73
+ function resetButKeepLoadedFromDbChanges(self) {
74
+ let latestEntityChangeById = {};
75
+ let keptCount = {
76
+ contents: 0
77
+ };
78
+ Utils.Dict.forEachWithKey(self.latestEntityChangeById, (change, key) => {
79
+ if (change.checkpointId === Internal.loadedFromDbCheckpointId) {
80
+ latestEntityChangeById[key] = change;
81
+ keptCount.contents = keptCount.contents + 1;
99
82
  return;
100
83
  }
101
84
  });
102
- Object.keys(self.fieldNameIndices.dict).forEach(fieldName => {
103
- let indices = self.fieldNameIndices.dict[fieldName];
85
+ let init = {
86
+ latestEntityChangeById: {},
87
+ changesCount: 0,
88
+ prevEntityChanges: [],
89
+ indicesByEntityId: {},
90
+ fieldNameIndices: {}
91
+ };
92
+ return {
93
+ latestEntityChangeById: latestEntityChangeById,
94
+ changesCount: keptCount.contents,
95
+ prevEntityChanges: init.prevEntityChanges,
96
+ indicesByEntityId: init.indicesByEntityId,
97
+ fieldNameIndices: init.fieldNameIndices
98
+ };
99
+ }
100
+
101
+ function updateIndices(self, entity) {
102
+ let entityId = getEntityIdUnsafe(entity);
103
+ let entityIndices = self.indicesByEntityId[entityId];
104
+ if (entityIndices !== undefined) {
105
+ let entityIndices$1 = Primitive_option.valFromOption(entityIndices);
106
+ entityIndices$1.forEach(index => {
107
+ let fieldName = TableIndices.Index.getFieldName(index);
108
+ let fieldValue = entity[fieldName];
109
+ if (!TableIndices.Index.evaluate(index, fieldName, fieldValue)) {
110
+ entityIndices$1.delete(index);
111
+ return;
112
+ }
113
+ });
114
+ }
115
+ Utils.Dict.forEachWithKey(self.fieldNameIndices, (indices, fieldName) => {
104
116
  let fieldValue = entity[fieldName];
105
- Object.values(indices.dict).forEach(param => {
117
+ Utils.Dict.forEach(indices, param => {
106
118
  let relatedEntityIds = param[1];
107
119
  let index = param[0];
108
120
  if (TableIndices.Index.evaluate(index, fieldName, fieldValue)) {
109
- relatedEntityIds.add(getEntityIdUnsafe(entity));
110
- entityIndices.add(index);
121
+ relatedEntityIds.add(entityId);
122
+ getOrCreateEntityIndices(self, entityId).add(index);
111
123
  } else {
112
- relatedEntityIds.delete(getEntityIdUnsafe(entity));
124
+ relatedEntityIds.delete(entityId);
113
125
  }
114
126
  });
115
127
  });
116
128
  }
117
129
 
118
- function deleteEntityFromIndices(self, entityId, entityIndices) {
119
- entityIndices.forEach(index => {
120
- let match = Stdlib_Option.flatMap(get(self.fieldNameIndices, index), __x => get(__x, index));
130
+ function deleteEntityFromIndices(self, entityId) {
131
+ let entityIndices = self.indicesByEntityId[entityId];
132
+ if (entityIndices === undefined) {
133
+ return;
134
+ }
135
+ let entityIndices$1 = Primitive_option.valFromOption(entityIndices);
136
+ entityIndices$1.forEach(index => {
137
+ let match = Stdlib_Option.flatMap(self.fieldNameIndices[TableIndices.Index.getFieldName(index)], indices => indices[TableIndices.Index.toString(index)]);
121
138
  if (match !== undefined) {
122
139
  match[1].delete(entityId);
123
140
  }
124
- entityIndices.delete(index);
141
+ entityIndices$1.delete(index);
125
142
  });
126
143
  }
127
144
 
128
- function initValue(inMemTable, key, entity, allowOverWriteEntityOpt) {
129
- let allowOverWriteEntity = allowOverWriteEntityOpt !== undefined ? allowOverWriteEntityOpt : false;
130
- let shouldWriteEntity = allowOverWriteEntity || Stdlib_Option.isNone(inMemTable.table.dict[inMemTable.table.hash(key)]);
131
- if (!shouldWriteEntity) {
132
- return;
133
- }
134
- let entityIndices = new Set();
135
- if (entity !== undefined) {
136
- updateIndices(inMemTable, Primitive_option.valFromOption(entity), entityIndices);
137
- }
138
- inMemTable.table.dict[inMemTable.table.hash(key)] = {
139
- latest: entity,
140
- status: "Loaded",
141
- entityIndices: entityIndices
142
- };
143
- }
144
-
145
- function set$1(inMemTable, change, shouldSaveHistory, containsRollbackDiffChangeOpt) {
146
- let containsRollbackDiffChange = containsRollbackDiffChangeOpt !== undefined ? containsRollbackDiffChangeOpt : false;
147
- let latest;
148
- latest = change.type === "SET" ? Primitive_option.some(change.entity) : undefined;
149
- let match = get(inMemTable.table, change.entityId);
150
- let updatedEntityRecord;
151
- if (match !== undefined) {
152
- let previous_values = match.status;
153
- if (previous_values === "Loaded") {
154
- updatedEntityRecord = {
155
- latest: latest,
156
- status: {
157
- latestChange: change,
158
- history: shouldSaveHistory ? [change] : Utils.$$Array.immutableEmpty,
159
- containsRollbackDiffChange: containsRollbackDiffChange
160
- },
161
- entityIndices: match.entityIndices
162
- };
163
- } else {
164
- let newStatus = {
165
- latestChange: change,
166
- history: shouldSaveHistory ? (
167
- previous_values.latestChange.checkpointId === change.checkpointId ? Utils.$$Array.setIndexImmutable(previous_values.history, previous_values.history.length - 1 | 0, change) : Belt_Array.concatMany([
168
- previous_values.history,
169
- [change]
170
- ])
171
- ) : previous_values.history,
172
- containsRollbackDiffChange: previous_values.containsRollbackDiffChange
173
- };
174
- updatedEntityRecord = {
175
- latest: latest,
176
- status: newStatus,
177
- entityIndices: match.entityIndices
178
- };
145
+ function set(inMemTable, committedCheckpointId, change) {
146
+ let entityId = change.entityId;
147
+ let prev = inMemTable.latestEntityChangeById[entityId];
148
+ if (prev !== undefined) {
149
+ let prevCheckpointId = prev.checkpointId;
150
+ if (prevCheckpointId > committedCheckpointId && prevCheckpointId < change.checkpointId) {
151
+ inMemTable.prevEntityChanges.push(prev);
152
+ inMemTable.changesCount = inMemTable.changesCount + 1;
179
153
  }
180
154
  } else {
181
- updatedEntityRecord = {
182
- latest: latest,
183
- status: {
184
- latestChange: change,
185
- history: shouldSaveHistory ? [change] : Utils.$$Array.immutableEmpty,
186
- containsRollbackDiffChange: containsRollbackDiffChange
187
- },
188
- entityIndices: new Set()
189
- };
155
+ inMemTable.changesCount = inMemTable.changesCount + 1;
190
156
  }
191
157
  if (change.type === "SET") {
192
- updateIndices(inMemTable, change.entity, updatedEntityRecord.entityIndices);
158
+ updateIndices(inMemTable, change.entity);
193
159
  } else {
194
- deleteEntityFromIndices(inMemTable, change.entityId, updatedEntityRecord.entityIndices);
160
+ deleteEntityFromIndices(inMemTable, change.entityId);
195
161
  }
196
- set(inMemTable.table, change.entityId, updatedEntityRecord);
162
+ inMemTable.latestEntityChangeById[entityId] = change;
197
163
  }
198
164
 
199
- function rowToEntity(row) {
200
- return row.latest;
165
+ function initValue(inMemTable, committedCheckpointId, key, entity) {
166
+ if (!Stdlib_Option.isNone(inMemTable.latestEntityChangeById[key])) {
167
+ return;
168
+ }
169
+ let change = entity !== undefined ? ({
170
+ type: "SET",
171
+ entityId: key,
172
+ entity: entity,
173
+ checkpointId: Internal.loadedFromDbCheckpointId
174
+ }) : ({
175
+ type: "DELETE",
176
+ entityId: key,
177
+ checkpointId: Internal.loadedFromDbCheckpointId
178
+ });
179
+ set(inMemTable, committedCheckpointId, change);
180
+ }
181
+
182
+ function mapChangeToEntity(change) {
183
+ if (change.type === "SET") {
184
+ return change.entity;
185
+ }
201
186
  }
202
187
 
203
188
  function getUnsafe(inMemTable) {
204
- return key => inMemTable.table.dict[key].latest;
189
+ return key => mapChangeToEntity(inMemTable.latestEntityChangeById[key]);
205
190
  }
206
191
 
207
192
  function hasIndex(inMemTable, fieldName, operator) {
208
193
  return fieldValueHash => {
209
- let indicesSerializedToValue = inMemTable.fieldNameIndices.dict[fieldName];
194
+ let indicesSerializedToValue = inMemTable.fieldNameIndices[fieldName];
210
195
  if (indicesSerializedToValue === undefined) {
211
196
  return false;
212
197
  }
213
- let key = fieldName + `:` + operator + `:` + fieldValueHash;
214
- return indicesSerializedToValue.dict[key] !== undefined;
198
+ let key = TableIndices.Index.toStringByParts(fieldName, operator, fieldValueHash);
199
+ return indicesSerializedToValue[key] !== undefined;
215
200
  };
216
201
  }
217
202
 
218
203
  function getUnsafeOnIndex(inMemTable, fieldName, operator) {
219
204
  let getEntity = getUnsafe(inMemTable);
220
205
  return fieldValueHash => {
221
- let indicesSerializedToValue = inMemTable.fieldNameIndices.dict[fieldName];
206
+ let indicesSerializedToValue = inMemTable.fieldNameIndices[fieldName];
222
207
  if (indicesSerializedToValue === undefined) {
223
208
  return Stdlib_JsError.throwWithMessage(`Unexpected error. Must have an index on field ` + fieldName);
224
209
  }
225
- let key = fieldName + `:` + operator + `:` + fieldValueHash;
226
- let match = indicesSerializedToValue.dict[key];
210
+ let key = TableIndices.Index.toStringByParts(fieldName, operator, fieldValueHash);
211
+ let match = indicesSerializedToValue[key];
227
212
  if (match !== undefined) {
228
213
  return Stdlib_Array.filterMap(Array.from(match[1]), entityId => {
229
- if (hasByHash(inMemTable.table, entityId)) {
214
+ if (entityId in inMemTable.latestEntityChangeById) {
230
215
  return getEntity(entityId);
231
216
  }
232
217
  });
@@ -239,111 +224,55 @@ function getUnsafeOnIndex(inMemTable, fieldName, operator) {
239
224
  function addEmptyIndex(inMemTable, index) {
240
225
  let fieldName = TableIndices.Index.getFieldName(index);
241
226
  let relatedEntityIds = new Set();
242
- Object.values(inMemTable.table.dict).forEach(row => {
243
- let entity = row.latest;
227
+ Utils.Dict.forEach(inMemTable.latestEntityChangeById, change => {
228
+ let entity = mapChangeToEntity(change);
244
229
  if (entity === undefined) {
245
230
  return;
246
231
  }
247
- let entity$1 = Primitive_option.valFromOption(entity);
248
- let fieldValue = entity$1[fieldName];
249
- if (TableIndices.Index.evaluate(index, fieldName, fieldValue)) {
250
- row.entityIndices.add(index);
251
- relatedEntityIds.add(getEntityIdUnsafe(entity$1));
232
+ let fieldValue = entity[fieldName];
233
+ if (!TableIndices.Index.evaluate(index, fieldName, fieldValue)) {
252
234
  return;
253
235
  }
236
+ let entityId = getEntityIdUnsafe(entity);
237
+ getOrCreateEntityIndices(inMemTable, entityId).add(index);
238
+ relatedEntityIds.add(entityId);
254
239
  });
255
- let indicesSerializedToValue = get(inMemTable.fieldNameIndices, index);
256
- if (indicesSerializedToValue === undefined) {
257
- return set(inMemTable.fieldNameIndices, index, makeIndicesSerializedToValue(index, Primitive_option.some(relatedEntityIds)));
258
- }
259
- let match = get(indicesSerializedToValue, index);
260
- if (match !== undefined) {
261
- return;
262
- } else {
263
- return set(indicesSerializedToValue, index, [
264
- index,
265
- relatedEntityIds
266
- ]);
267
- }
268
- }
269
-
270
- function addIdToIndex(inMemTable, index, entityId) {
271
- let indicesSerializedToValue = get(inMemTable.fieldNameIndices, index);
272
- if (indicesSerializedToValue === undefined) {
273
- return set(inMemTable.fieldNameIndices, index, makeIndicesSerializedToValue(index, Primitive_option.some(new Set().add(entityId))));
274
- }
275
- let match = get(indicesSerializedToValue, index);
276
- if (match !== undefined) {
277
- match[1].add(entityId);
278
- return;
279
- } else {
280
- return set(indicesSerializedToValue, index, [
281
- index,
282
- new Set().add(entityId)
283
- ]);
284
- }
285
- }
286
-
287
- function updates(inMemTable) {
288
- return Stdlib_Array.filterMap(Object.values(inMemTable.table.dict), v => {
289
- let update = v.status;
290
- if (update === "Loaded") {
240
+ let indicesSerializedToValue = inMemTable.fieldNameIndices[fieldName];
241
+ if (indicesSerializedToValue !== undefined) {
242
+ let match = indicesSerializedToValue[TableIndices.Index.toString(index)];
243
+ if (match !== undefined) {
291
244
  return;
292
245
  } else {
293
- return update;
294
- }
295
- });
296
- }
297
-
298
- function values$1(inMemTable) {
299
- return Stdlib_Array.filterMap(Object.values(inMemTable.table.dict), rowToEntity);
300
- }
301
-
302
- function clone$1(param) {
303
- let fieldNameIndices = param.fieldNameIndices;
304
- return {
305
- table: clone(param.table),
306
- fieldNameIndices: {
307
- dict: Object.fromEntries(Object.entries(fieldNameIndices.dict).map(param => [
308
- param[0],
309
- clone(param[1])
310
- ])),
311
- hash: fieldNameIndices.hash
246
+ indicesSerializedToValue[TableIndices.Index.toString(index)] = [
247
+ index,
248
+ relatedEntityIds
249
+ ];
250
+ return;
312
251
  }
313
- };
252
+ }
253
+ inMemTable.fieldNameIndices[fieldName] = makeIndicesSerializedToValue(index, Primitive_option.some(relatedEntityIds));
314
254
  }
315
255
 
316
256
  let Entity = {
317
257
  UnexpectedIdNotDefinedOnEntity: UnexpectedIdNotDefinedOnEntity,
318
258
  getEntityIdUnsafe: getEntityIdUnsafe,
259
+ getOrCreateEntityIndices: getOrCreateEntityIndices,
319
260
  makeIndicesSerializedToValue: makeIndicesSerializedToValue,
320
- make: make$1,
261
+ make: make,
262
+ resetButKeepLatestChanges: resetButKeepLatestChanges,
263
+ resetButKeepLoadedFromDbChanges: resetButKeepLoadedFromDbChanges,
321
264
  updateIndices: updateIndices,
322
265
  deleteEntityFromIndices: deleteEntityFromIndices,
266
+ set: set,
323
267
  initValue: initValue,
324
- setRow: set,
325
- set: set$1,
326
- rowToEntity: rowToEntity,
327
- getRow: get,
268
+ mapChangeToEntity: mapChangeToEntity,
328
269
  getUnsafe: getUnsafe,
329
270
  hasIndex: hasIndex,
330
271
  getUnsafeOnIndex: getUnsafeOnIndex,
331
- addEmptyIndex: addEmptyIndex,
332
- addIdToIndex: addIdToIndex,
333
- updates: updates,
334
- values: values$1,
335
- clone: clone$1
272
+ addEmptyIndex: addEmptyIndex
336
273
  };
337
274
 
338
275
  export {
339
- make,
340
- set,
341
- setByHash,
342
- hasByHash,
343
- getUnsafeByHash,
344
- get,
345
- values,
346
- clone,
347
276
  Entity,
348
277
  }
349
278
  /* Utils Not a pure module */
package/src/Internal.res CHANGED
@@ -330,17 +330,11 @@ type genericHandlerWithLoader<'loader, 'handler, 'where> = {
330
330
  // param (or any nested field) is a Solidity struct. `name` is always non-empty —
331
331
  // the CLI fills in `"0"`, `"1"`, ... for anonymous components in mixed-name
332
332
  // tuples — so the runtime can always rebuild a keyed object.
333
- type rec eventParamComponent = {
334
- name: string,
335
- abiType: string,
336
- components?: array<eventParamComponent>,
337
- }
338
-
339
- type eventParam = {
333
+ type rec paramMeta = {
340
334
  name: string,
341
335
  abiType: string,
342
336
  indexed: bool,
343
- components?: array<eventParamComponent>,
337
+ components?: array<paramMeta>,
344
338
  }
345
339
 
346
340
  // This is private so it's not manually constructed internally
@@ -398,15 +392,11 @@ type eventFilters =
398
392
  type evmEventConfig = {
399
393
  ...eventConfig,
400
394
  getEventFiltersOrThrow: ChainMap.Chain.t => eventFilters,
401
- convertHyperSyncEventArgs: HyperSyncClient.Decoder.decodedEvent => eventParams,
402
395
  selectedBlockFields: Utils.Set.t<evmBlockField>,
403
396
  selectedTransactionFields: Utils.Set.t<evmTransactionField>,
404
- // Retained so `HandlerLoader.applyRegistrations` can re-run
405
- // `LogSelection.parseEventFiltersOrThrow` after handler modules register
406
- // with a `where:` filter. Only indexed params are kept — they're all the
407
- // filter parser needs for topic-getter construction + key validation.
408
397
  sighash: string,
409
- indexedParams: array<eventParam>,
398
+ topicCount: int,
399
+ paramsMetadata: array<paramMeta>,
410
400
  }
411
401
 
412
402
  // Shared formula for `eventConfig.dependsOnAddresses`. Kept here so
@@ -520,8 +510,6 @@ let fuelTransferParamsSchema = S.schema(s => {
520
510
  amount: s.matches(Utils.BigInt.schema),
521
511
  })
522
512
 
523
- type multichain = | @as("ordered") Ordered | @as("unordered") Unordered
524
-
525
513
  type entity = private {id: string}
526
514
 
527
515
  // Per-entity storage resolved at parse time against the global storage
@@ -595,6 +583,12 @@ type noOnEventWhere
595
583
 
596
584
  type checkpointId = bigint
597
585
 
586
+ // Assigned to changes loaded from the db, which never become history.
587
+ let loadedFromDbCheckpointId: checkpointId = 0n
588
+
589
+ // Committed checkpoint before any batch is written.
590
+ let initialCheckpointId: checkpointId = 0n
591
+
598
592
  type reorgCheckpoint = {
599
593
  @as("id")
600
594
  checkpointId: bigint,
@@ -605,21 +599,3 @@ type reorgCheckpoint = {
605
599
  @as("block_hash")
606
600
  blockHash: string,
607
601
  }
608
-
609
- type inMemoryStoreEntityUpdate<'entity> = {
610
- latestChange: Change.t<'entity>,
611
- history: array<Change.t<'entity>>,
612
- // In the event of a rollback, some entity updates may have been
613
- // been affected by a rollback diff. If there was no rollback diff
614
- // this will always be false.
615
- // If there was a rollback diff, this will be false in the case of a
616
- // new entity update (where entity affected is not present in the diff) b
617
- // but true if the update is related to an entity that is
618
- // currently present in the diff
619
- containsRollbackDiffChange: bool,
620
- }
621
-
622
- @unboxed
623
- type inMemoryStoreEntityStatus<'entity> =
624
- | Updated(inMemoryStoreEntityUpdate<'entity>)
625
- | Loaded // This means there is no change from the db.
@@ -151,11 +151,15 @@ let effectCacheItemRowsSchema = S$RescriptSchema.array(S$RescriptSchema.schema(s
151
151
 
152
152
  function makeCacheTable(effectName) {
153
153
  return Table.mkTable(cacheTablePrefix + effectName, undefined, [
154
- Table.mkField("id", "String", S$RescriptSchema.string, undefined, undefined, undefined, true, undefined, undefined),
155
- Table.mkField("output", "Json", cacheOutputSchema, undefined, undefined, true, undefined, undefined, undefined)
156
- ]);
154
+ Table.mkField("id", "String", S$RescriptSchema.string, undefined, undefined, undefined, true, undefined, undefined, undefined),
155
+ Table.mkField("output", "Json", cacheOutputSchema, undefined, undefined, true, undefined, undefined, undefined, undefined)
156
+ ], undefined);
157
157
  }
158
158
 
159
+ let loadedFromDbCheckpointId = 0n;
160
+
161
+ let initialCheckpointId = 0n;
162
+
159
163
  export {
160
164
  allEvmBlockFields,
161
165
  evmBlockFieldSchema,
@@ -171,5 +175,7 @@ export {
171
175
  cacheOutputSchema,
172
176
  effectCacheItemRowsSchema,
173
177
  makeCacheTable,
178
+ loadedFromDbCheckpointId,
179
+ initialCheckpointId,
174
180
  }
175
181
  /* evmBlockFieldSchema Not a pure module */
package/src/LoadLayer.res CHANGED
@@ -36,7 +36,7 @@ let loadById = (
36
36
  }
37
37
  idsToLoad->Array.forEach(entityId => {
38
38
  inMemTable->InMemoryTable.Entity.initValue(
39
- ~allowOverWriteEntity=false,
39
+ ~committedCheckpointId=inMemoryStore.committedCheckpointId,
40
40
  ~key=entityId,
41
41
  ~entity=entitiesMap->Utils.Dict.dangerouslyGetNonOption(entityId),
42
42
  )
@@ -56,7 +56,7 @@ let loadById = (
56
56
  ~shouldGroup,
57
57
  ~hasher=LoadManager.noopHasher,
58
58
  ~getUnsafeInMemory=inMemTable->InMemoryTable.Entity.getUnsafe,
59
- ~hasInMemory=hash => inMemTable.table->InMemoryTable.hasByHash(hash),
59
+ ~hasInMemory=hash => inMemTable.latestEntityChangeById->Dict.has(hash),
60
60
  ~input=entityId,
61
61
  )
62
62
  }
@@ -253,7 +253,7 @@ let loadEffect = (
253
253
 
254
254
  if (
255
255
  switch persistence.storageStatus {
256
- | Ready({cache}) => cache->Utils.Dict.has(effectName)
256
+ | Ready({cache}) => cache->Dict.has(effectName)
257
257
  | _ => false
258
258
  }
259
259
  ) {
@@ -335,7 +335,7 @@ let loadEffect = (
335
335
  ~shouldGroup,
336
336
  ~hasher=args => args.cacheKey,
337
337
  ~getUnsafeInMemory=hash => inMemTable.dict->Dict.getUnsafe(hash),
338
- ~hasInMemory=hash => inMemTable.dict->Utils.Dict.has(hash),
338
+ ~hasInMemory=hash => inMemTable.dict->Dict.has(hash),
339
339
  ~input=effectArgs,
340
340
  )
341
341
  }
@@ -397,7 +397,7 @@ let loadByField = (
397
397
 
398
398
  entities->Array.forEach(entity => {
399
399
  inMemTable->InMemoryTable.Entity.initValue(
400
- ~allowOverWriteEntity=false,
400
+ ~committedCheckpointId=inMemoryStore.committedCheckpointId,
401
401
  ~key=entity.id,
402
402
  ~entity=Some(entity),
403
403
  )
@@ -37,10 +37,10 @@ function loadById(loadManager, persistence, entityConfig, inMemoryStore, shouldG
37
37
  let entity = dbEntities[idx];
38
38
  entitiesMap[entity.id] = entity;
39
39
  }
40
- idsToLoad.forEach(entityId => InMemoryTable.Entity.initValue(inMemTable, entityId, entitiesMap[entityId], false));
40
+ idsToLoad.forEach(entityId => InMemoryTable.Entity.initValue(inMemTable, inMemoryStore.committedCheckpointId, entityId, entitiesMap[entityId]));
41
41
  return Prometheus.StorageLoad.endOperation(timerRef, storage.name, key, idsToLoad.length, dbEntities.length);
42
42
  };
43
- return LoadManager.call(loadManager, entityId, key, load, LoadManager.noopHasher, shouldGroup, hash => InMemoryTable.hasByHash(inMemTable.table, hash), InMemoryTable.Entity.getUnsafe(inMemTable));
43
+ return LoadManager.call(loadManager, entityId, key, load, LoadManager.noopHasher, shouldGroup, hash => hash in inMemTable.latestEntityChangeById, InMemoryTable.Entity.getUnsafe(inMemTable));
44
44
  }
45
45
 
46
46
  function callEffect(effect, arg, inMemTable, timerRef, onError) {
@@ -137,7 +137,7 @@ function loadEffect(loadManager, persistence, effect, effectArgs, inMemoryStore,
137
137
  let idsFromCache = new Set();
138
138
  let match = persistence.storageStatus;
139
139
  let tmp;
140
- tmp = typeof match !== "object" || match.TAG === "Initializing" ? false : Utils.Dict.has(match._0.cache, effectName);
140
+ tmp = typeof match !== "object" || match.TAG === "Initializing" ? false : effectName in match._0.cache;
141
141
  if (tmp) {
142
142
  let storage = Persistence.getInitializedStorageOrThrow(persistence);
143
143
  let timerRef = Prometheus.StorageLoad.startOperation(storage.name, key);
@@ -193,7 +193,7 @@ function loadEffect(loadManager, persistence, effect, effectArgs, inMemoryStore,
193
193
  return await executeWithRateLimit(effect, argsToCall, inMemTable, onError, false);
194
194
  }
195
195
  };
196
- return LoadManager.call(loadManager, effectArgs, key, load, args => args.cacheKey, shouldGroup, hash => Utils.Dict.has(inMemTable.dict, hash), hash => inMemTable.dict[hash]);
196
+ return LoadManager.call(loadManager, effectArgs, key, load, args => args.cacheKey, shouldGroup, hash => hash in inMemTable.dict, hash => inMemTable.dict[hash]);
197
197
  }
198
198
 
199
199
  function loadByField(loadManager, persistence, operator, entityConfig, inMemoryStore, fieldName, fieldValueSchema, shouldGroup, item, fieldValue) {
@@ -238,7 +238,7 @@ function loadByField(loadManager, persistence, operator, entityConfig, inMemoryS
238
238
  break;
239
239
  }
240
240
  let entities = await storage.loadByFieldOrThrow(TableIndices.Index.getFieldName(index), fieldValueSchema, index.fieldValue, tmp, entityConfig.table, entityConfig.rowsSchema);
241
- entities.forEach(entity => InMemoryTable.Entity.initValue(inMemTable, entity.id, entity, false));
241
+ entities.forEach(entity => InMemoryTable.Entity.initValue(inMemTable, inMemoryStore.committedCheckpointId, entity.id, entity));
242
242
  size.contents = size.contents + entities.length | 0;
243
243
  return;
244
244
  } catch (raw_exn) {