envio 2.27.5 → 2.28.0-alpha.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.
@@ -141,7 +141,7 @@ let makeHistoryRowSchema: S.t<'entity> => S.t<historyRow<'entity>> = entitySchem
141
141
 
142
142
  type t<'entity> = {
143
143
  table: table,
144
- createInsertFnQuery: string,
144
+ makeInsertFnQuery: (~pgSchema: string) => string,
145
145
  schema: S.t<historyRow<'entity>>,
146
146
  // Used for parsing
147
147
  schemaRows: S.t<array<historyRow<'entity>>>,
@@ -153,7 +153,7 @@ type entityInternal
153
153
  external castInternal: t<'entity> => t<entityInternal> = "%identity"
154
154
  external eval: string => 'a = "eval"
155
155
 
156
- let fromTable = (table: table, ~pgSchema, ~schema: S.t<'entity>): t<'entity> => {
156
+ let fromTable = (table: table, ~schema: S.t<'entity>): t<'entity> => {
157
157
  let entity_history_block_timestamp = "entity_history_block_timestamp"
158
158
  let entity_history_chain_id = "entity_history_chain_id"
159
159
  let entity_history_block_number = "entity_history_block_number"
@@ -227,19 +227,6 @@ let fromTable = (table: table, ~pgSchema, ~schema: S.t<'entity>): t<'entity> =>
227
227
  )
228
228
 
229
229
  let insertFnName = `"insert_${table.tableName}"`
230
- let historyRowArg = "history_row"
231
- let historyTablePath = `"${pgSchema}"."${historyTableName}"`
232
- let originTablePath = `"${pgSchema}"."${originTableName}"`
233
-
234
- let previousHistoryFieldsAreNullStr =
235
- previousChangeFieldNames
236
- ->Belt.Array.map(fieldName => `${historyRowArg}.${fieldName} IS NULL`)
237
- ->Js.Array2.joinWith(" OR ")
238
-
239
- let currentChangeFieldNamesCommaSeparated = currentChangeFieldNames->Js.Array2.joinWith(", ")
240
-
241
- let dataFieldNamesDoubleQuoted = dataFieldNames->Belt.Array.map(fieldName => `"${fieldName}"`)
242
- let dataFieldNamesCommaSeparated = dataFieldNamesDoubleQuoted->Js.Array2.joinWith(", ")
243
230
 
244
231
  let allFieldNamesDoubleQuoted =
245
232
  Belt.Array.concatMany([
@@ -249,60 +236,73 @@ let fromTable = (table: table, ~pgSchema, ~schema: S.t<'entity>): t<'entity> =>
249
236
  [actionFieldName],
250
237
  ])->Belt.Array.map(fieldName => `"${fieldName}"`)
251
238
 
252
- let createInsertFnQuery = {
239
+ let makeInsertFnQuery = (~pgSchema) => {
240
+ let historyRowArg = "history_row"
241
+ let historyTablePath = `"${pgSchema}"."${historyTableName}"`
242
+ let originTablePath = `"${pgSchema}"."${originTableName}"`
243
+
244
+ let previousHistoryFieldsAreNullStr =
245
+ previousChangeFieldNames
246
+ ->Belt.Array.map(fieldName => `${historyRowArg}.${fieldName} IS NULL`)
247
+ ->Js.Array2.joinWith(" OR ")
248
+
249
+ let currentChangeFieldNamesCommaSeparated = currentChangeFieldNames->Js.Array2.joinWith(", ")
250
+
251
+ let dataFieldNamesDoubleQuoted = dataFieldNames->Belt.Array.map(fieldName => `"${fieldName}"`)
252
+ let dataFieldNamesCommaSeparated = dataFieldNamesDoubleQuoted->Js.Array2.joinWith(", ")
253
+
253
254
  `CREATE OR REPLACE FUNCTION ${insertFnName}(${historyRowArg} ${historyTablePath}, should_copy_current_entity BOOLEAN)
254
- RETURNS void AS $$
255
- DECLARE
256
- v_previous_record RECORD;
257
- v_origin_record RECORD;
258
- BEGIN
259
- -- Check if previous values are not provided
260
- IF ${previousHistoryFieldsAreNullStr} THEN
261
- -- Find the most recent record for the same id
262
- SELECT ${currentChangeFieldNamesCommaSeparated} INTO v_previous_record
263
- FROM ${historyTablePath}
264
- WHERE ${id} = ${historyRowArg}.${id}
265
- ORDER BY ${currentChangeFieldNames
255
+ RETURNS void AS $$
256
+ DECLARE
257
+ v_previous_record RECORD;
258
+ v_origin_record RECORD;
259
+ BEGIN
260
+ -- Check if previous values are not provided
261
+ IF ${previousHistoryFieldsAreNullStr} THEN
262
+ -- Find the most recent record for the same id
263
+ SELECT ${currentChangeFieldNamesCommaSeparated} INTO v_previous_record
264
+ FROM ${historyTablePath}
265
+ WHERE ${id} = ${historyRowArg}.${id}
266
+ ORDER BY ${currentChangeFieldNames
266
267
  ->Belt.Array.map(fieldName => fieldName ++ " DESC")
267
268
  ->Js.Array2.joinWith(", ")}
268
- LIMIT 1;
269
+ LIMIT 1;
269
270
 
270
- -- If a previous record exists, use its values
271
- IF FOUND THEN
272
- ${Belt.Array.zip(currentChangeFieldNames, previousChangeFieldNames)
271
+ -- If a previous record exists, use its values
272
+ IF FOUND THEN
273
+ ${Belt.Array.zip(currentChangeFieldNames, previousChangeFieldNames)
273
274
  ->Belt.Array.map(((currentFieldName, previousFieldName)) => {
274
275
  `${historyRowArg}.${previousFieldName} := v_previous_record.${currentFieldName};`
275
276
  })
276
277
  ->Js.Array2.joinWith(" ")}
277
- ElSIF should_copy_current_entity THEN
278
- -- Check if a value for the id exists in the origin table and if so, insert a history row for it.
279
- SELECT ${dataFieldNamesCommaSeparated} FROM ${originTablePath} WHERE id = ${historyRowArg}.${id} INTO v_origin_record;
280
- IF FOUND THEN
281
- INSERT INTO ${historyTablePath} (${currentChangeFieldNamesCommaSeparated}, ${dataFieldNamesCommaSeparated}, "${actionFieldName}")
282
- -- SET the current change data fields to 0 since we don't know what they were
283
- -- and it doesn't matter provided they are less than any new values
284
- VALUES (${currentChangeFieldNames
278
+ ElSIF should_copy_current_entity THEN
279
+ -- Check if a value for the id exists in the origin table and if so, insert a history row for it.
280
+ SELECT ${dataFieldNamesCommaSeparated} FROM ${originTablePath} WHERE id = ${historyRowArg}.${id} INTO v_origin_record;
281
+ IF FOUND THEN
282
+ INSERT INTO ${historyTablePath} (${currentChangeFieldNamesCommaSeparated}, ${dataFieldNamesCommaSeparated}, "${actionFieldName}")
283
+ -- SET the current change data fields to 0 since we don't know what they were
284
+ -- and it doesn't matter provided they are less than any new values
285
+ VALUES (${currentChangeFieldNames
285
286
  ->Belt.Array.map(_ => "0")
286
287
  ->Js.Array2.joinWith(", ")}, ${dataFieldNames
287
288
  ->Belt.Array.map(fieldName => `v_origin_record."${fieldName}"`)
288
289
  ->Js.Array2.joinWith(", ")}, 'SET');
289
290
 
290
- ${previousChangeFieldNames
291
+ ${previousChangeFieldNames
291
292
  ->Belt.Array.map(previousFieldName => {
292
293
  `${historyRowArg}.${previousFieldName} := 0;`
293
294
  })
294
295
  ->Js.Array2.joinWith(" ")}
295
- END IF;
296
- END IF;
297
- END IF;
296
+ END IF;
297
+ END IF;
298
+ END IF;
298
299
 
299
- INSERT INTO ${historyTablePath} (${allFieldNamesDoubleQuoted->Js.Array2.joinWith(", ")})
300
- VALUES (${allFieldNamesDoubleQuoted
300
+ INSERT INTO ${historyTablePath} (${allFieldNamesDoubleQuoted->Js.Array2.joinWith(", ")})
301
+ VALUES (${allFieldNamesDoubleQuoted
301
302
  ->Belt.Array.map(fieldName => `${historyRowArg}.${fieldName}`)
302
303
  ->Js.Array2.joinWith(", ")});
303
- END;
304
- $$ LANGUAGE plpgsql;
305
- `
304
+ END;
305
+ $$ LANGUAGE plpgsql;`
306
306
  }
307
307
 
308
308
  let insertFnString = `(sql, rowArgs, shouldCopyCurrentEntity) =>
@@ -316,5 +316,70 @@ let fromTable = (table: table, ~pgSchema, ~schema: S.t<'entity>): t<'entity> =>
316
316
 
317
317
  let schema = makeHistoryRowSchema(schema)
318
318
 
319
- {table, createInsertFnQuery, schema, schemaRows: S.array(schema), insertFn}
319
+ {table, makeInsertFnQuery, schema, schemaRows: S.array(schema), insertFn}
320
+ }
321
+
322
+ type safeReorgBlocks = {
323
+ chainIds: array<int>,
324
+ blockNumbers: array<int>,
325
+ }
326
+
327
+ // We want to keep only the minimum history needed to survive chain reorgs and delete everything older.
328
+ // Each chain gives us a "safe block": we assume reorgs will never happen at that block.
329
+ //
330
+ // What we keep per entity id:
331
+ // - The latest history row at or before the safe block (the "anchor"). This is the last state that could
332
+ // ever be relevant during a rollback.
333
+ // - If there are history rows in reorg threshold (after the safe block), we keep the anchor and delete all older rows.
334
+ // - If there are no history rows in reorg threshold (after the safe block), even the anchor is redundant, so we delete it too.
335
+ //
336
+ // Why this is safe:
337
+ // - Rollbacks will not cross the safe block, so rows older than the anchor can never be referenced again.
338
+ // - If nothing changed in reorg threshold (after the safe block), the current state for that id can be reconstructed from the
339
+ // origin table; we do not need a pre-safe anchor for it.
340
+ //
341
+ // Performance notes:
342
+ // - Multi-chain batching: inputs are expanded with unnest, letting one prepared statement prune many chains and
343
+ // enabling the planner to use indexes per chain_id efficiently.
344
+ // - Minimal row touches: we only compute keep_serial per id and delete strictly older rows; this reduces write
345
+ // amplification and vacuum pressure compared to broad time-based purges.
346
+ // - Contention-awareness: the DELETE joins on ids first, narrowing target rows early to limit locking and buffer churn.
347
+ let makePruneStaleEntityHistoryQuery = (~entityName, ~pgSchema) => {
348
+ let historyTableName = entityName ++ "_history"
349
+ let historyTableRef = `"${pgSchema}"."${historyTableName}"`
350
+
351
+ `WITH safe AS (
352
+ SELECT s.chain_id, s.block_number
353
+ FROM unnest($1::int[], $2::bigint[]) AS s(chain_id, block_number)
354
+ ),
355
+ max_before_safe AS (
356
+ SELECT t.id, MAX(t.serial) AS keep_serial
357
+ FROM ${historyTableRef} t
358
+ JOIN safe s
359
+ ON s.chain_id = t.entity_history_chain_id
360
+ AND t.entity_history_block_number <= s.block_number
361
+ GROUP BY t.id
362
+ ),
363
+ post_safe AS (
364
+ SELECT DISTINCT t.id
365
+ FROM ${historyTableRef} t
366
+ JOIN safe s
367
+ ON s.chain_id = t.entity_history_chain_id
368
+ AND t.entity_history_block_number > s.block_number
369
+ )
370
+ DELETE FROM ${historyTableRef} d
371
+ USING max_before_safe m
372
+ LEFT JOIN post_safe p ON p.id = m.id
373
+ WHERE d.id = m.id
374
+ AND (
375
+ d.serial < m.keep_serial
376
+ OR (p.id IS NULL AND d.serial = m.keep_serial)
377
+ );`
378
+ }
379
+
380
+ let pruneStaleEntityHistory = (sql, ~entityName, ~pgSchema, ~safeReorgBlocks): promise<unit> => {
381
+ sql->Postgres.preparedUnsafe(
382
+ makePruneStaleEntityHistoryQuery(~entityName, ~pgSchema),
383
+ (safeReorgBlocks.chainIds, safeReorgBlocks.blockNumbers)->Utils.magic,
384
+ )
320
385
  }
@@ -157,7 +157,7 @@ function makeHistoryRowSchema(entitySchema) {
157
157
  }));
158
158
  }
159
159
 
160
- function fromTable(table, pgSchema, schema) {
160
+ function fromTable(table, schema) {
161
161
  var currentChangeFieldNames = [
162
162
  "entity_history_block_timestamp",
163
163
  "entity_history_chain_id",
@@ -233,17 +233,6 @@ function fromTable(table, pgSchema, schema) {
233
233
  ]
234
234
  ]));
235
235
  var insertFnName = "\"insert_" + table$1.tableName + "\"";
236
- var historyRowArg = "history_row";
237
- var historyTablePath = "\"" + pgSchema + "\".\"" + historyTableName + "\"";
238
- var originTablePath = "\"" + pgSchema + "\".\"" + originTableName + "\"";
239
- var previousHistoryFieldsAreNullStr = Belt_Array.map(previousChangeFieldNames, (function (fieldName) {
240
- return historyRowArg + "." + fieldName + " IS NULL";
241
- })).join(" OR ");
242
- var currentChangeFieldNamesCommaSeparated = currentChangeFieldNames.join(", ");
243
- var dataFieldNamesDoubleQuoted = Belt_Array.map(dataFieldNames, (function (fieldName) {
244
- return "\"" + fieldName + "\"";
245
- }));
246
- var dataFieldNamesCommaSeparated = dataFieldNamesDoubleQuoted.join(", ");
247
236
  var allFieldNamesDoubleQuoted = Belt_Array.map(Belt_Array.concatMany([
248
237
  currentChangeFieldNames,
249
238
  previousChangeFieldNames,
@@ -252,19 +241,32 @@ function fromTable(table, pgSchema, schema) {
252
241
  ]), (function (fieldName) {
253
242
  return "\"" + fieldName + "\"";
254
243
  }));
255
- var createInsertFnQuery = "CREATE OR REPLACE FUNCTION " + insertFnName + "(" + historyRowArg + " " + historyTablePath + ", should_copy_current_entity BOOLEAN)\n RETURNS void AS $$\n DECLARE\n v_previous_record RECORD;\n v_origin_record RECORD;\n BEGIN\n -- Check if previous values are not provided\n IF " + previousHistoryFieldsAreNullStr + " THEN\n -- Find the most recent record for the same id\n SELECT " + currentChangeFieldNamesCommaSeparated + " INTO v_previous_record\n FROM " + historyTablePath + "\n WHERE " + id + " = " + historyRowArg + "." + id + "\n ORDER BY " + Belt_Array.map(currentChangeFieldNames, (function (fieldName) {
256
- return fieldName + " DESC";
257
- })).join(", ") + "\n LIMIT 1;\n\n -- If a previous record exists, use its values\n IF FOUND THEN\n " + Belt_Array.map(Belt_Array.zip(currentChangeFieldNames, previousChangeFieldNames), (function (param) {
258
- return historyRowArg + "." + param[1] + " := v_previous_record." + param[0] + ";";
259
- })).join(" ") + "\n ElSIF should_copy_current_entity THEN\n -- Check if a value for the id exists in the origin table and if so, insert a history row for it.\n SELECT " + dataFieldNamesCommaSeparated + " FROM " + originTablePath + " WHERE id = " + historyRowArg + "." + id + " INTO v_origin_record;\n IF FOUND THEN\n INSERT INTO " + historyTablePath + " (" + currentChangeFieldNamesCommaSeparated + ", " + dataFieldNamesCommaSeparated + ", \"" + actionFieldName + "\")\n -- SET the current change data fields to 0 since we don't know what they were\n -- and it doesn't matter provided they are less than any new values\n VALUES (" + Belt_Array.map(currentChangeFieldNames, (function (param) {
260
- return "0";
261
- })).join(", ") + ", " + Belt_Array.map(dataFieldNames, (function (fieldName) {
262
- return "v_origin_record.\"" + fieldName + "\"";
263
- })).join(", ") + ", 'SET');\n\n " + Belt_Array.map(previousChangeFieldNames, (function (previousFieldName) {
264
- return historyRowArg + "." + previousFieldName + " := 0;";
265
- })).join(" ") + "\n END IF;\n END IF;\n END IF;\n\n INSERT INTO " + historyTablePath + " (" + allFieldNamesDoubleQuoted.join(", ") + ")\n VALUES (" + Belt_Array.map(allFieldNamesDoubleQuoted, (function (fieldName) {
266
- return historyRowArg + "." + fieldName;
267
- })).join(", ") + ");\n END;\n $$ LANGUAGE plpgsql;\n ";
244
+ var makeInsertFnQuery = function (pgSchema) {
245
+ var historyRowArg = "history_row";
246
+ var historyTablePath = "\"" + pgSchema + "\".\"" + historyTableName + "\"";
247
+ var originTablePath = "\"" + pgSchema + "\".\"" + originTableName + "\"";
248
+ var previousHistoryFieldsAreNullStr = Belt_Array.map(previousChangeFieldNames, (function (fieldName) {
249
+ return historyRowArg + "." + fieldName + " IS NULL";
250
+ })).join(" OR ");
251
+ var currentChangeFieldNamesCommaSeparated = currentChangeFieldNames.join(", ");
252
+ var dataFieldNamesDoubleQuoted = Belt_Array.map(dataFieldNames, (function (fieldName) {
253
+ return "\"" + fieldName + "\"";
254
+ }));
255
+ var dataFieldNamesCommaSeparated = dataFieldNamesDoubleQuoted.join(", ");
256
+ return "CREATE OR REPLACE FUNCTION " + insertFnName + "(" + historyRowArg + " " + historyTablePath + ", should_copy_current_entity BOOLEAN)\nRETURNS void AS $$\nDECLARE\n v_previous_record RECORD;\n v_origin_record RECORD;\nBEGIN\n -- Check if previous values are not provided\n IF " + previousHistoryFieldsAreNullStr + " THEN\n -- Find the most recent record for the same id\n SELECT " + currentChangeFieldNamesCommaSeparated + " INTO v_previous_record\n FROM " + historyTablePath + "\n WHERE " + id + " = " + historyRowArg + "." + id + "\n ORDER BY " + Belt_Array.map(currentChangeFieldNames, (function (fieldName) {
257
+ return fieldName + " DESC";
258
+ })).join(", ") + "\n LIMIT 1;\n\n -- If a previous record exists, use its values\n IF FOUND THEN\n " + Belt_Array.map(Belt_Array.zip(currentChangeFieldNames, previousChangeFieldNames), (function (param) {
259
+ return historyRowArg + "." + param[1] + " := v_previous_record." + param[0] + ";";
260
+ })).join(" ") + "\n ElSIF should_copy_current_entity THEN\n -- Check if a value for the id exists in the origin table and if so, insert a history row for it.\n SELECT " + dataFieldNamesCommaSeparated + " FROM " + originTablePath + " WHERE id = " + historyRowArg + "." + id + " INTO v_origin_record;\n IF FOUND THEN\n INSERT INTO " + historyTablePath + " (" + currentChangeFieldNamesCommaSeparated + ", " + dataFieldNamesCommaSeparated + ", \"" + actionFieldName + "\")\n -- SET the current change data fields to 0 since we don't know what they were\n -- and it doesn't matter provided they are less than any new values\n VALUES (" + Belt_Array.map(currentChangeFieldNames, (function (param) {
261
+ return "0";
262
+ })).join(", ") + ", " + Belt_Array.map(dataFieldNames, (function (fieldName) {
263
+ return "v_origin_record.\"" + fieldName + "\"";
264
+ })).join(", ") + ", 'SET');\n\n " + Belt_Array.map(previousChangeFieldNames, (function (previousFieldName) {
265
+ return historyRowArg + "." + previousFieldName + " := 0;";
266
+ })).join(" ") + "\n END IF;\n END IF;\n END IF;\n\n INSERT INTO " + historyTablePath + " (" + allFieldNamesDoubleQuoted.join(", ") + ")\n VALUES (" + Belt_Array.map(allFieldNamesDoubleQuoted, (function (fieldName) {
267
+ return historyRowArg + "." + fieldName;
268
+ })).join(", ") + ");\nEND;\n$$ LANGUAGE plpgsql;";
269
+ };
268
270
  var insertFnString = "(sql, rowArgs, shouldCopyCurrentEntity) =>\n sql\`select " + insertFnName + "(ROW(" + Belt_Array.map(allFieldNamesDoubleQuoted, (function (fieldNameDoubleQuoted) {
269
271
  return "\${rowArgs[" + fieldNameDoubleQuoted + "]\}";
270
272
  })).join(", ") + ", NULL), --NULL argument for SERIAL field\n \${shouldCopyCurrentEntity});\`";
@@ -272,17 +274,32 @@ function fromTable(table, pgSchema, schema) {
272
274
  var schema$1 = makeHistoryRowSchema(schema);
273
275
  return {
274
276
  table: table$1,
275
- createInsertFnQuery: createInsertFnQuery,
277
+ makeInsertFnQuery: makeInsertFnQuery,
276
278
  schema: schema$1,
277
279
  schemaRows: S$RescriptSchema.array(schema$1),
278
280
  insertFn: insertFn
279
281
  };
280
282
  }
281
283
 
284
+ function makePruneStaleEntityHistoryQuery(entityName, pgSchema) {
285
+ var historyTableName = entityName + "_history";
286
+ var historyTableRef = "\"" + pgSchema + "\".\"" + historyTableName + "\"";
287
+ return "WITH safe AS (\n SELECT s.chain_id, s.block_number\n FROM unnest($1::int[], $2::bigint[]) AS s(chain_id, block_number)\n),\nmax_before_safe AS (\n SELECT t.id, MAX(t.serial) AS keep_serial\n FROM " + historyTableRef + " t\n JOIN safe s\n ON s.chain_id = t.entity_history_chain_id\n AND t.entity_history_block_number <= s.block_number\n GROUP BY t.id\n),\npost_safe AS (\n SELECT DISTINCT t.id\n FROM " + historyTableRef + " t\n JOIN safe s\n ON s.chain_id = t.entity_history_chain_id\n AND t.entity_history_block_number > s.block_number\n)\nDELETE FROM " + historyTableRef + " d\nUSING max_before_safe m\nLEFT JOIN post_safe p ON p.id = m.id\nWHERE d.id = m.id\n AND (\n d.serial < m.keep_serial\n OR (p.id IS NULL AND d.serial = m.keep_serial)\n );";
288
+ }
289
+
290
+ function pruneStaleEntityHistory(sql, entityName, pgSchema, safeReorgBlocks) {
291
+ return sql.unsafe(makePruneStaleEntityHistoryQuery(entityName, pgSchema), [
292
+ safeReorgBlocks.chainIds,
293
+ safeReorgBlocks.blockNumbers
294
+ ], {prepare: true});
295
+ }
296
+
282
297
  exports.RowAction = RowAction;
283
298
  exports.entityIdOnlySchema = entityIdOnlySchema;
284
299
  exports.previousHistoryFieldsSchema = previousHistoryFieldsSchema;
285
300
  exports.currentHistoryFieldsSchema = currentHistoryFieldsSchema;
286
301
  exports.makeHistoryRowSchema = makeHistoryRowSchema;
287
302
  exports.fromTable = fromTable;
303
+ exports.makePruneStaleEntityHistoryQuery = makePruneStaleEntityHistoryQuery;
304
+ exports.pruneStaleEntityHistory = pruneStaleEntityHistory;
288
305
  /* schema Not a pure module */
@@ -0,0 +1,43 @@
1
+ /* TypeScript file generated from InternalTable.res by genType. */
2
+
3
+ /* eslint-disable */
4
+ /* tslint:disable */
5
+
6
+ import type {Json_t as Js_Json_t} from '../../src/Js.shim';
7
+
8
+ import type {t as Address_t} from '../../src/Address.gen';
9
+
10
+ export type EventSyncState_t = {
11
+ readonly chain_id: number;
12
+ readonly block_number: number;
13
+ readonly log_index: number;
14
+ readonly block_timestamp: number
15
+ };
16
+
17
+ export type RawEvents_t = {
18
+ readonly chain_id: number;
19
+ readonly event_id: bigint;
20
+ readonly event_name: string;
21
+ readonly contract_name: string;
22
+ readonly block_number: number;
23
+ readonly log_index: number;
24
+ readonly src_address: Address_t;
25
+ readonly block_hash: string;
26
+ readonly block_timestamp: number;
27
+ readonly block_fields: Js_Json_t;
28
+ readonly transaction_fields: Js_Json_t;
29
+ readonly params: Js_Json_t
30
+ };
31
+
32
+ export type DynamicContractRegistry_t = {
33
+ readonly id: string;
34
+ readonly chain_id: number;
35
+ readonly registering_event_block_number: number;
36
+ readonly registering_event_log_index: number;
37
+ readonly registering_event_block_timestamp: number;
38
+ readonly registering_event_contract_name: string;
39
+ readonly registering_event_name: string;
40
+ readonly registering_event_src_address: Address_t;
41
+ readonly contract_address: Address_t;
42
+ readonly contract_name: string
43
+ };