UNPKG

envio

Version:

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

331 lines (314 loc) 11.2 kB
// Generated by ReScript, PLEASE EDIT WITH CARE import * as Utils from "./Utils.res.mjs"; 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 S$RescriptSchema from "rescript-schema/src/S.res.mjs"; import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js"; let MissingRequiredTopic0 = /* @__PURE__ */Primitive_exceptions.create("LogSelection.MissingRequiredTopic0"); function makeTopicSelection(topic0, topic1Opt, topic2Opt, topic3Opt) { let topic1 = topic1Opt !== undefined ? topic1Opt : []; let topic2 = topic2Opt !== undefined ? topic2Opt : []; let topic3 = topic3Opt !== undefined ? topic3Opt : []; if (Utils.$$Array.isEmpty(topic0)) { return { TAG: "Error", _0: { RE_EXN_ID: MissingRequiredTopic0 } }; } else { return { TAG: "Ok", _0: { topic0: topic0, topic1: topic1, topic2: topic2, topic3: topic3 } }; } } function hasFilters(param) { return Stdlib_Option.isSome([ param.topic1, param.topic2, param.topic3 ].find(topic => !Utils.$$Array.isEmpty(topic))); } function compressTopicSelections(topicSelections) { let topic0sOfSelectionsWithoutFilters = []; let selectionsWithFilters = []; topicSelections.forEach(selection => { if (hasFilters(selection)) { selectionsWithFilters.push(selection); } else { selection.topic0.forEach(topic0 => { topic0sOfSelectionsWithoutFilters.push(topic0); }); } }); if (topic0sOfSelectionsWithoutFilters.length === 0) { return selectionsWithFilters; } let selectionWithoutFilters_topic1 = []; let selectionWithoutFilters_topic2 = []; let selectionWithoutFilters_topic3 = []; let selectionWithoutFilters = { topic0: topic0sOfSelectionsWithoutFilters, topic1: selectionWithoutFilters_topic1, topic2: selectionWithoutFilters_topic2, topic3: selectionWithoutFilters_topic3 }; return [selectionWithoutFilters].concat(selectionsWithFilters); } function make(addresses, topicSelections) { let topicSelections$1 = compressTopicSelections(topicSelections); return { addresses: addresses, topicSelections: topicSelections$1 }; } let eventBlockRangeSchema = S$RescriptSchema.strict(S$RescriptSchema.object(s => ({ _gte: s.f("_gte", S$RescriptSchema.option(S$RescriptSchema.int)) }))); function extractStartBlock(where, onEventBlockFilterSchema, contractName) { if (typeof where === "boolean") { return; } try { let inner = S$RescriptSchema.parseOrThrow(where, onEventBlockFilterSchema); if (inner !== undefined) { return S$RescriptSchema.parseOrThrow(Primitive_option.valFromOption(inner), eventBlockRangeSchema)._gte; } else { return; } } catch (raw_exn) { let exn = Primitive_exceptions.internalToException(raw_exn); if (exn.RE_EXN_ID === S$RescriptSchema.Raised) { return Stdlib_JsError.throwWithMessage(`Invalid where configuration for ` + contractName + `. \`block\` filter is invalid: ` + Utils.prettifyExn(exn._1) + `. Only \`_gte\` is supported on event filters — use \`indexer.onBlock\` for \`_lte\` or \`_every\`.`); } throw exn; } } function makeChainArg(contractName, chainId, addresses) { let chainObj = {}; chainObj["id"] = chainId; chainObj[contractName] = { addresses: addresses }; return chainObj; } function makeDetectionChainArg(contractName, chainId, getAddresses) { let contractObj = Object.create(null); Object.defineProperty(contractObj, "addresses", { enumerable: true, get: getAddresses }); let chainObj = {}; chainObj["id"] = chainId; chainObj[contractName] = contractObj; return chainObj; } let makeAddressesProbe = (function (contractName) { var trap = function () { throw new Error( 'Invalid where configuration for "' + contractName + '": chain.' + contractName + '.addresses must be passed directly as an indexed-param ' + 'filter value (e.g. { params: { to: chain.' + contractName + '.addresses } }). ' + 'It cannot be spread, mapped, indexed, or otherwise transformed.' ); }; return new Proxy([], {get: trap}); }); function extractAddressFilterGroupsOrThrow(result, probe, contractName) { let groups = []; let scanGroup = paramsObj => { let names = []; Utils.Dict.forEachWithKey(paramsObj, (value, key) => { if (value === probe) { names.push(key); paramsObj[key] = []; return; } }); if (!Utils.$$Array.isEmpty(names)) { groups.push(names); return; } }; if (typeof result === "object" && result !== null && !Array.isArray(result)) { let match = result["params"]; if (match !== undefined) { if (Array.isArray(match)) { match.forEach(item => { if (typeof item === "object" && item !== null && !Array.isArray(item)) { return scanGroup(item); } }); } else { switch (typeof match) { case "object" : scanGroup(match); break; } } } } if (Utils.$$Array.isEmpty(groups)) { Stdlib_JsError.throwWithMessage(`Invalid where configuration for ` + contractName + `. The callback reads \`chain.` + contractName + `.addresses\` but doesn't use it as an indexed-param filter value. Use it directly, e.g. { params: { to: chain.` + contractName + `.addresses } }.`); } return groups; } let emptyTopics = []; function noopGetter(param) { return emptyTopics; } function parseEventFiltersOrThrow(eventFilters, sighash, params, contractName, probeChainId, onEventBlockFilterSchema, topic1Opt, topic2Opt, topic3Opt) { let topic1 = topic1Opt !== undefined ? topic1Opt : noopGetter; let topic2 = topic2Opt !== undefined ? topic2Opt : noopGetter; let topic3 = topic3Opt !== undefined ? topic3Opt : noopGetter; let filterByAddresses = { contents: false }; let addressFilterParamGroups = []; let startBlock; let topic0 = [sighash]; let $$default = { topic0: topic0, topic1: emptyTopics, topic2: emptyTopics, topic3: emptyTopics }; let paramsRecordToTopicSelection = paramsFilter => { if (Utils.Dict.isEmpty(paramsFilter)) { return $$default; } else { Utils.Dict.forEachWithKey(paramsFilter, (param, key) => { if (!params.includes(key)) { return Stdlib_JsError.throwWithMessage(`Invalid where configuration. The event doesn't have an indexed parameter "` + key + `" and can't use it for filtering`); } }); return { topic0: topic0, topic1: topic1(paramsFilter), topic2: topic2(paramsFilter), topic3: topic3(paramsFilter) }; } }; let acceptedWhereKeys = [ "params", "block" ]; let parse = where => { if (where === true) { return [$$default]; } if (where === false) { return []; } if (typeof where !== "object" || where === null || Array.isArray(where)) { return Stdlib_JsError.throwWithMessage("Invalid where configuration. Expected an object"); } Utils.Dict.forEachWithKey(where, (param, key) => { if (!acceptedWhereKeys.includes(key)) { return Stdlib_JsError.throwWithMessage(`Invalid where configuration. Unknown field "` + key + `". Indexed parameter filters must be nested under \`params\` and block-range filters under \`block\``); } }); let match = where["params"]; if (match === undefined) { return [$$default]; } if (Array.isArray(match)) { if (match.length !== 0) { return match.map(item => { if (typeof item === "object" && item !== null && !Array.isArray(item)) { return paramsRecordToTopicSelection(item); } else { return Stdlib_JsError.throwWithMessage("Invalid where configuration. Each entry in `params` must be an object"); } }); } else { return [$$default]; } } if (match === null) { return Stdlib_JsError.throwWithMessage("Invalid where configuration. Expected `params` to be an object or an array of objects"); } switch (typeof match) { case "object" : return [paramsRecordToTopicSelection(match)]; default: return Stdlib_JsError.throwWithMessage("Invalid where configuration. Expected `params` to be an object or an array of objects"); } }; let getEventFiltersOrThrow; if (eventFilters !== undefined) { if (typeof eventFilters === "function") { let addressesProbe = makeAddressesProbe(contractName); let chain = makeDetectionChainArg(contractName, probeChainId, () => { filterByAddresses.contents = true; return addressesProbe; }); let probedResult = eventFilters({ chain: chain }); if (filterByAddresses.contents) { addressFilterParamGroups = extractAddressFilterGroupsOrThrow(probedResult, addressesProbe, contractName); } startBlock = extractStartBlock(probedResult, onEventBlockFilterSchema, contractName); getEventFiltersOrThrow = filterByAddresses.contents ? chain => ({ TAG: "Dynamic", _0: addresses => { let chainArg = makeChainArg(contractName, chain, addresses); return parse(eventFilters({ chain: chainArg })); } }) : chain => { let chainArg = makeDetectionChainArg(contractName, chain, () => Stdlib_JsError.throwWithMessage(`Invalid where configuration. Event callback for contract "` + contractName + `" read \`chain.` + contractName + `.addresses\` at runtime but the probe didn't detect the access on chainId ` + chain.toString() + `. Move the \`chain.` + contractName + `.addresses\` read above any \`chain.id\` branching so the probe picks up the dependency and switches to the dynamic fetch path.`)); return { TAG: "Static", _0: parse(eventFilters({ chain: chainArg })) }; }; } else { startBlock = extractStartBlock(eventFilters, onEventBlockFilterSchema, contractName); let $$static = { TAG: "Static", _0: parse(eventFilters) }; getEventFiltersOrThrow = param => $$static; } } else { let $$static$1 = { TAG: "Static", _0: [$$default] }; getEventFiltersOrThrow = param => $$static$1; } return { getEventFiltersOrThrow: getEventFiltersOrThrow, filterByAddresses: filterByAddresses.contents, addressFilterParamGroups: addressFilterParamGroups, startBlock: startBlock }; } export { MissingRequiredTopic0, makeTopicSelection, hasFilters, compressTopicSelections, make, eventBlockRangeSchema, extractStartBlock, makeChainArg, makeDetectionChainArg, makeAddressesProbe, extractAddressFilterGroupsOrThrow, parseEventFiltersOrThrow, } /* eventBlockRangeSchema Not a pure module */