envio
Version:
A latency and sync speed optimized, developer friendly blockchain data indexer.
1,023 lines (977 loc) • 38.3 kB
JavaScript
// Generated by ReScript, PLEASE EDIT WITH CARE
import * as Env from "./Env.res.mjs";
import * as Evm from "./sources/Evm.res.mjs";
import * as Svm from "./sources/Svm.res.mjs";
import * as Core from "./Core.res.mjs";
import * as Fuel from "./sources/Fuel.res.mjs";
import * as Table from "./db/Table.res.mjs";
import * as Utils from "./Utils.res.mjs";
import * as Address from "./Address.res.mjs";
import * as ChainMap from "./ChainMap.res.mjs";
import * as Internal from "./Internal.res.mjs";
import * as BigDecimal from "./bindings/BigDecimal.res.mjs";
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.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 Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
import * as Primitive_string from "@rescript/runtime/lib/es6/Primitive_string.js";
import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
import * as EventConfigBuilder from "./EventConfigBuilder.res.mjs";
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
let name = "envio_addresses";
function makeId(chainId, address) {
return chainId.toString() + "-" + address;
}
function getAddress(entity) {
let sepIdx = entity.id.indexOf("-");
return entity.id.slice(sepIdx + 1 | 0, entity.id.length);
}
let schema = S$RescriptSchema.schema(s => ({
id: s.m(S$RescriptSchema.string),
chain_id: s.m(S$RescriptSchema.int),
registration_block: s.m(S$RescriptSchema.int),
registration_log_index: s.m(S$RescriptSchema.int),
contract_name: s.m(S$RescriptSchema.string)
}));
let table = Table.mkTable(name, undefined, [
Table.mkField("id", "String", S$RescriptSchema.string, 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("registration_block", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
Table.mkField("registration_log_index", "Int32", S$RescriptSchema.int, 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)
], undefined);
let entityConfig_storage = {
postgres: true,
clickhouse: false
};
let entityConfig = {
name: name,
index: -1,
schema: schema,
table: table,
storage: entityConfig_storage
};
let EnvioAddresses = {
name: name,
index: -1,
makeId: makeId,
getAddress: getAddress,
schema: schema,
table: table,
entityConfig: entityConfig
};
let rpcSourceForSchema = S$RescriptSchema.$$enum([
"sync",
"fallback",
"realtime"
]);
let rpcConfigSchema = S$RescriptSchema.schema(s => ({
url: s.m(S$RescriptSchema.string),
for: s.m(rpcSourceForSchema),
ws: s.m(S$RescriptSchema.option(S$RescriptSchema.string)),
initialBlockInterval: s.m(S$RescriptSchema.option(S$RescriptSchema.int)),
backoffMultiplicative: s.m(S$RescriptSchema.option(S$RescriptSchema.float)),
accelerationAdditive: s.m(S$RescriptSchema.option(S$RescriptSchema.int)),
intervalCeiling: s.m(S$RescriptSchema.option(S$RescriptSchema.int)),
backoffMillis: s.m(S$RescriptSchema.option(S$RescriptSchema.int)),
fallbackStallTimeout: s.m(S$RescriptSchema.option(S$RescriptSchema.int)),
queryTimeoutMillis: s.m(S$RescriptSchema.option(S$RescriptSchema.int)),
pollingInterval: s.m(S$RescriptSchema.option(S$RescriptSchema.int))
}));
let chainContractSchema = S$RescriptSchema.schema(s => ({
addresses: s.m(S$RescriptSchema.option(S$RescriptSchema.array(S$RescriptSchema.string))),
startBlock: s.m(S$RescriptSchema.option(S$RescriptSchema.int))
}));
let publicConfigChainSchema = S$RescriptSchema.schema(s => ({
id: s.m(S$RescriptSchema.int),
startBlock: s.m(S$RescriptSchema.int),
endBlock: s.m(S$RescriptSchema.option(S$RescriptSchema.int)),
maxReorgDepth: s.m(S$RescriptSchema.option(S$RescriptSchema.int)),
blockLag: s.m(S$RescriptSchema.option(S$RescriptSchema.int)),
hypersync: s.m(S$RescriptSchema.option(S$RescriptSchema.string)),
rpcs: s.m(S$RescriptSchema.option(S$RescriptSchema.array(rpcConfigSchema))),
rpc: s.m(S$RescriptSchema.option(S$RescriptSchema.string)),
contracts: s.m(S$RescriptSchema.option(S$RescriptSchema.dict(chainContractSchema)))
}));
let svmEventDescriptorSchema = S$RescriptSchema.schema(s => ({
discriminator: s.m(S$RescriptSchema.option(S$RescriptSchema.string)),
discriminatorByteLen: s.m(S$RescriptSchema.int),
includeTransaction: s.m(S$RescriptSchema.bool),
includeLogs: s.m(S$RescriptSchema.bool),
includeTokenBalances: s.m(S$RescriptSchema.bool),
accountFilters: s.m(S$RescriptSchema.option(S$RescriptSchema.array(S$RescriptSchema.schema(s => ({
position: s.m(S$RescriptSchema.int),
values: s.m(S$RescriptSchema.array(S$RescriptSchema.string))
}))))),
isInner: s.m(S$RescriptSchema.option(S$RescriptSchema.bool)),
accounts: s.m(S$RescriptSchema.option(S$RescriptSchema.array(S$RescriptSchema.string))),
args: s.m(S$RescriptSchema.option(S$RescriptSchema.json(false)))
}));
let svmAbiSchema = S$RescriptSchema.schema(s => ({
programId: s.m(S$RescriptSchema.string),
definedTypes: s.m(S$RescriptSchema.json(false)),
source: s.m(S$RescriptSchema.string)
}));
let contractEventItemSchema = S$RescriptSchema.schema(s => ({
name: s.m(S$RescriptSchema.string),
sighash: s.m(S$RescriptSchema.string),
params: s.m(S$RescriptSchema.option(S$RescriptSchema.array(EventConfigBuilder.paramMetaSchema))),
kind: s.m(S$RescriptSchema.option(S$RescriptSchema.string)),
blockFields: s.m(S$RescriptSchema.option(S$RescriptSchema.array(Internal.evmBlockFieldSchema))),
transactionFields: s.m(S$RescriptSchema.option(S$RescriptSchema.array(Internal.evmTransactionFieldSchema))),
svm: s.m(S$RescriptSchema.option(svmEventDescriptorSchema))
}));
let contractConfigSchema = S$RescriptSchema.schema(s => ({
abi: s.m(S$RescriptSchema.json(false)),
handler: s.m(S$RescriptSchema.option(S$RescriptSchema.string)),
events: s.m(S$RescriptSchema.option(S$RescriptSchema.array(contractEventItemSchema))),
svmAbi: s.m(S$RescriptSchema.option(svmAbiSchema))
}));
let publicConfigEcosystemSchema = S$RescriptSchema.schema(s => ({
chains: s.m(S$RescriptSchema.dict(publicConfigChainSchema)),
contracts: s.m(S$RescriptSchema.option(S$RescriptSchema.dict(contractConfigSchema))),
programs: s.m(S$RescriptSchema.option(S$RescriptSchema.dict(contractConfigSchema)))
}));
let publicConfigEvmSchema = S$RescriptSchema.schema(s => ({
chains: s.m(S$RescriptSchema.dict(publicConfigChainSchema)),
contracts: s.m(S$RescriptSchema.option(S$RescriptSchema.dict(contractConfigSchema))),
addressFormat: s.m(S$RescriptSchema.option(S$RescriptSchema.$$enum([
"lowercase",
"checksum"
]))),
globalBlockFields: s.m(S$RescriptSchema.option(S$RescriptSchema.array(Internal.evmBlockFieldSchema))),
globalTransactionFields: s.m(S$RescriptSchema.option(S$RescriptSchema.array(Internal.evmTransactionFieldSchema)))
}));
let compositeIndexFieldSchema = S$RescriptSchema.schema(s => ({
fieldName: s.m(S$RescriptSchema.string),
direction: s.m(S$RescriptSchema.string)
}));
let derivedFieldSchema = S$RescriptSchema.schema(s => ({
fieldName: s.m(S$RescriptSchema.string),
derivedFromEntity: s.m(S$RescriptSchema.string),
derivedFromField: s.m(S$RescriptSchema.string),
description: s.m(S$RescriptSchema.option(S$RescriptSchema.string))
}));
let propertySchema = S$RescriptSchema.schema(s => ({
name: s.m(S$RescriptSchema.string),
postgresDbName: s.m(S$RescriptSchema.option(S$RescriptSchema.string)),
clickhouseDbName: s.m(S$RescriptSchema.option(S$RescriptSchema.string)),
type: s.m(S$RescriptSchema.string),
isNullable: s.m(S$RescriptSchema.option(S$RescriptSchema.bool)),
isArray: s.m(S$RescriptSchema.option(S$RescriptSchema.bool)),
isIndex: s.m(S$RescriptSchema.option(S$RescriptSchema.bool)),
linkedEntity: s.m(S$RescriptSchema.option(S$RescriptSchema.string)),
enum: s.m(S$RescriptSchema.option(S$RescriptSchema.string)),
entity: s.m(S$RescriptSchema.option(S$RescriptSchema.string)),
precision: s.m(S$RescriptSchema.option(S$RescriptSchema.int)),
scale: s.m(S$RescriptSchema.option(S$RescriptSchema.int)),
description: s.m(S$RescriptSchema.option(S$RescriptSchema.string))
}));
let entityStorageSchema = S$RescriptSchema.schema(s => ({
postgres: s.m(S$RescriptSchema.option(S$RescriptSchema.bool)),
clickhouse: s.m(S$RescriptSchema.option(S$RescriptSchema.bool))
}));
let entityJsonSchema = S$RescriptSchema.schema(s => ({
name: s.m(S$RescriptSchema.string),
storage: s.m(S$RescriptSchema.option(entityStorageSchema)),
properties: s.m(S$RescriptSchema.array(propertySchema)),
derivedFields: s.m(S$RescriptSchema.option(S$RescriptSchema.array(derivedFieldSchema))),
compositeIndices: s.m(S$RescriptSchema.option(S$RescriptSchema.array(S$RescriptSchema.array(compositeIndexFieldSchema)))),
description: s.m(S$RescriptSchema.option(S$RescriptSchema.string))
}));
function getFieldTypeAndSchema(prop, enumConfigsByName) {
let typ = prop.type;
let isNullable = Stdlib_Option.getOr(prop.isNullable, false);
let isArray = Stdlib_Option.getOr(prop.isArray, false);
let isIndex = Stdlib_Option.getOr(prop.isIndex, false);
let match;
switch (typ) {
case "bigdecimal" :
match = [
{
type: "BigDecimal",
config: Stdlib_Option.map(prop.precision, p => [
p,
Stdlib_Option.getOr(prop.scale, 0)
])
},
BigDecimal.schema
];
break;
case "bigint" :
match = [
{
type: "BigInt",
precision: prop.precision
},
Utils.$$BigInt.schema
];
break;
case "boolean" :
match = [
"Boolean",
S$RescriptSchema.bool
];
break;
case "date" :
match = [
"Date",
Utils.Schema.dbDate
];
break;
case "entity" :
let entityName = Stdlib_Option.getOrThrow(prop.entity, undefined);
match = [
{
type: "Entity",
name: entityName
},
S$RescriptSchema.string
];
break;
case "enum" :
let enumName = Stdlib_Option.getOrThrow(prop.enum, undefined);
let enumConfig = Stdlib_Option.getOrThrow(enumConfigsByName[enumName], undefined);
match = [
{
type: "Enum",
config: enumConfig
},
enumConfig.schema
];
break;
case "float" :
match = [
"Number",
S$RescriptSchema.float
];
break;
case "int" :
match = [
"Int32",
S$RescriptSchema.int
];
break;
case "json" :
match = [
"Json",
S$RescriptSchema.json(false)
];
break;
case "serial" :
match = [
"Serial",
S$RescriptSchema.int
];
break;
case "string" :
match = [
"String",
S$RescriptSchema.string
];
break;
default:
match = Stdlib_JsError.throwWithMessage("Unknown field type in entity config: " + typ);
}
let baseSchema = match[1];
let fieldSchema = isArray ? S$RescriptSchema.array(baseSchema) : baseSchema;
let fieldSchema$1 = isNullable ? S$RescriptSchema.$$null(fieldSchema) : fieldSchema;
return [
match[0],
fieldSchema$1,
isNullable,
isArray,
isIndex
];
}
function parseEnumsFromJson(enumsJson) {
return Object.entries(enumsJson).map(param => Table.makeEnumConfig(param[0], param[1]));
}
function parseEntitiesFromJson(entitiesJson, enumConfigsByName, globalStorage) {
return entitiesJson.map((entityJson, index) => {
let entityName = entityJson.name;
let fields = entityJson.properties.map(prop => {
let match = getFieldTypeAndSchema(prop, enumConfigsByName);
return Table.mkField(prop.name, match[0], match[1], undefined, match[3], match[2], prop.name === "id", match[4], prop.linkedEntity, prop.description, prop.postgresDbName, prop.clickhouseDbName);
});
let derivedFields = Stdlib_Option.getOr(entityJson.derivedFields, []).map(df => Table.mkDerivedFromField(df.fieldName, df.derivedFromEntity, df.derivedFromField, df.description));
let compositeIndices = Stdlib_Option.getOr(entityJson.compositeIndices, []).map(ci => ci.map(f => ({
fieldName: f.fieldName,
direction: f.direction === "Asc" ? "Asc" : "Desc"
})));
let table = Table.mkTable(entityName, compositeIndices, fields.concat(derivedFields), entityJson.description);
let getApiFieldName = prop => {
let match = prop.linkedEntity;
if (match !== undefined) {
return prop.name + "_id";
} else {
return prop.name;
}
};
let schema = S$RescriptSchema.schema(s => {
let dict = {};
entityJson.properties.forEach(prop => {
let match = getFieldTypeAndSchema(prop, enumConfigsByName);
dict[getApiFieldName(prop)] = s.m(match[1]);
});
return dict;
});
let s = entityJson.storage;
let storage;
if (s !== undefined) {
let s$1 = Primitive_option.valFromOption(s);
storage = {
postgres: Stdlib_Option.getOr(s$1.postgres, false),
clickhouse: Stdlib_Option.getOr(s$1.clickhouse, false)
};
} else {
storage = {
postgres: globalStorage.postgres,
clickhouse: globalStorage.clickhouse
};
}
return {
name: entityName,
index: index,
schema: schema,
table: table,
storage: storage
};
});
}
let publicConfigStorageSchema = S$RescriptSchema.schema(s => ({
postgres: s.m(S$RescriptSchema.bool),
clickhouse: s.m(S$RescriptSchema.option(S$RescriptSchema.bool))
}));
let publicConfigSchema = S$RescriptSchema.schema(s => ({
name: s.m(S$RescriptSchema.string),
description: s.m(S$RescriptSchema.option(S$RescriptSchema.string)),
handlers: s.m(S$RescriptSchema.option(S$RescriptSchema.string)),
isDev: s.m(S$RescriptSchema.option(S$RescriptSchema.bool)),
fullBatchSize: s.m(S$RescriptSchema.option(S$RescriptSchema.int)),
rollbackOnReorg: s.m(S$RescriptSchema.option(S$RescriptSchema.bool)),
saveFullHistory: s.m(S$RescriptSchema.option(S$RescriptSchema.bool)),
rawEvents: s.m(S$RescriptSchema.option(S$RescriptSchema.bool)),
storage: s.m(publicConfigStorageSchema),
evm: s.m(S$RescriptSchema.option(publicConfigEvmSchema)),
fuel: s.m(S$RescriptSchema.option(publicConfigEcosystemSchema)),
svm: s.m(S$RescriptSchema.option(publicConfigEcosystemSchema)),
enums: s.m(S$RescriptSchema.option(S$RescriptSchema.dict(S$RescriptSchema.array(S$RescriptSchema.string)))),
entities: s.m(S$RescriptSchema.option(S$RescriptSchema.array(entityJsonSchema)))
}));
function fromPublic(publicConfigJson) {
let publicConfig;
try {
publicConfig = S$RescriptSchema.parseOrThrow(publicConfigJson, publicConfigSchema);
} catch (raw_exn) {
let exn = Primitive_exceptions.internalToException(raw_exn);
if (exn.RE_EXN_ID === S$RescriptSchema.Raised) {
publicConfig = Stdlib_JsError.throwWithMessage(`Invalid indexer config: ` + Utils.prettifyExn(exn._1));
} else {
throw exn;
}
}
let match = publicConfig.evm;
let match$1 = publicConfig.fuel;
let match$2 = publicConfig.svm;
let match$3 = match !== undefined ? (
match$1 !== undefined || match$2 !== undefined ? Stdlib_JsError.throwWithMessage("Invalid indexer config: Multiple ecosystems are not supported for a single indexer") : [
Primitive_option.valFromOption(match).chains,
"evm"
]
) : (
match$1 !== undefined ? (
match$2 !== undefined ? Stdlib_JsError.throwWithMessage("Invalid indexer config: Multiple ecosystems are not supported for a single indexer") : [
Primitive_option.valFromOption(match$1).chains,
"fuel"
]
) : (
match$2 !== undefined ? [
Primitive_option.valFromOption(match$2).chains,
"svm"
] : Stdlib_JsError.throwWithMessage("Invalid indexer config: No ecosystem configured (evm, fuel, or svm)")
)
);
let ecosystemName = match$3[1];
let publicChainsConfig = match$3[0];
let ecosystem;
switch (ecosystemName) {
case "evm" :
ecosystem = Evm.ecosystem;
break;
case "fuel" :
ecosystem = Fuel.ecosystem;
break;
case "svm" :
ecosystem = Svm.ecosystem;
break;
}
let evm = publicConfig.evm;
let lowercaseAddresses = evm !== undefined ? Stdlib_Option.getOr(Primitive_option.valFromOption(evm).addressFormat, "checksum") === "lowercase" : false;
let match$4 = publicConfig.evm;
let match$5 = publicConfig.fuel;
let match$6 = publicConfig.svm;
let publicContractsConfig;
switch (ecosystemName) {
case "evm" :
publicContractsConfig = match$4 !== undefined ? Primitive_option.valFromOption(match$4).contracts : undefined;
break;
case "fuel" :
publicContractsConfig = match$5 !== undefined ? Primitive_option.valFromOption(match$5).contracts : undefined;
break;
case "svm" :
publicContractsConfig = match$6 !== undefined ? Primitive_option.valFromOption(match$6).programs : undefined;
break;
}
let evm$1 = publicConfig.evm;
let match$7;
if (evm$1 !== undefined) {
let evm$2 = Primitive_option.valFromOption(evm$1);
match$7 = [
new Set(EventConfigBuilder.alwaysIncludedBlockFields.concat(Stdlib_Option.getOr(evm$2.globalBlockFields, []))),
new Set(Stdlib_Option.getOr(evm$2.globalTransactionFields, []))
];
} else {
match$7 = [
new Set(EventConfigBuilder.alwaysIncludedBlockFields),
new Set()
];
}
let globalTransactionFieldsSet = match$7[1];
let globalBlockFieldsSet = match$7[0];
let contractDataByName = {};
if (publicContractsConfig !== undefined) {
Object.entries(publicContractsConfig).forEach(param => {
let contractConfig = param[1];
let capitalizedName = Utils.$$String.capitalize(param[0]);
let abi = contractConfig.abi;
let events = contractConfig.events;
let eventSignatures = events !== undefined ? events.map(eventItem => eventItem.sighash) : [];
contractDataByName[capitalizedName] = {
abi: abi,
eventSignatures: eventSignatures,
events: contractConfig.events,
svmAbi: contractConfig.svmAbi
};
});
}
let buildContractEvents = (contractName, events, abi, chainId, startBlock, addresses, svmDefinedTypesOpt) => {
let svmDefinedTypes = svmDefinedTypesOpt !== undefined ? svmDefinedTypesOpt : null;
if (events !== undefined) {
return events.map(eventItem => {
let eventName = eventItem.name;
let sighash = eventItem.sighash;
let params = Stdlib_Option.getOr(eventItem.params, []);
let kind = eventItem.kind;
switch (ecosystemName) {
case "evm" :
return EventConfigBuilder.buildEvmEventConfig(contractName, eventName, sighash, params, false, undefined, undefined, undefined, chainId, ecosystem.onEventBlockFilterSchema, eventItem.blockFields, eventItem.transactionFields, startBlock, Primitive_option.some(globalBlockFieldsSet), Primitive_option.some(globalTransactionFieldsSet));
case "fuel" :
if (kind !== undefined) {
return EventConfigBuilder.buildFuelEventConfig(contractName, eventName, kind, sighash, abi, false, undefined, undefined, startBlock);
} else {
return Stdlib_JsError.throwWithMessage(`Fuel event ` + contractName + `.` + eventName + ` is missing "kind" in internal config`);
}
case "svm" :
let len = addresses.length;
let programId = len !== 1 ? (
len !== 0 ? Stdlib_JsError.throwWithMessage(`SVM program ` + contractName + ` on chain ` + chainId.toString() + ` has multiple addresses; a program is uniquely identified by a single program_id`) : Stdlib_JsError.throwWithMessage(`SVM program ` + contractName + ` on chain ` + chainId.toString() + ` is missing a program_id`)
) : addresses[0];
let s = eventItem.svm;
let svm = s !== undefined ? Primitive_option.valFromOption(s) : Stdlib_JsError.throwWithMessage(`SVM instruction ` + contractName + `.` + eventName + ` is missing the "svm" descriptor in internal config`);
let accountFilters = Stdlib_Option.getOr(svm.accountFilters, []).map(group => group.map(af => ({
position: af.position,
values: af.values
})));
return EventConfigBuilder.buildSvmInstructionEventConfig(contractName, eventName, programId, svm.discriminator, svm.discriminatorByteLen, svm.includeTransaction, svm.includeLogs, svm.includeTokenBalances, accountFilters, svm.isInner, false, undefined, undefined, Stdlib_Option.getOr(svm.accounts, []), Stdlib_Option.getOr(svm.args, null), svmDefinedTypes, startBlock);
}
});
} else {
return [];
}
};
let parseAddress = addressString => {
switch (ecosystemName) {
case "evm" :
if (lowercaseAddresses) {
return Address.Evm.fromStringLowercaseOrThrow(addressString);
} else {
return Address.Evm.fromStringOrThrow(addressString);
}
case "fuel" :
case "svm" :
return addressString;
}
};
let parseRpcSourceFor = sourceFor => {
switch (sourceFor) {
case "sync" :
return "Sync";
case "fallback" :
return "Fallback";
case "realtime" :
return "Realtime";
}
};
let chains = Object.keys(publicChainsConfig).map(chainName => {
let publicChainConfig = publicChainsConfig[chainName];
let chainId = publicChainConfig.id;
let chainContracts = Stdlib_Option.getOr(publicChainConfig.contracts, {});
let contracts = Object.entries(contractDataByName).map(param => {
let contractData = param[1];
let capitalizedName = param[0];
let chainContract = chainContracts[capitalizedName];
let rawAddresses = Stdlib_Option.getOr(Stdlib_Option.flatMap(chainContract, cc => cc.addresses), []);
let addresses = rawAddresses.map(parseAddress);
let startBlock = Stdlib_Option.flatMap(chainContract, cc => cc.startBlock);
let events = buildContractEvents(capitalizedName, contractData.events, contractData.abi, chainId, startBlock, rawAddresses, Stdlib_Option.getOr(Stdlib_Option.map(contractData.svmAbi, a => a.definedTypes), null));
return {
name: capitalizedName,
abi: contractData.abi,
addresses: addresses,
events: events,
startBlock: startBlock
};
});
let contractNameByAddress = {};
contracts.forEach(contract => {
contract.addresses.forEach(address => {
let existingContractName = contractNameByAddress[address];
if (existingContractName !== undefined) {
return Stdlib_JsError.throwWithMessage(existingContractName === contract.name ? `Address ` + address + ` is listed multiple times for the contract ` + contract.name + ` on chain ` + chainId.toString() + `. Please remove the duplicate from your config.` : `Address ` + address + ` on chain ` + chainId.toString() + ` is configured for multiple contracts: ` + existingContractName + ` and ` + contract.name + `. Indexing the same address with multiple contract definitions is not supported. Please define the events on a single contract definition instead.`);
} else {
contractNameByAddress[address] = contract.name;
return;
}
});
});
let sourceConfig;
switch (ecosystemName) {
case "evm" :
let rpcs = Stdlib_Option.getOr(publicChainConfig.rpcs, []).map(rpcConfig => {
let initialBlockInterval = rpcConfig.initialBlockInterval;
let backoffMultiplicative = rpcConfig.backoffMultiplicative;
let accelerationAdditive = rpcConfig.accelerationAdditive;
let intervalCeiling = rpcConfig.intervalCeiling;
let backoffMillis = rpcConfig.backoffMillis;
let queryTimeoutMillis = rpcConfig.queryTimeoutMillis;
let fallbackStallTimeout = rpcConfig.fallbackStallTimeout;
let pollingInterval = rpcConfig.pollingInterval;
let hasSyncConfig = Stdlib_Option.isSome(initialBlockInterval) || Stdlib_Option.isSome(backoffMultiplicative) || Stdlib_Option.isSome(accelerationAdditive) || Stdlib_Option.isSome(intervalCeiling) || Stdlib_Option.isSome(backoffMillis) || Stdlib_Option.isSome(queryTimeoutMillis) || Stdlib_Option.isSome(fallbackStallTimeout) || Stdlib_Option.isSome(pollingInterval);
let syncConfig = hasSyncConfig ? ({
initialBlockInterval: initialBlockInterval,
backoffMultiplicative: backoffMultiplicative,
accelerationAdditive: accelerationAdditive,
intervalCeiling: intervalCeiling,
backoffMillis: backoffMillis,
queryTimeoutMillis: queryTimeoutMillis,
fallbackStallTimeout: fallbackStallTimeout,
pollingInterval: pollingInterval
}) : undefined;
return {
url: rpcConfig.url,
sourceFor: parseRpcSourceFor(rpcConfig.for),
syncConfig: syncConfig,
ws: rpcConfig.ws
};
});
sourceConfig = {
TAG: "EvmSourceConfig",
hypersync: publicChainConfig.hypersync,
rpcs: rpcs
};
break;
case "fuel" :
let hypersync = publicChainConfig.hypersync;
sourceConfig = hypersync !== undefined ? ({
TAG: "FuelSourceConfig",
hypersync: hypersync
}) : Stdlib_JsError.throwWithMessage(`Chain ` + chainName + ` is missing hypersync endpoint in config`);
break;
case "svm" :
let hypersync$1 = publicChainConfig.hypersync;
let rpc = publicChainConfig.rpc;
if (Stdlib_Option.isNone(hypersync$1) && Stdlib_Option.isNone(rpc)) {
Stdlib_JsError.throwWithMessage(`Chain ` + chainName + ` is missing a data source: provide either an rpc endpoint or an experimental hypersync config`);
}
sourceConfig = {
TAG: "SvmSourceConfig",
hypersync: hypersync$1,
rpc: rpc
};
break;
}
let tmp;
switch (ecosystemName) {
case "evm" :
tmp = Stdlib_Option.getOr(publicChainConfig.maxReorgDepth, 200);
break;
case "fuel" :
case "svm" :
tmp = 0;
break;
}
return {
name: chainName,
id: chainId,
startBlock: publicChainConfig.startBlock,
endBlock: publicChainConfig.endBlock,
maxReorgDepth: tmp,
blockLag: Stdlib_Option.getOr(publicChainConfig.blockLag, 0),
contracts: contracts,
sourceConfig: sourceConfig
};
});
let chainMap = ChainMap.fromArrayUnsafe(chains.map(chain => [
ChainMap.Chain.makeUnsafe(chain.id),
chain
]));
let allEnums = parseEnumsFromJson(Stdlib_Option.getOr(publicConfig.enums, {}));
let enumConfigsByName = Object.fromEntries(allEnums.map(enumConfig => [
enumConfig.name,
enumConfig
]));
let globalStorage_postgres = publicConfig.storage.postgres;
let globalStorage_clickhouse = Stdlib_Option.getOr(publicConfig.storage.clickhouse, false);
let globalStorage = {
postgres: globalStorage_postgres,
clickhouse: globalStorage_clickhouse
};
let userEntities = parseEntitiesFromJson(Stdlib_Option.getOr(publicConfig.entities, []), enumConfigsByName, globalStorage);
let allEntities = userEntities.concat([entityConfig]);
let userEntitiesByName = Object.fromEntries(userEntities.map(entityConfig => [
entityConfig.name,
entityConfig
]));
let contractHandlers = publicContractsConfig !== undefined ? Object.entries(publicContractsConfig).map(param => ({
name: Utils.$$String.capitalize(param[0]),
handler: param[1].handler
})) : [];
return {
name: publicConfig.name,
description: publicConfig.description,
handlers: Stdlib_Option.getOr(publicConfig.handlers, "src/handlers"),
contractHandlers: contractHandlers,
shouldRollbackOnReorg: Stdlib_Option.getOr(publicConfig.rollbackOnReorg, true),
shouldSaveFullHistory: Stdlib_Option.getOr(publicConfig.saveFullHistory, false),
storage: globalStorage,
chainMap: chainMap,
defaultChain: chains[0],
ecosystem: ecosystem,
enableRawEvents: Stdlib_Option.getOr(publicConfig.rawEvents, false),
maxAddrInPartition: Env.maxAddrInPartition,
batchSize: Stdlib_Option.getOr(publicConfig.fullBatchSize, 5000),
lowercaseAddresses: lowercaseAddresses,
isDev: Stdlib_Option.getOr(publicConfig.isDev, false),
userEntitiesByName: userEntitiesByName,
userEntities: userEntities,
allEntities: allEntities,
allEnums: allEnums
};
}
function getEventConfig(config, contractName, eventName, chainId) {
let chains;
if (chainId !== undefined) {
let chain = ChainMap.Chain.makeUnsafe(chainId);
let exit = 0;
let chainConfig;
try {
chainConfig = ChainMap.get(config.chainMap, chain);
exit = 1;
} catch (exn) {
chains = Stdlib_JsError.throwWithMessage(`Chain ` + chainId.toString() + ` is not configured. Add it to config.yaml or pass a configured chain.`);
}
if (exit === 1) {
chains = [chainConfig];
}
} else {
chains = ChainMap.values(config.chainMap);
}
return Stdlib_Array.reduce(chains, undefined, (acc, chain) => {
if (acc !== undefined) {
return acc;
} else {
return Stdlib_Option.flatMap(chain.contracts.find(c => c.name === contractName), contract => contract.events.find(e => e.name === eventName));
}
});
}
function shouldSaveHistory(config, isInReorgThreshold) {
if (config.shouldSaveFullHistory) {
return true;
} else if (config.shouldRollbackOnReorg) {
return isInReorgThreshold;
} else {
return false;
}
}
function shouldPruneHistory(config, isInReorgThreshold) {
if (!config.shouldSaveFullHistory && config.shouldRollbackOnReorg) {
return isInReorgThreshold;
} else {
return false;
}
}
function getChain(config, chainId) {
let chain = ChainMap.Chain.makeUnsafe(chainId);
if (ChainMap.has(config.chainMap, chain)) {
return chain;
} else {
return Stdlib_JsError.throwWithMessage("No chain with id " + ChainMap.Chain.toString(chain) + " found in config.yaml");
}
}
let primedJson = {
contents: undefined
};
let cached = {
contents: undefined
};
function prime(json) {
primedJson.contents = json;
cached.contents = undefined;
}
function getPublicConfigJson() {
let json = primedJson.contents;
if (json !== undefined) {
return json;
} else {
return JSON.parse(Core.getConfigJson(undefined, undefined));
}
}
function stripSensitiveData(json) {
let cloned = JSON.parse(JSON.stringify(json));
let stripChains = ecosystem => {
if (ecosystem === undefined) {
return;
}
if (typeof ecosystem !== "object" || ecosystem === null || Array.isArray(ecosystem)) {
return;
}
let match = ecosystem["chains"];
if (match === undefined) {
return;
}
if (typeof match !== "object" || match === null || Array.isArray(match)) {
return;
}
Object.values(match).forEach(chainJson => {
if (typeof chainJson !== "object" || chainJson === null || Array.isArray(chainJson)) {
return;
}
Utils.Dict.deleteInPlace(chainJson, "rpcs");
Utils.Dict.deleteInPlace(chainJson, "rpc");
Utils.Dict.deleteInPlace(chainJson, "hypersync");
});
};
if (typeof cloned === "object" && cloned !== null && !Array.isArray(cloned)) {
Utils.Dict.deleteInPlace(cloned, "isDev");
stripChains(cloned["evm"]);
stripChains(cloned["fuel"]);
stripChains(cloned["svm"]);
}
return cloned;
}
function canonicalJson(json) {
if (Array.isArray(json)) {
return json.map(canonicalJson);
}
if (json === null) {
return json;
}
switch (typeof json) {
case "object" :
let sorted = {};
Object.keys(json).toSorted(Primitive_string.compare).forEach(k => {
sorted[k] = canonicalJson(json[k]);
});
return sorted;
default:
return json;
}
}
function diffPaths(stored, current) {
let canonEq = (a, b) => JSON.stringify(canonicalJson(a)) === JSON.stringify(canonicalJson(b));
let acc = [];
let go = (s, c, prefix) => {
if (canonEq(s, c)) {
return;
}
if (Array.isArray(s)) {
if (Array.isArray(c)) {
let maxLen = Math.max(s.length, c.length);
for (let i = 0; i < maxLen; ++i) {
let p = prefix + `[` + i.toString() + `]`;
let match = s[i];
let match$1 = c[i];
if (match !== undefined && match$1 !== undefined) {
go(match, match$1, p);
} else {
acc.push(p);
}
}
return;
}
} else {
switch (typeof s) {
case "object" :
if (typeof c === "object" && c !== null && !Array.isArray(c)) {
let keys = new Set(Object.keys(s).concat(Object.keys(c)));
Array.from(keys).toSorted(Primitive_string.compare).forEach(k => {
let p = prefix === "" ? k : prefix + `.` + k;
let match = s[k];
let match$1 = c[k];
if (match !== undefined) {
if (match$1 !== undefined) {
return go(match, match$1, p);
} else {
acc.push(p);
return;
}
} else if (match$1 !== undefined) {
acc.push(p);
return;
} else {
return;
}
});
return;
}
break;
}
}
acc.push(prefix === "" ? "<root>" : prefix);
};
let getTopKey = (j, k) => {
if (typeof j === "object" && j !== null && !Array.isArray(j)) {
return j[k];
}
};
let topKeyDiffers = k => {
let match = getTopKey(stored, k);
let match$1 = getTopKey(current, k);
if (match !== undefined) {
if (match$1 !== undefined) {
return !canonEq(match, match$1);
} else {
return true;
}
} else {
return match$1 !== undefined;
}
};
let runTier = keys => {
keys.forEach(k => {
let match = getTopKey(stored, k);
let match$1 = getTopKey(current, k);
if (match !== undefined) {
if (match$1 !== undefined) {
return go(match, match$1, k);
} else {
acc.push(k);
return;
}
} else if (match$1 !== undefined) {
acc.push(k);
return;
} else {
return;
}
});
};
if (typeof stored === "object" && stored !== null && !Array.isArray(stored) && typeof current === "object" && current !== null && !Array.isArray(current)) {
let tiers = [
["version"],
["name"],
["storage"],
[
"evm",
"fuel",
"svm"
],
["entities"]
];
let firstHit = Stdlib_Array.reduce(tiers, undefined, (acc, tier) => {
if (acc !== undefined) {
return acc;
}
let hits = tier.filter(topKeyDiffers);
if (hits.length !== 0) {
return hits;
}
});
if (firstHit !== undefined) {
runTier(firstHit);
} else {
let knownSet = new Set(tiers.flat());
runTier(Array.from(new Set(Object.keys(stored).concat(Object.keys(current)))).filter(k => !knownSet.has(k)).toSorted(Primitive_string.compare).filter(topKeyDiffers));
}
} else {
go(stored, current, "");
}
return acc;
}
function throwIfIncompatible(changedPaths, resetCommand, runCommand, hasClickhouse) {
if (changedPaths.length === 0) {
return;
}
let bullets = changedPaths.map(p => ` - ` + p).join("\n");
let option1 = "Revert the changes above";
let padTo = (s, col) => s + " ".repeat(Math.max(col - s.length | 0, 1));
let col = Math.max(option1.length, resetCommand.length) + 2 | 0;
let option3;
if (runCommand !== undefined) {
let clickhouseLine = hasClickhouse ? " ENVIO_CLICKHOUSE_DATABASE=<new_db> \\\n" : "";
option3 = `\n 3. Run a second indexer alongside this one — keep both datasets:\n ENVIO_PG_SCHEMA=<new_schema> \\\n` + clickhouseLine + ` ENVIO_INDEXER_PORT=<new_port> \\\n ` + runCommand;
} else {
option3 = "";
}
Stdlib_JsError.throwWithMessage(`The following config changes are incompatible with the existing indexer data:\n\n` + bullets + `\n\nPick one:\n 1. ` + padTo(option1, col) + `# resume indexing where it left off\n 2. ` + padTo(resetCommand, col) + `# delete all indexed data and start over` + option3);
}
function loadWithoutRegistrations() {
let c = cached.contents;
if (c !== undefined) {
return c;
}
let c$1 = fromPublic(getPublicConfigJson());
cached.contents = c$1;
return c$1;
}
function getPgUserEntities(config) {
return config.userEntities.filter(e => e.storage.postgres);
}
export {
EnvioAddresses,
rpcSourceForSchema,
rpcConfigSchema,
chainContractSchema,
publicConfigChainSchema,
svmEventDescriptorSchema,
svmAbiSchema,
contractEventItemSchema,
contractConfigSchema,
publicConfigEcosystemSchema,
publicConfigEvmSchema,
compositeIndexFieldSchema,
derivedFieldSchema,
propertySchema,
entityStorageSchema,
entityJsonSchema,
getFieldTypeAndSchema,
parseEnumsFromJson,
parseEntitiesFromJson,
publicConfigStorageSchema,
publicConfigSchema,
fromPublic,
getEventConfig,
shouldSaveHistory,
shouldPruneHistory,
getChain,
prime,
getPublicConfigJson,
stripSensitiveData,
canonicalJson,
diffPaths,
throwIfIncompatible,
loadWithoutRegistrations,
getPgUserEntities,
}
/* schema Not a pure module */