envio
Version:
A latency and sync speed optimized, developer friendly blockchain data indexer.
485 lines (437 loc) • 20.3 kB
JavaScript
// 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 */