envio 2.28.0-rc.0 → 2.28.0
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.
- package/package.json +6 -6
- package/src/InternalConfig.res +10 -0
- package/src/sources/EventRouter.res +113 -0
- package/src/sources/EventRouter.res.js +125 -0
- package/src/sources/HyperSync.res +15 -7
- package/src/sources/HyperSync.res.js +48 -15
- package/src/sources/HyperSyncClient.res +4 -3
- package/src/sources/HyperSyncClient.res.js +6 -1
- package/src/sources/RpcSource.res +748 -0
- package/src/sources/RpcSource.res.js +697 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "envio",
|
|
3
|
-
"version": "v2.28.0
|
|
3
|
+
"version": "v2.28.0",
|
|
4
4
|
"description": "A latency and sync speed optimized, developer friendly blockchain data indexer.",
|
|
5
5
|
"bin": "./bin.js",
|
|
6
6
|
"main": "./index.js",
|
|
@@ -25,13 +25,13 @@
|
|
|
25
25
|
},
|
|
26
26
|
"homepage": "https://envio.dev",
|
|
27
27
|
"optionalDependencies": {
|
|
28
|
-
"envio-linux-x64": "v2.28.0
|
|
29
|
-
"envio-linux-arm64": "v2.28.0
|
|
30
|
-
"envio-darwin-x64": "v2.28.0
|
|
31
|
-
"envio-darwin-arm64": "v2.28.0
|
|
28
|
+
"envio-linux-x64": "v2.28.0",
|
|
29
|
+
"envio-linux-arm64": "v2.28.0",
|
|
30
|
+
"envio-darwin-x64": "v2.28.0",
|
|
31
|
+
"envio-darwin-arm64": "v2.28.0"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@envio-dev/hypersync-client": "0.6.
|
|
34
|
+
"@envio-dev/hypersync-client": "0.6.6",
|
|
35
35
|
"rescript": "11.1.3",
|
|
36
36
|
"rescript-schema": "9.3.0",
|
|
37
37
|
"viem": "2.21.0",
|
package/src/InternalConfig.res
CHANGED
|
@@ -18,3 +18,13 @@ type chain = {
|
|
|
18
18
|
contracts: array<contract>,
|
|
19
19
|
sources: array<Source.t>,
|
|
20
20
|
}
|
|
21
|
+
|
|
22
|
+
type sourceSync = {
|
|
23
|
+
initialBlockInterval: int,
|
|
24
|
+
backoffMultiplicative: float,
|
|
25
|
+
accelerationAdditive: int,
|
|
26
|
+
intervalCeiling: int,
|
|
27
|
+
backoffMillis: int,
|
|
28
|
+
queryTimeoutMillis: int,
|
|
29
|
+
fallbackStallTimeout: int,
|
|
30
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
open Belt
|
|
2
|
+
|
|
3
|
+
exception EventDuplicate
|
|
4
|
+
exception WildcardCollision
|
|
5
|
+
|
|
6
|
+
module Group = {
|
|
7
|
+
type t<'a> = {
|
|
8
|
+
mutable wildcard: option<'a>,
|
|
9
|
+
byContractName: dict<'a>,
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let empty = () => {
|
|
13
|
+
wildcard: None,
|
|
14
|
+
byContractName: Js.Dict.empty(),
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let addOrThrow = (group: t<'a>, event, ~contractName, ~isWildcard) => {
|
|
18
|
+
let {byContractName, wildcard} = group
|
|
19
|
+
switch byContractName->Utils.Dict.dangerouslyGetNonOption(contractName) {
|
|
20
|
+
| Some(_) => raise(EventDuplicate)
|
|
21
|
+
| None =>
|
|
22
|
+
if isWildcard && wildcard->Option.isSome {
|
|
23
|
+
raise(WildcardCollision)
|
|
24
|
+
} else {
|
|
25
|
+
if isWildcard {
|
|
26
|
+
group.wildcard = Some(event)
|
|
27
|
+
}
|
|
28
|
+
byContractName->Js.Dict.set(contractName, event)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
let get = (
|
|
34
|
+
group: t<'a>,
|
|
35
|
+
~contractAddress,
|
|
36
|
+
~blockNumber,
|
|
37
|
+
~indexingContracts: dict<FetchState.indexingContract>,
|
|
38
|
+
) =>
|
|
39
|
+
switch group {
|
|
40
|
+
| {wildcard, byContractName} =>
|
|
41
|
+
switch indexingContracts->Utils.Dict.dangerouslyGetNonOption(
|
|
42
|
+
contractAddress->Address.toString,
|
|
43
|
+
) {
|
|
44
|
+
| Some(indexingContract) =>
|
|
45
|
+
if indexingContract.startBlock <= blockNumber {
|
|
46
|
+
byContractName->Utils.Dict.dangerouslyGetNonOption(indexingContract.contractName)
|
|
47
|
+
} else {
|
|
48
|
+
None
|
|
49
|
+
}
|
|
50
|
+
| None => wildcard
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
type t<'a> = dict<Group.t<'a>>
|
|
56
|
+
|
|
57
|
+
let empty = () => Js.Dict.empty()
|
|
58
|
+
|
|
59
|
+
let addOrThrow = (
|
|
60
|
+
router: t<'a>,
|
|
61
|
+
eventId,
|
|
62
|
+
event,
|
|
63
|
+
~contractName,
|
|
64
|
+
~isWildcard,
|
|
65
|
+
~eventName,
|
|
66
|
+
~chain,
|
|
67
|
+
) => {
|
|
68
|
+
let group = switch router->Utils.Dict.dangerouslyGetNonOption(eventId) {
|
|
69
|
+
| None =>
|
|
70
|
+
let group = Group.empty()
|
|
71
|
+
router->Js.Dict.set(eventId, group)
|
|
72
|
+
group
|
|
73
|
+
| Some(group) => group
|
|
74
|
+
}
|
|
75
|
+
try group->Group.addOrThrow(event, ~contractName, ~isWildcard) catch {
|
|
76
|
+
| EventDuplicate =>
|
|
77
|
+
Js.Exn.raiseError(
|
|
78
|
+
`Duplicate event detected: ${eventName} for contract ${contractName} on chain ${chain->ChainMap.Chain.toString}`,
|
|
79
|
+
)
|
|
80
|
+
| WildcardCollision =>
|
|
81
|
+
Js.Exn.raiseError(
|
|
82
|
+
`Another event is already registered with the same signature that would interfer with wildcard filtering: ${eventName} for contract ${contractName} on chain ${chain->ChainMap.Chain.toString}`,
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
let get = (router: t<'a>, ~tag, ~contractAddress, ~blockNumber, ~indexingContracts) => {
|
|
88
|
+
switch router->Utils.Dict.dangerouslyGetNonOption(tag) {
|
|
89
|
+
| None => None
|
|
90
|
+
| Some(group) => group->Group.get(~contractAddress, ~blockNumber, ~indexingContracts)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
let getEvmEventId = (~sighash, ~topicCount) => {
|
|
95
|
+
sighash ++ "_" ++ topicCount->Belt.Int.toString
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
let fromEvmEventModsOrThrow = (events: array<Internal.evmEventConfig>, ~chain): t<
|
|
99
|
+
Internal.evmEventConfig,
|
|
100
|
+
> => {
|
|
101
|
+
let router = empty()
|
|
102
|
+
events->Belt.Array.forEach(config => {
|
|
103
|
+
router->addOrThrow(
|
|
104
|
+
config.id,
|
|
105
|
+
config,
|
|
106
|
+
~contractName=config.contractName,
|
|
107
|
+
~eventName=config.name,
|
|
108
|
+
~chain,
|
|
109
|
+
~isWildcard=config.isWildcard,
|
|
110
|
+
)
|
|
111
|
+
})
|
|
112
|
+
router
|
|
113
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var Js_exn = require("rescript/lib/js/js_exn.js");
|
|
5
|
+
var ChainMap = require("../ChainMap.res.js");
|
|
6
|
+
var Belt_Array = require("rescript/lib/js/belt_Array.js");
|
|
7
|
+
var Belt_Option = require("rescript/lib/js/belt_Option.js");
|
|
8
|
+
var Caml_option = require("rescript/lib/js/caml_option.js");
|
|
9
|
+
var Caml_exceptions = require("rescript/lib/js/caml_exceptions.js");
|
|
10
|
+
var Caml_js_exceptions = require("rescript/lib/js/caml_js_exceptions.js");
|
|
11
|
+
|
|
12
|
+
var EventDuplicate = /* @__PURE__ */Caml_exceptions.create("EventRouter.EventDuplicate");
|
|
13
|
+
|
|
14
|
+
var WildcardCollision = /* @__PURE__ */Caml_exceptions.create("EventRouter.WildcardCollision");
|
|
15
|
+
|
|
16
|
+
function empty() {
|
|
17
|
+
return {
|
|
18
|
+
wildcard: undefined,
|
|
19
|
+
byContractName: {}
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function addOrThrow(group, $$event, contractName, isWildcard) {
|
|
24
|
+
var wildcard = group.wildcard;
|
|
25
|
+
var byContractName = group.byContractName;
|
|
26
|
+
var match = byContractName[contractName];
|
|
27
|
+
if (match !== undefined) {
|
|
28
|
+
throw {
|
|
29
|
+
RE_EXN_ID: EventDuplicate,
|
|
30
|
+
Error: new Error()
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
if (isWildcard && Belt_Option.isSome(wildcard)) {
|
|
34
|
+
throw {
|
|
35
|
+
RE_EXN_ID: WildcardCollision,
|
|
36
|
+
Error: new Error()
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
if (isWildcard) {
|
|
40
|
+
group.wildcard = Caml_option.some($$event);
|
|
41
|
+
}
|
|
42
|
+
byContractName[contractName] = $$event;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function get(group, contractAddress, blockNumber, indexingContracts) {
|
|
46
|
+
var wildcard = group.wildcard;
|
|
47
|
+
var indexingContract = indexingContracts[contractAddress];
|
|
48
|
+
if (indexingContract !== undefined) {
|
|
49
|
+
if (indexingContract.startBlock <= blockNumber) {
|
|
50
|
+
return group.byContractName[indexingContract.contractName];
|
|
51
|
+
} else {
|
|
52
|
+
return ;
|
|
53
|
+
}
|
|
54
|
+
} else {
|
|
55
|
+
return wildcard;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
var Group = {
|
|
60
|
+
empty: empty,
|
|
61
|
+
addOrThrow: addOrThrow,
|
|
62
|
+
get: get
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
function empty$1() {
|
|
66
|
+
return {};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function addOrThrow$1(router, eventId, $$event, contractName, isWildcard, eventName, chain) {
|
|
70
|
+
var group = router[eventId];
|
|
71
|
+
var group$1;
|
|
72
|
+
if (group !== undefined) {
|
|
73
|
+
group$1 = group;
|
|
74
|
+
} else {
|
|
75
|
+
var group$2 = {
|
|
76
|
+
wildcard: undefined,
|
|
77
|
+
byContractName: {}
|
|
78
|
+
};
|
|
79
|
+
router[eventId] = group$2;
|
|
80
|
+
group$1 = group$2;
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
return addOrThrow(group$1, $$event, contractName, isWildcard);
|
|
84
|
+
}
|
|
85
|
+
catch (raw_exn){
|
|
86
|
+
var exn = Caml_js_exceptions.internalToOCamlException(raw_exn);
|
|
87
|
+
if (exn.RE_EXN_ID === EventDuplicate) {
|
|
88
|
+
return Js_exn.raiseError("Duplicate event detected: " + eventName + " for contract " + contractName + " on chain " + ChainMap.Chain.toString(chain));
|
|
89
|
+
}
|
|
90
|
+
if (exn.RE_EXN_ID === WildcardCollision) {
|
|
91
|
+
return Js_exn.raiseError("Another event is already registered with the same signature that would interfer with wildcard filtering: " + eventName + " for contract " + contractName + " on chain " + ChainMap.Chain.toString(chain));
|
|
92
|
+
}
|
|
93
|
+
throw exn;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function get$1(router, tag, contractAddress, blockNumber, indexingContracts) {
|
|
98
|
+
var group = router[tag];
|
|
99
|
+
if (group !== undefined) {
|
|
100
|
+
return get(group, contractAddress, blockNumber, indexingContracts);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function getEvmEventId(sighash, topicCount) {
|
|
106
|
+
return sighash + "_" + String(topicCount);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function fromEvmEventModsOrThrow(events, chain) {
|
|
110
|
+
var router = {};
|
|
111
|
+
Belt_Array.forEach(events, (function (config) {
|
|
112
|
+
addOrThrow$1(router, config.id, config, config.contractName, config.isWildcard, config.name, chain);
|
|
113
|
+
}));
|
|
114
|
+
return router;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
exports.EventDuplicate = EventDuplicate;
|
|
118
|
+
exports.WildcardCollision = WildcardCollision;
|
|
119
|
+
exports.Group = Group;
|
|
120
|
+
exports.empty = empty$1;
|
|
121
|
+
exports.addOrThrow = addOrThrow$1;
|
|
122
|
+
exports.get = get$1;
|
|
123
|
+
exports.getEvmEventId = getEvmEventId;
|
|
124
|
+
exports.fromEvmEventModsOrThrow = fromEvmEventModsOrThrow;
|
|
125
|
+
/* ChainMap Not a pure module */
|
|
@@ -76,15 +76,23 @@ module GetLogs = {
|
|
|
76
76
|
fieldSelection,
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
+
@inline
|
|
79
80
|
let addMissingParams = (acc, fieldNames, returnedObj, ~prefix) => {
|
|
80
|
-
fieldNames->Array.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
81
|
+
if fieldNames->Utils.Array.notEmpty {
|
|
82
|
+
if !(returnedObj->Obj.magic) {
|
|
83
|
+
acc->Array.push(prefix)->ignore
|
|
84
|
+
} else {
|
|
85
|
+
for idx in 0 to fieldNames->Array.length - 1 {
|
|
86
|
+
let fieldName = fieldNames->Array.getUnsafe(idx)
|
|
87
|
+
switch returnedObj
|
|
88
|
+
->(Utils.magic: 'a => Js.Dict.t<unknown>)
|
|
89
|
+
->Utils.Dict.dangerouslyGetNonOption(fieldName) {
|
|
90
|
+
| Some(_) => ()
|
|
91
|
+
| None => acc->Array.push(prefix ++ "." ++ fieldName)->ignore
|
|
92
|
+
}
|
|
93
|
+
}
|
|
86
94
|
}
|
|
87
|
-
}
|
|
95
|
+
}
|
|
88
96
|
}
|
|
89
97
|
|
|
90
98
|
//Note this function can throw an error
|
|
@@ -57,18 +57,6 @@ function makeRequestBody(fromBlock, toBlockInclusive, addressesWithTopics, field
|
|
|
57
57
|
};
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
function addMissingParams(acc, fieldNames, returnedObj, prefix) {
|
|
61
|
-
Belt_Array.forEach(fieldNames, (function (fieldName) {
|
|
62
|
-
var match = returnedObj[fieldName];
|
|
63
|
-
if (match !== undefined) {
|
|
64
|
-
return ;
|
|
65
|
-
} else {
|
|
66
|
-
acc.push(prefix + "." + fieldName);
|
|
67
|
-
return ;
|
|
68
|
-
}
|
|
69
|
-
}));
|
|
70
|
-
}
|
|
71
|
-
|
|
72
60
|
async function query(client, fromBlock, toBlock, logSelections, fieldSelection, nonOptionalBlockFieldNames, nonOptionalTransactionFieldNames) {
|
|
73
61
|
var addressesWithTopics = Belt_Array.flatMap(logSelections, (function (param) {
|
|
74
62
|
var addresses = param.addresses;
|
|
@@ -88,9 +76,54 @@ async function query(client, fromBlock, toBlock, logSelections, fieldSelection,
|
|
|
88
76
|
}
|
|
89
77
|
var items = Belt_Array.map(res.data, (function (item) {
|
|
90
78
|
var missingParams = [];
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
79
|
+
var returnedObj = item.log;
|
|
80
|
+
if (Utils.$$Array.notEmpty(fieldNames)) {
|
|
81
|
+
if (returnedObj) {
|
|
82
|
+
for(var idx = 0 ,idx_finish = fieldNames.length; idx < idx_finish; ++idx){
|
|
83
|
+
var fieldName = fieldNames[idx];
|
|
84
|
+
var match = returnedObj[fieldName];
|
|
85
|
+
if (match !== undefined) {
|
|
86
|
+
|
|
87
|
+
} else {
|
|
88
|
+
missingParams.push("log." + fieldName);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
} else {
|
|
92
|
+
missingParams.push("log");
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
var returnedObj$1 = item.block;
|
|
96
|
+
if (Utils.$$Array.notEmpty(nonOptionalBlockFieldNames)) {
|
|
97
|
+
if (returnedObj$1) {
|
|
98
|
+
for(var idx$1 = 0 ,idx_finish$1 = nonOptionalBlockFieldNames.length; idx$1 < idx_finish$1; ++idx$1){
|
|
99
|
+
var fieldName$1 = nonOptionalBlockFieldNames[idx$1];
|
|
100
|
+
var match$1 = returnedObj$1[fieldName$1];
|
|
101
|
+
if (match$1 !== undefined) {
|
|
102
|
+
|
|
103
|
+
} else {
|
|
104
|
+
missingParams.push("block." + fieldName$1);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
} else {
|
|
108
|
+
missingParams.push("block");
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
var returnedObj$2 = item.transaction;
|
|
112
|
+
if (Utils.$$Array.notEmpty(nonOptionalTransactionFieldNames)) {
|
|
113
|
+
if (returnedObj$2) {
|
|
114
|
+
for(var idx$2 = 0 ,idx_finish$2 = nonOptionalTransactionFieldNames.length; idx$2 < idx_finish$2; ++idx$2){
|
|
115
|
+
var fieldName$2 = nonOptionalTransactionFieldNames[idx$2];
|
|
116
|
+
var match$2 = returnedObj$2[fieldName$2];
|
|
117
|
+
if (match$2 !== undefined) {
|
|
118
|
+
|
|
119
|
+
} else {
|
|
120
|
+
missingParams.push("transaction." + fieldName$2);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
} else {
|
|
124
|
+
missingParams.push("transaction");
|
|
125
|
+
}
|
|
126
|
+
}
|
|
94
127
|
if (missingParams.length !== 0) {
|
|
95
128
|
throw {
|
|
96
129
|
RE_EXN_ID: $$Error,
|
|
@@ -447,10 +447,9 @@ type t = {
|
|
|
447
447
|
streamEvents: (~query: query, ~config: streamConfig) => promise<eventStream>,
|
|
448
448
|
}
|
|
449
449
|
|
|
450
|
-
@module("@envio-dev/hypersync-client") @scope("HypersyncClient") external
|
|
451
|
-
|
|
450
|
+
@module("@envio-dev/hypersync-client") @scope("HypersyncClient") external make: cfg => t = "new"
|
|
452
451
|
let make = (~url, ~apiToken, ~httpReqTimeoutMillis, ~maxNumRetries) =>
|
|
453
|
-
|
|
452
|
+
make({
|
|
454
453
|
url,
|
|
455
454
|
enableChecksumAddresses: true,
|
|
456
455
|
bearerToken: apiToken,
|
|
@@ -503,4 +502,6 @@ module Decoder = {
|
|
|
503
502
|
|
|
504
503
|
@module("@envio-dev/hypersync-client") @scope("Decoder")
|
|
505
504
|
external fromSignatures: array<string> => t = "fromSignatures"
|
|
505
|
+
// Keep the @envio-dev/hypersync-client import inside of the package
|
|
506
|
+
let fromSignatures = fromSignatures
|
|
506
507
|
}
|
|
@@ -88,8 +88,13 @@ function toUnderlying(_d) {
|
|
|
88
88
|
};
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
function fromSignatures(prim) {
|
|
92
|
+
return HypersyncClient.Decoder.fromSignatures(prim);
|
|
93
|
+
}
|
|
94
|
+
|
|
91
95
|
var Decoder = {
|
|
92
|
-
toUnderlying: toUnderlying
|
|
96
|
+
toUnderlying: toUnderlying,
|
|
97
|
+
fromSignatures: fromSignatures
|
|
93
98
|
};
|
|
94
99
|
|
|
95
100
|
exports.QueryTypes = QueryTypes;
|