UNPKG

envio

Version:

A latency and sync speed optimized, developer friendly blockchain data indexer.

485 lines (437 loc) • 20.3 kB
// Generated by ReScript, PLEASE EDIT WITH CARE import * as Table from "./Table.res.mjs"; import * as Utils from "../Utils.res.mjs"; import * as Config from "../Config.res.mjs"; import * as Address from "../Address.res.mjs"; import * as Stdlib_Null from "@rescript/runtime/lib/es6/Stdlib_Null.js"; import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js"; import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js"; import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs"; import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js"; let fields = [ "id", "start_block", "end_block", "max_reorg_depth", "source_block", "first_event_block", "buffer_block", "progress_block", "ready_at", "events_processed", "_is_hyper_sync" ]; let table = Table.mkTable("envio_chains", undefined, [ Table.mkField("id", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, true, undefined, undefined, undefined, undefined, undefined), Table.mkField("start_block", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined), Table.mkField("end_block", "Int32", S$RescriptSchema.$$null(S$RescriptSchema.int), undefined, undefined, true, undefined, undefined, undefined, undefined, undefined, undefined), Table.mkField("max_reorg_depth", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined), Table.mkField("buffer_block", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined), Table.mkField("source_block", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined), Table.mkField("first_event_block", "Int32", S$RescriptSchema.$$null(S$RescriptSchema.int), undefined, undefined, true, undefined, undefined, undefined, undefined, undefined, undefined), Table.mkField("ready_at", "Date", S$RescriptSchema.$$null(Utils.Schema.dbDate), undefined, undefined, true, undefined, undefined, undefined, undefined, undefined, undefined), Table.mkField("events_processed", "UInt52", S$RescriptSchema.float, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined), Table.mkField("_is_hyper_sync", "Boolean", S$RescriptSchema.bool, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined), Table.mkField("progress_block", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined) ], undefined); function initialFromConfig(chainConfig) { return { id: chainConfig.id, start_block: chainConfig.startBlock, end_block: Stdlib_Null.fromOption(chainConfig.endBlock), max_reorg_depth: chainConfig.maxReorgDepth, source_block: 0, progress_block: -1, events_processed: 0, first_event_block: null, buffer_block: -1, ready_at: null, _is_hyper_sync: false }; } function makeInitialValuesQuery(pgSchema, chainConfigs) { if (chainConfigs.length === 0) { return; } let columnNames = fields.map(field => `"` + field + `"`); let valuesRows = chainConfigs.map(chainConfig => { let initialValues = initialFromConfig(chainConfig); let values = fields.map(field => { let value = initialValues[field]; let match = typeof value; if (match === "number" || match === "bigint") { return value.toString(); } else if (match === "boolean") { if (value) { return "true"; } else { return "false"; } } else if (match === "object") { return "NULL"; } else { return Stdlib_JsError.throwWithMessage("Invalid envio_chains value type"); } }); return `(` + values.join(", ") + `)`; }); return `INSERT INTO "` + pgSchema + `"."` + table.tableName + `" (` + columnNames.join(", ") + `) VALUES ` + valuesRows.join(",\n ") + `;`; } let metaFields = [ "buffer_block", "first_event_block", "ready_at", "_is_hyper_sync" ]; function makeMetaFieldsUpdateQuery(pgSchema) { let setClauses = metaFields.map((field, index) => { let paramIndex = index + 2 | 0; return `"` + field + `" = $` + paramIndex.toString(); }); return `UPDATE "` + pgSchema + `"."` + table.tableName + `" SET ` + setClauses.join(",\n ") + ` WHERE "` + "id" + `" = $1;`; } function makeGetInitialStateQuery(pgSchema) { return `SELECT "` + "id" + `" as "id", "` + "start_block" + `" as "startBlock", "` + "end_block" + `" as "endBlock", "` + "max_reorg_depth" + `" as "maxReorgDepth", "` + "first_event_block" + `" as "firstEventBlockNumber", "` + "ready_at" + `" as "timestampCaughtUpToHeadOrEndblock", "` + "events_processed" + `"::float8 as "numEventsProcessed", "` + "progress_block" + `" as "progressBlockNumber", "` + "source_block" + `" as "sourceBlockNumber" FROM "` + pgSchema + `"."` + table.tableName + `";`; } function makeGetIndexingAddressesQuery(pgSchema) { return `SELECT "chain_id" as "chainId", SUBSTRING("id" FROM POSITION('-' IN "id") + 1) as "address", "contract_name" as "contractName", "registration_block" as "registrationBlock" FROM "` + pgSchema + `"."` + Config.EnvioAddresses.table.tableName + `";`; } async function getInitialState(sql, pgSchema) { let match = await Promise.all([ sql.unsafe(makeGetInitialStateQuery(pgSchema)), sql.unsafe(makeGetIndexingAddressesQuery(pgSchema)) ]); let indexingAddressesByChainId = {}; match[1].forEach(row => { let key = row.chainId.toString(); let addresses = indexingAddressesByChainId[key]; let addresses$1; if (addresses !== undefined) { addresses$1 = addresses; } else { let addresses$2 = []; indexingAddressesByChainId[key] = addresses$2; addresses$1 = addresses$2; } addresses$1.push({ address: row.address, contractName: row.contractName, registrationBlock: row.registrationBlock }); }); return match[0].map(rawInitialState => ({ id: rawInitialState.id, startBlock: rawInitialState.startBlock, endBlock: rawInitialState.endBlock, maxReorgDepth: rawInitialState.maxReorgDepth, firstEventBlockNumber: rawInitialState.firstEventBlockNumber, timestampCaughtUpToHeadOrEndblock: rawInitialState.timestampCaughtUpToHeadOrEndblock, numEventsProcessed: rawInitialState.numEventsProcessed, progressBlockNumber: rawInitialState.progressBlockNumber, indexingAddresses: Stdlib_Option.getOr(indexingAddressesByChainId[rawInitialState.id.toString()], []), sourceBlockNumber: rawInitialState.sourceBlockNumber })); } let progressFields = [ "progress_block", "events_processed", "source_block" ]; function makeProgressFieldsUpdateQuery(pgSchema) { let setClauses = progressFields.map((field, index) => { let paramIndex = index + 2 | 0; return `"` + field + `" = $` + paramIndex.toString(); }); return `UPDATE "` + pgSchema + `"."` + table.tableName + `" SET ` + setClauses.join(",\n ") + ` WHERE "id" = $1;`; } function setMeta(sql, pgSchema, chainsData) { let query = makeMetaFieldsUpdateQuery(pgSchema); let promises = []; Utils.Dict.forEachWithKey(chainsData, (data, chainId) => { let params = []; params.push(chainId); metaFields.forEach(field => { let value = data[field]; params.push(value); }); promises.push(sql.unsafe(query, params, {prepare: true})); }); return Promise.all(promises); } function setProgressedChains(sql, pgSchema, progressedChains) { let query = makeProgressFieldsUpdateQuery(pgSchema); let promises = []; progressedChains.forEach(data => { let params = []; params.push(data.chainId); progressFields.forEach(field => { params.push(field === "source_block" ? data.sourceBlockNumber : ( field === "progress_block" ? data.progressBlockNumber : data.totalEventsProcessed )); }); promises.push(sql.unsafe(query, params, {prepare: true})); }); return Promise.all(promises); } let Chains = { fields: fields, table: table, initialFromConfig: initialFromConfig, makeInitialValuesQuery: makeInitialValuesQuery, metaFields: metaFields, makeMetaFieldsUpdateQuery: makeMetaFieldsUpdateQuery, makeGetInitialStateQuery: makeGetInitialStateQuery, makeGetIndexingAddressesQuery: makeGetIndexingAddressesQuery, getInitialState: getInitialState, progressFields: progressFields, makeProgressFieldsUpdateQuery: makeProgressFieldsUpdateQuery, setMeta: setMeta, setProgressedChains: setProgressedChains }; let table$1 = Table.mkTable("envio_info", undefined, [ Table.mkField("id", "Int32", S$RescriptSchema.int, "1", undefined, undefined, true, undefined, undefined, undefined, undefined, undefined), Table.mkField("config", "String", S$RescriptSchema.string, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined) ], undefined); let undefinedTableSqlState = "42P01"; async function read(sql, pgSchema) { let rows; try { rows = await sql.unsafe(`SELECT "config" FROM "` + pgSchema + `"."` + table$1.tableName + `" LIMIT 1;`); } catch (raw_exn) { let exn = Primitive_exceptions.internalToException(raw_exn); let e = Primitive_exceptions.internalToException(exn); if (e.RE_EXN_ID === "JsExn") { if (e._1.code === undefinedTableSqlState) { rows = []; } else { throw exn; } } else { throw exn; } } return Stdlib_Option.map(rows[0], row => JSON.parse(row.config)); } function write(sql, pgSchema, envioInfo) { return sql.unsafe(`INSERT INTO "` + pgSchema + `"."` + table$1.tableName + `" ("id", "config") VALUES (1, $1) ON CONFLICT ("id") DO UPDATE SET "config" = EXCLUDED."config";`, [JSON.stringify(envioInfo)], {prepare: true}); } let EnvioInfo = { table: table$1, undefinedTableSqlState: undefinedTableSqlState, read: read, write: write }; let dbSchema = S$RescriptSchema.object(s => ({ id: s.f("id", Utils.$$BigInt.schema), chain_id: s.f("chain_id", S$RescriptSchema.int), block_number: s.f("block_number", S$RescriptSchema.int), block_hash: s.f("block_hash", S$RescriptSchema.union([ S$RescriptSchema.string, S$RescriptSchema.literal(null) ])), events_processed: s.f("events_processed", S$RescriptSchema.int) })); let table$2 = Table.mkTable("envio_checkpoints", undefined, [ Table.mkField("id", "UInt64", S$RescriptSchema.bigint, undefined, undefined, undefined, true, undefined, undefined, undefined, undefined, undefined), Table.mkField("chain_id", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined), Table.mkField("block_number", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined), Table.mkField("block_hash", "String", S$RescriptSchema.$$null(S$RescriptSchema.string), undefined, undefined, true, undefined, undefined, undefined, undefined, undefined, undefined), Table.mkField("events_processed", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined) ], undefined); function makeGetReorgCheckpointsQuery(pgSchema) { return `WITH reorg_chains AS ( SELECT "` + "id" + `" as id, "` + "source_block" + `" - "` + "max_reorg_depth" + `" AS safe_block FROM "` + pgSchema + `"."` + table.tableName + `" WHERE "` + "max_reorg_depth" + `" > 0 AND "` + "progress_block" + `" > "` + "source_block" + `" - "` + "max_reorg_depth" + `" ) SELECT cp."` + "id" + `", cp."` + "chain_id" + `", cp."` + "block_number" + `", cp."` + "block_hash" + `" FROM "` + pgSchema + `"."` + table$2.tableName + `" cp INNER JOIN reorg_chains rc ON cp."` + "chain_id" + `" = rc.id WHERE cp."` + "block_hash" + `" IS NOT NULL AND cp."` + "block_number" + `" >= rc.safe_block;`; } function makeCommitedCheckpointIdQuery(pgSchema) { return `SELECT COALESCE(MAX(` + "id" + `), ` + (0n).toString() + `) AS id FROM "` + pgSchema + `"."` + table$2.tableName + `";`; } function makeInsertCheckpointQuery(pgSchema) { return `INSERT INTO "` + pgSchema + `"."` + table$2.tableName + `" ("` + "id" + `", "` + "chain_id" + `", "` + "block_number" + `", "` + "block_hash" + `", "` + "events_processed" + `") SELECT * FROM unnest($1::` + "BIGINT" + `[],$2::` + "INTEGER" + `[],$3::` + "INTEGER" + `[],$4::` + "TEXT" + `[],$5::` + "INTEGER" + `[]);`; } function insert(sql, pgSchema, checkpointIds, checkpointChainIds, checkpointBlockNumbers, checkpointBlockHashes, checkpointEventsProcessed) { let query = makeInsertCheckpointQuery(pgSchema); let checkpointIdStrings = Utils.$$BigInt.arrayToStringArray(checkpointIds); return sql.unsafe(query, [ checkpointIdStrings, checkpointChainIds, checkpointBlockNumbers, checkpointBlockHashes, checkpointEventsProcessed ], {prepare: true}); } function rollback(sql, pgSchema, rollbackTargetCheckpointId) { return sql.unsafe(`DELETE FROM "` + pgSchema + `"."` + table$2.tableName + `" WHERE "` + "id" + `" > $1;`, [rollbackTargetCheckpointId.toString()], {prepare: true}); } function makePruneStaleCheckpointsQuery(pgSchema) { return `DELETE FROM "` + pgSchema + `"."` + table$2.tableName + `" WHERE "` + "id" + `" < $1;`; } function pruneStaleCheckpoints(sql, pgSchema, safeCheckpointId) { return sql.unsafe(makePruneStaleCheckpointsQuery(pgSchema), [safeCheckpointId.toString()], {prepare: true}); } function makeGetRollbackTargetCheckpointQuery(pgSchema) { return `SELECT "` + "id" + `" FROM "` + pgSchema + `"."` + table$2.tableName + `" WHERE "` + "chain_id" + `" = $1 AND "` + "block_number" + `" <= $2 ORDER BY "` + "id" + `" DESC LIMIT 1;`; } function getRollbackTargetCheckpoint(sql, pgSchema, reorgChainId, lastKnownValidBlockNumber) { let rawResult = sql.unsafe(makeGetRollbackTargetCheckpointQuery(pgSchema), [ reorgChainId, lastKnownValidBlockNumber ], {prepare: true}); return rawResult.then(rows => Stdlib_Option.map(rows[0], row => BigInt(row.id))); } function makeGetRollbackProgressDiffQuery(pgSchema) { return `SELECT "` + "chain_id" + `", SUM("` + "events_processed" + `") as events_processed_diff, MIN("` + "block_number" + `") - 1 as new_progress_block_number FROM "` + pgSchema + `"."` + table$2.tableName + `" WHERE "` + "id" + `" > $1 GROUP BY "` + "chain_id" + `";`; } function getRollbackProgressDiff(sql, pgSchema, rollbackTargetCheckpointId) { return sql.unsafe(makeGetRollbackProgressDiffQuery(pgSchema), [rollbackTargetCheckpointId.toString()], {prepare: true}); } let Checkpoints = { dbSchema: dbSchema, initialCheckpointId: 0n, table: table$2, makeGetReorgCheckpointsQuery: makeGetReorgCheckpointsQuery, makeCommitedCheckpointIdQuery: makeCommitedCheckpointIdQuery, makeInsertCheckpointQuery: makeInsertCheckpointQuery, insert: insert, rollback: rollback, makePruneStaleCheckpointsQuery: makePruneStaleCheckpointsQuery, pruneStaleCheckpoints: pruneStaleCheckpoints, makeGetRollbackTargetCheckpointQuery: makeGetRollbackTargetCheckpointQuery, getRollbackTargetCheckpoint: getRollbackTargetCheckpoint, makeGetRollbackProgressDiffQuery: makeGetRollbackProgressDiffQuery, getRollbackProgressDiff: getRollbackProgressDiff }; let schema = S$RescriptSchema.schema(s => ({ chain_id: s.m(S$RescriptSchema.int), event_id: s.m(S$RescriptSchema.bigint), event_name: s.m(S$RescriptSchema.string), contract_name: s.m(S$RescriptSchema.string), block_number: s.m(S$RescriptSchema.int), log_index: s.m(S$RescriptSchema.int), src_address: s.m(Address.schema), block_hash: s.m(S$RescriptSchema.string), block_timestamp: s.m(S$RescriptSchema.int), block_fields: s.m(S$RescriptSchema.json(false)), transaction_fields: s.m(S$RescriptSchema.json(false)), params: s.m(S$RescriptSchema.json(false)) })); let table$3 = Table.mkTable("raw_events", undefined, [ Table.mkField("chain_id", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined), Table.mkField("event_id", "UInt64", S$RescriptSchema.bigint, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined), Table.mkField("event_name", "String", S$RescriptSchema.string, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined), Table.mkField("contract_name", "String", S$RescriptSchema.string, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined), Table.mkField("block_number", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined), Table.mkField("log_index", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined), Table.mkField("src_address", "String", Address.schema, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined), Table.mkField("block_hash", "String", S$RescriptSchema.string, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined), Table.mkField("block_timestamp", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined), Table.mkField("block_fields", "Json", S$RescriptSchema.json(false), undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined), Table.mkField("transaction_fields", "Json", S$RescriptSchema.json(false), undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined), Table.mkField("params", "Json", S$RescriptSchema.json(false), undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined), Table.mkField("serial", "BigSerial", S$RescriptSchema.$$null(S$RescriptSchema.bigint), undefined, undefined, true, true, undefined, undefined, undefined, undefined, undefined) ], undefined); let RawEvents = { schema: schema, table: table$3 }; let metaViewName = "_meta"; let chainMetadataViewName = "chain_metadata"; function makeMetaViewQuery(pgSchema) { return `CREATE VIEW "` + pgSchema + `"."` + metaViewName + `" AS SELECT "` + "id" + `" AS "chainId", "` + "start_block" + `" AS "startBlock", "` + "end_block" + `" AS "endBlock", "` + "progress_block" + `" AS "progressBlock", "` + "buffer_block" + `" AS "bufferBlock", "` + "first_event_block" + `" AS "firstEventBlock", "` + "events_processed" + `"::float4 AS "eventsProcessed", "` + "source_block" + `" AS "sourceBlock", "` + "ready_at" + `" AS "readyAt", ("` + "ready_at" + `" IS NOT NULL) AS "isReady" FROM "` + pgSchema + `"."` + table.tableName + `" ORDER BY "` + "id" + `";`; } function makeChainMetadataViewQuery(pgSchema) { return `CREATE VIEW "` + pgSchema + `"."` + chainMetadataViewName + `" AS SELECT "` + "source_block" + `" AS "block_height", "` + "id" + `" AS "chain_id", "` + "end_block" + `" AS "end_block", "` + "first_event_block" + `" AS "first_event_block_number", "` + "_is_hyper_sync" + `" AS "is_hyper_sync", "` + "buffer_block" + `" AS "latest_fetched_block_number", "` + "progress_block" + `" AS "latest_processed_block", 0 AS "num_batches_fetched", "` + "events_processed" + `"::float4 AS "num_events_processed", "` + "start_block" + `" AS "start_block", "` + "ready_at" + `" AS "timestamp_caught_up_to_head_or_endblock" FROM "` + pgSchema + `"."` + table.tableName + `";`; } let Views = { metaViewName: metaViewName, chainMetadataViewName: chainMetadataViewName, makeMetaViewQuery: makeMetaViewQuery, makeChainMetadataViewQuery: makeChainMetadataViewQuery }; let isPrimaryKey = true; let isNullable = true; let isIndex = true; let EnvioAddresses; export { isPrimaryKey, isNullable, isIndex, EnvioAddresses, Chains, EnvioInfo, Checkpoints, RawEvents, Views, } /* table Not a pure module */