envio 3.0.0-alpha.3 → 3.0.0-alpha.4
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/README.md +2 -2
- package/evm.schema.json +0 -1
- package/index.d.ts +4 -2
- package/index.js +1 -0
- package/package.json +5 -5
- package/src/Config.res +1 -1
- package/src/Config.res.mjs +4 -4
- package/src/Ecosystem.res +2 -2
- package/src/Ecosystem.res.mjs +1 -1
- package/src/Envio.gen.ts +1 -1
- package/src/Envio.res +1 -1
- package/src/Internal.res +41 -0
- package/src/Types.ts +1 -1
- package/src/Utils.res +15 -0
- package/src/Utils.res.mjs +18 -0
- package/src/bindings/ClickHouse.res +31 -1
- package/src/bindings/ClickHouse.res.mjs +27 -1
- package/src/bindings/Ethers.res +27 -63
- package/src/bindings/Ethers.res.mjs +18 -65
- package/src/sources/HyperSyncHeightStream.res +28 -110
- package/src/sources/HyperSyncHeightStream.res.mjs +30 -63
- package/src/sources/HyperSyncSource.res +11 -13
- package/src/sources/HyperSyncSource.res.mjs +20 -20
- package/src/sources/Rpc.res +43 -0
- package/src/sources/Rpc.res.mjs +31 -0
- package/src/sources/RpcSource.res +9 -4
- package/src/sources/RpcSource.res.mjs +9 -4
- package/src/sources/Source.res +1 -0
- package/src/sources/SourceManager.res +164 -81
- package/src/sources/SourceManager.res.mjs +146 -83
- package/src/sources/{Solana.res → Svm.res} +4 -4
- package/src/sources/{Solana.res.mjs → Svm.res.mjs} +4 -4
- package/src/bindings/Ethers.gen.ts +0 -14
|
@@ -1,28 +1,15 @@
|
|
|
1
1
|
/*
|
|
2
|
-
Pure
|
|
2
|
+
Pure subscription-based implementation of the HyperSync height stream.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
timeoutIdRef
|
|
9
|
-
eventsourceRef: ref<option<EventSource.t>>,
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
let make = (~hyperSyncUrl, ~apiToken) => {
|
|
13
|
-
/**
|
|
14
|
-
On every successful ping or height event, clear the timeout and set a new one.
|
|
5
|
+
let subscribe = (~hyperSyncUrl, ~apiToken, ~onHeight: int => unit): (unit => unit) => {
|
|
6
|
+
let eventsourceRef = ref(None)
|
|
7
|
+
// Timeout doesn't do anything for initialization
|
|
8
|
+
let timeoutIdRef = ref(Js.Global.setTimeout(() => (), 0))
|
|
15
9
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
let rec updateTimeoutId = (
|
|
19
|
-
~eventsourceRef: ref<option<EventSource.t>>,
|
|
20
|
-
~timeoutIdRef: ref<Js.Global.timeoutId>,
|
|
21
|
-
~hyperSyncUrl,
|
|
22
|
-
~apiToken,
|
|
23
|
-
~heightRef: ref<int>,
|
|
24
|
-
~errorRef: ref<option<string>>,
|
|
25
|
-
) => {
|
|
10
|
+
// On every successful ping or height event, clear the timeout and set a new one.
|
|
11
|
+
// If the timeout lapses, close and reconnect the EventSource.
|
|
12
|
+
let rec updateTimeoutId = () => {
|
|
26
13
|
timeoutIdRef.contents->Js.Global.clearTimeout
|
|
27
14
|
|
|
28
15
|
// Should receive a ping at least every 5s, so 15s is a safe margin
|
|
@@ -34,31 +21,15 @@ let make = (~hyperSyncUrl, ~apiToken) => {
|
|
|
34
21
|
"url": hyperSyncUrl,
|
|
35
22
|
"staleTimeMillis": staleTimeMillis,
|
|
36
23
|
})
|
|
37
|
-
refreshEventSource(
|
|
38
|
-
~eventsourceRef,
|
|
39
|
-
~hyperSyncUrl,
|
|
40
|
-
~apiToken,
|
|
41
|
-
~heightRef,
|
|
42
|
-
~errorRef,
|
|
43
|
-
~timeoutIdRef,
|
|
44
|
-
)
|
|
24
|
+
refreshEventSource()
|
|
45
25
|
}, staleTimeMillis)
|
|
46
26
|
|
|
47
27
|
timeoutIdRef := newTimeoutId
|
|
48
28
|
}
|
|
49
|
-
and
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
*/
|
|
54
|
-
refreshEventSource = (
|
|
55
|
-
~eventsourceRef: ref<option<EventSource.t>>,
|
|
56
|
-
~hyperSyncUrl,
|
|
57
|
-
~apiToken,
|
|
58
|
-
~heightRef: ref<int>,
|
|
59
|
-
~errorRef: ref<option<string>>,
|
|
60
|
-
~timeoutIdRef: ref<Js.Global.timeoutId>,
|
|
61
|
-
) => {
|
|
29
|
+
// Instantiate a new EventSource and set it to the shared refs.
|
|
30
|
+
// Add the necessary event listeners, handle errors
|
|
31
|
+
// and update the timeout.
|
|
32
|
+
and refreshEventSource = () => {
|
|
62
33
|
// Close the old EventSource if it exists (on a new connection after timeout)
|
|
63
34
|
switch eventsourceRef.contents {
|
|
64
35
|
| Some(es) => es->EventSource.close
|
|
@@ -79,7 +50,7 @@ let make = (~hyperSyncUrl, ~apiToken) => {
|
|
|
79
50
|
// Set the new EventSource to the shared ref
|
|
80
51
|
eventsourceRef := Some(es)
|
|
81
52
|
// Update the timeout in case connection goes stale
|
|
82
|
-
updateTimeoutId(
|
|
53
|
+
updateTimeoutId()
|
|
83
54
|
|
|
84
55
|
es->EventSource.onopen(_ => {
|
|
85
56
|
Logging.trace({"msg": "SSE connection opened for height stream", "url": hyperSyncUrl})
|
|
@@ -90,90 +61,37 @@ let make = (~hyperSyncUrl, ~apiToken) => {
|
|
|
90
61
|
"msg": "EventSource error",
|
|
91
62
|
"error": error->Js.Exn.message,
|
|
92
63
|
})
|
|
93
|
-
// On errors, set the error ref
|
|
94
|
-
// so that getHeight can raise an error
|
|
95
|
-
errorRef :=
|
|
96
|
-
Some(error->Js.Exn.message->Belt.Option.getWithDefault("Unexpected no error.message"))
|
|
97
64
|
})
|
|
98
65
|
|
|
99
66
|
es->EventSource.addEventListener("ping", _event => {
|
|
100
67
|
// ping lets us know from the server that the connection is still alive
|
|
101
|
-
// and that the height hasn't updated for
|
|
68
|
+
// and that the height hasn't updated for 5 seconds
|
|
102
69
|
// update the timeout on each successful ping received
|
|
103
|
-
updateTimeoutId(
|
|
104
|
-
~eventsourceRef,
|
|
105
|
-
~timeoutIdRef,
|
|
106
|
-
~hyperSyncUrl,
|
|
107
|
-
~apiToken,
|
|
108
|
-
~heightRef,
|
|
109
|
-
~errorRef,
|
|
110
|
-
)
|
|
111
|
-
// reset the error ref, since we had a successful ping
|
|
112
|
-
errorRef := None
|
|
70
|
+
updateTimeoutId()
|
|
113
71
|
})
|
|
114
72
|
|
|
115
73
|
es->EventSource.addEventListener("height", event => {
|
|
116
74
|
switch event.data->Belt.Int.fromString {
|
|
117
75
|
| Some(height) =>
|
|
118
76
|
// On a successful height event, update the timeout
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
~timeoutIdRef,
|
|
123
|
-
~hyperSyncUrl,
|
|
124
|
-
~apiToken,
|
|
125
|
-
~heightRef,
|
|
126
|
-
~errorRef,
|
|
127
|
-
)
|
|
128
|
-
errorRef := None
|
|
129
|
-
// Set the actual height ref
|
|
130
|
-
heightRef := height
|
|
77
|
+
updateTimeoutId()
|
|
78
|
+
// Call the callback with the new height
|
|
79
|
+
onHeight(height)
|
|
131
80
|
| None =>
|
|
132
81
|
Logging.trace({"msg": "Height was not a number in event.data", "data": event.data})
|
|
133
|
-
errorRef := Some("Height was not a number in event.data")
|
|
134
82
|
}
|
|
135
83
|
})
|
|
136
84
|
}
|
|
137
85
|
|
|
138
|
-
//
|
|
139
|
-
|
|
140
|
-
let heightRef = ref(0)
|
|
141
|
-
let errorRef = ref(None)
|
|
142
|
-
let eventsourceRef = ref(None)
|
|
143
|
-
// Timeout doesn't do anything for initalization
|
|
144
|
-
let timeoutIdRef = ref(Js.Global.setTimeout(() => (), 0))
|
|
145
|
-
refreshEventSource(
|
|
146
|
-
~eventsourceRef,
|
|
147
|
-
~hyperSyncUrl,
|
|
148
|
-
~apiToken,
|
|
149
|
-
~heightRef,
|
|
150
|
-
~errorRef,
|
|
151
|
-
~timeoutIdRef,
|
|
152
|
-
)
|
|
153
|
-
|
|
154
|
-
{
|
|
155
|
-
heightRef,
|
|
156
|
-
errorRef,
|
|
157
|
-
timeoutIdRef,
|
|
158
|
-
eventsourceRef,
|
|
159
|
-
}
|
|
160
|
-
}
|
|
86
|
+
// Start the EventSource connection
|
|
87
|
+
refreshEventSource()
|
|
161
88
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
| Some(error) => Js.Exn.raiseError(error)
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
let close = t => {
|
|
174
|
-
t.timeoutIdRef.contents->Js.Global.clearTimeout
|
|
175
|
-
switch t.eventsourceRef.contents {
|
|
176
|
-
| Some(es) => es->EventSource.close
|
|
177
|
-
| None => ()
|
|
89
|
+
// Return unsubscribe function
|
|
90
|
+
() => {
|
|
91
|
+
timeoutIdRef.contents->Js.Global.clearTimeout
|
|
92
|
+
switch eventsourceRef.contents {
|
|
93
|
+
| Some(es) => es->EventSource.close
|
|
94
|
+
| None => ()
|
|
95
|
+
}
|
|
178
96
|
}
|
|
179
97
|
}
|
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
3
|
import * as Utils from "../Utils.res.mjs";
|
|
4
|
-
import * as Js_exn from "rescript/lib/es6/js_exn.js";
|
|
5
4
|
import * as Js_dict from "rescript/lib/es6/js_dict.js";
|
|
6
5
|
import * as Logging from "../Logging.res.mjs";
|
|
7
6
|
import * as Belt_Int from "rescript/lib/es6/belt_Int.js";
|
|
8
|
-
import * as Belt_Option from "rescript/lib/es6/belt_Option.js";
|
|
9
7
|
import * as Caml_option from "rescript/lib/es6/caml_option.js";
|
|
10
8
|
import * as Eventsource from "eventsource";
|
|
11
9
|
|
|
12
|
-
function
|
|
13
|
-
var
|
|
10
|
+
function subscribe(hyperSyncUrl, apiToken, onHeight) {
|
|
11
|
+
var eventsourceRef = {
|
|
12
|
+
contents: undefined
|
|
13
|
+
};
|
|
14
|
+
var timeoutIdRef = {
|
|
15
|
+
contents: setTimeout((function () {
|
|
16
|
+
|
|
17
|
+
}), 0)
|
|
18
|
+
};
|
|
19
|
+
var updateTimeoutId = function () {
|
|
14
20
|
clearTimeout(timeoutIdRef.contents);
|
|
15
21
|
var newTimeoutId = setTimeout((function () {
|
|
16
22
|
Logging.trace({
|
|
@@ -18,11 +24,11 @@ function make(hyperSyncUrl, apiToken) {
|
|
|
18
24
|
url: hyperSyncUrl,
|
|
19
25
|
staleTimeMillis: 15000
|
|
20
26
|
});
|
|
21
|
-
refreshEventSource(
|
|
27
|
+
refreshEventSource();
|
|
22
28
|
}), 15000);
|
|
23
29
|
timeoutIdRef.contents = newTimeoutId;
|
|
24
30
|
};
|
|
25
|
-
var refreshEventSource = function (
|
|
31
|
+
var refreshEventSource = function () {
|
|
26
32
|
var es = eventsourceRef.contents;
|
|
27
33
|
if (es !== undefined) {
|
|
28
34
|
Caml_option.valFromOption(es).close();
|
|
@@ -41,7 +47,7 @@ function make(hyperSyncUrl, apiToken) {
|
|
|
41
47
|
])
|
|
42
48
|
});
|
|
43
49
|
eventsourceRef.contents = Caml_option.some(es$1);
|
|
44
|
-
updateTimeoutId(
|
|
50
|
+
updateTimeoutId();
|
|
45
51
|
es$1.onopen = (function () {
|
|
46
52
|
Logging.trace({
|
|
47
53
|
msg: "SSE connection opened for height stream",
|
|
@@ -53,75 +59,36 @@ function make(hyperSyncUrl, apiToken) {
|
|
|
53
59
|
msg: "EventSource error",
|
|
54
60
|
error: error.message
|
|
55
61
|
});
|
|
56
|
-
errorRef.contents = Belt_Option.getWithDefault(error.message, "Unexpected no error.message");
|
|
57
62
|
});
|
|
58
63
|
es$1.addEventListener("ping", (function (_event) {
|
|
59
|
-
updateTimeoutId(
|
|
60
|
-
errorRef.contents = undefined;
|
|
64
|
+
updateTimeoutId();
|
|
61
65
|
}));
|
|
62
66
|
es$1.addEventListener("height", (function ($$event) {
|
|
63
67
|
var height = Belt_Int.fromString($$event.data);
|
|
64
68
|
if (height !== undefined) {
|
|
65
|
-
updateTimeoutId(
|
|
66
|
-
|
|
67
|
-
heightRef.contents = height;
|
|
69
|
+
updateTimeoutId();
|
|
70
|
+
return onHeight(height);
|
|
68
71
|
} else {
|
|
69
|
-
Logging.trace({
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
errorRef.contents = "Height was not a number in event.data";
|
|
72
|
+
return Logging.trace({
|
|
73
|
+
msg: "Height was not a number in event.data",
|
|
74
|
+
data: $$event.data
|
|
75
|
+
});
|
|
74
76
|
}
|
|
75
77
|
}));
|
|
76
78
|
};
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
var timeoutIdRef = {
|
|
87
|
-
contents: setTimeout((function () {
|
|
88
|
-
|
|
89
|
-
}), 0)
|
|
90
|
-
};
|
|
91
|
-
refreshEventSource(eventsourceRef, hyperSyncUrl, apiToken, heightRef, errorRef, timeoutIdRef);
|
|
92
|
-
return {
|
|
93
|
-
heightRef: heightRef,
|
|
94
|
-
errorRef: errorRef,
|
|
95
|
-
timeoutIdRef: timeoutIdRef,
|
|
96
|
-
eventsourceRef: eventsourceRef
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
async function getHeight(t) {
|
|
101
|
-
while(t.heightRef.contents === 0 && t.errorRef.contents === undefined) {
|
|
102
|
-
await Utils.delay(200);
|
|
79
|
+
refreshEventSource();
|
|
80
|
+
return function () {
|
|
81
|
+
clearTimeout(timeoutIdRef.contents);
|
|
82
|
+
var es = eventsourceRef.contents;
|
|
83
|
+
if (es !== undefined) {
|
|
84
|
+
Caml_option.valFromOption(es).close();
|
|
85
|
+
return ;
|
|
86
|
+
}
|
|
87
|
+
|
|
103
88
|
};
|
|
104
|
-
var error = t.errorRef.contents;
|
|
105
|
-
if (error !== undefined) {
|
|
106
|
-
return Js_exn.raiseError(error);
|
|
107
|
-
} else {
|
|
108
|
-
return t.heightRef.contents;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function close(t) {
|
|
113
|
-
clearTimeout(t.timeoutIdRef.contents);
|
|
114
|
-
var es = t.eventsourceRef.contents;
|
|
115
|
-
if (es !== undefined) {
|
|
116
|
-
Caml_option.valFromOption(es).close();
|
|
117
|
-
return ;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
89
|
}
|
|
121
90
|
|
|
122
91
|
export {
|
|
123
|
-
|
|
124
|
-
getHeight ,
|
|
125
|
-
close ,
|
|
92
|
+
subscribe ,
|
|
126
93
|
}
|
|
127
94
|
/* Utils Not a pure module */
|
|
@@ -551,32 +551,30 @@ let make = (
|
|
|
551
551
|
~logger,
|
|
552
552
|
)->Promise.thenResolve(HyperSync.mapExn)
|
|
553
553
|
|
|
554
|
-
let
|
|
554
|
+
let jsonApiClient = Rest.client(endpointUrl)
|
|
555
555
|
|
|
556
|
-
let
|
|
556
|
+
let malformedTokenMessage = `Your token is malformed. For more info: https://docs.envio.dev/docs/HyperSync/api-tokens.`
|
|
557
557
|
|
|
558
558
|
{
|
|
559
559
|
name,
|
|
560
560
|
sourceFor: Sync,
|
|
561
561
|
chain,
|
|
562
|
-
pollingInterval:
|
|
562
|
+
pollingInterval: 100,
|
|
563
563
|
poweredByHyperSync: true,
|
|
564
564
|
getBlockHashes,
|
|
565
|
-
getHeightOrThrow: async () =>
|
|
566
|
-
|
|
567
|
-
|
|
|
568
|
-
|
|
569
|
-
->Js.Exn.message
|
|
570
|
-
->Option.getWithDefault("")
|
|
571
|
-
->Js.String2.includes(malformedTokenMessage) =>
|
|
565
|
+
getHeightOrThrow: async () =>
|
|
566
|
+
switch await HyperSyncJsonApi.heightRoute->Rest.fetch(apiToken, ~client=jsonApiClient) {
|
|
567
|
+
| Value(height) => height
|
|
568
|
+
| ErrorMessage(m) if m === malformedTokenMessage =>
|
|
572
569
|
Logging.error(`Your ENVIO_API_TOKEN is malformed. The indexer will not be able to fetch events. Update the token and restart the indexer using 'pnpm envio start'. For more info: https://docs.envio.dev/docs/HyperSync/api-tokens`)
|
|
573
570
|
// Don't want to retry if the token is malformed
|
|
574
571
|
// So just block forever
|
|
575
572
|
let _ = await Promise.make((_, _) => ())
|
|
576
573
|
0
|
|
577
|
-
|
|
|
578
|
-
}
|
|
579
|
-
},
|
|
574
|
+
| ErrorMessage(m) => Js.Exn.raiseError(m)
|
|
575
|
+
},
|
|
580
576
|
getItemsOrThrow,
|
|
577
|
+
createHeightSubscription: (~onHeight) =>
|
|
578
|
+
HyperSyncHeightStream.subscribe(~hyperSyncUrl=endpointUrl, ~apiToken, ~onHeight),
|
|
581
579
|
}
|
|
582
580
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
|
+
import * as Rest from "../vendored/Rest.res.mjs";
|
|
3
4
|
import * as Viem from "../bindings/Viem.res.mjs";
|
|
4
5
|
import * as Utils from "../Utils.res.mjs";
|
|
5
6
|
import * as Hrtime from "../bindings/Hrtime.res.mjs";
|
|
@@ -15,6 +16,7 @@ import * as ErrorHandling from "../ErrorHandling.res.mjs";
|
|
|
15
16
|
import * as Caml_exceptions from "rescript/lib/es6/caml_exceptions.js";
|
|
16
17
|
import * as HyperSyncClient from "./HyperSyncClient.res.mjs";
|
|
17
18
|
import * as Caml_splice_call from "rescript/lib/es6/caml_splice_call.js";
|
|
19
|
+
import * as HyperSyncJsonApi from "./HyperSyncJsonApi.res.mjs";
|
|
18
20
|
import * as Caml_js_exceptions from "rescript/lib/es6/caml_js_exceptions.js";
|
|
19
21
|
import * as HyperSyncHeightStream from "./HyperSyncHeightStream.res.mjs";
|
|
20
22
|
|
|
@@ -383,34 +385,32 @@ function make(param) {
|
|
|
383
385
|
var getBlockHashes = function (blockNumbers, logger) {
|
|
384
386
|
return HyperSync.queryBlockDataMulti(endpointUrl, apiToken, blockNumbers, logger).then(HyperSync.mapExn);
|
|
385
387
|
};
|
|
386
|
-
var
|
|
388
|
+
var jsonApiClient = Rest.client(endpointUrl, undefined);
|
|
387
389
|
return {
|
|
388
390
|
name: "HyperSync",
|
|
389
391
|
sourceFor: "Sync",
|
|
390
392
|
chain: chain,
|
|
391
393
|
poweredByHyperSync: true,
|
|
392
|
-
pollingInterval:
|
|
394
|
+
pollingInterval: 100,
|
|
393
395
|
getBlockHashes: getBlockHashes,
|
|
394
396
|
getHeightOrThrow: (async function () {
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
return 0;
|
|
407
|
-
}
|
|
408
|
-
throw exn;
|
|
409
|
-
}
|
|
410
|
-
throw exn;
|
|
397
|
+
var height = await Rest.$$fetch(HyperSyncJsonApi.heightRoute, apiToken, jsonApiClient);
|
|
398
|
+
if (typeof height === "number") {
|
|
399
|
+
return height;
|
|
400
|
+
} else if (height === "Your token is malformed. For more info: https://docs.envio.dev/docs/HyperSync/api-tokens.") {
|
|
401
|
+
Logging.error("Your ENVIO_API_TOKEN is malformed. The indexer will not be able to fetch events. Update the token and restart the indexer using 'pnpm envio start'. For more info: https://docs.envio.dev/docs/HyperSync/api-tokens");
|
|
402
|
+
await new Promise((function (param, param$1) {
|
|
403
|
+
|
|
404
|
+
}));
|
|
405
|
+
return 0;
|
|
406
|
+
} else {
|
|
407
|
+
return Js_exn.raiseError(height);
|
|
411
408
|
}
|
|
412
409
|
}),
|
|
413
|
-
getItemsOrThrow: getItemsOrThrow
|
|
410
|
+
getItemsOrThrow: getItemsOrThrow,
|
|
411
|
+
createHeightSubscription: (function (onHeight) {
|
|
412
|
+
return HyperSyncHeightStream.subscribe(endpointUrl, apiToken, onHeight);
|
|
413
|
+
})
|
|
414
414
|
};
|
|
415
415
|
}
|
|
416
416
|
|
|
@@ -419,4 +419,4 @@ export {
|
|
|
419
419
|
memoGetSelectionConfig ,
|
|
420
420
|
make ,
|
|
421
421
|
}
|
|
422
|
-
/*
|
|
422
|
+
/* Rest Not a pure module */
|
package/src/sources/Rpc.res
CHANGED
|
@@ -179,3 +179,46 @@ module GetBlockByNumber = {
|
|
|
179
179
|
module GetBlockHeight = {
|
|
180
180
|
let route = makeRpcRoute("eth_blockNumber", S.tuple(_ => ()), hexIntSchema)
|
|
181
181
|
}
|
|
182
|
+
|
|
183
|
+
module GetTransactionByHash = {
|
|
184
|
+
let transactionSchema = S.object((s): Internal.evmTransactionFields => {
|
|
185
|
+
// We already know the data so ignore the fields
|
|
186
|
+
// blockHash: ?s.field("blockHash", S.option(S.string)),
|
|
187
|
+
// blockNumber: ?s.field("blockNumber", S.option(hexIntSchema)),
|
|
188
|
+
// chainId: ?s.field("chainId", S.option(hexIntSchema)),
|
|
189
|
+
from: ?s.field("from", S.option(S.string->(Utils.magic: S.t<string> => S.t<Address.t>))),
|
|
190
|
+
to: ?s.field("to", S.option(S.string->(Utils.magic: S.t<string> => S.t<Address.t>))),
|
|
191
|
+
gas: ?s.field("gas", S.option(hexBigintSchema)),
|
|
192
|
+
gasPrice: ?s.field("gasPrice", S.option(hexBigintSchema)),
|
|
193
|
+
hash: ?s.field("hash", S.option(S.string)),
|
|
194
|
+
input: ?s.field("input", S.option(S.string)),
|
|
195
|
+
nonce: ?s.field("nonce", S.option(hexBigintSchema)),
|
|
196
|
+
transactionIndex: ?s.field("transactionIndex", S.option(hexIntSchema)),
|
|
197
|
+
value: ?s.field("value", S.option(hexBigintSchema)),
|
|
198
|
+
type_: ?s.field("type", S.option(hexIntSchema)),
|
|
199
|
+
// Signature fields - optional for ZKSync EIP-712 compatibility
|
|
200
|
+
v: ?s.field("v", S.option(S.string)),
|
|
201
|
+
r: ?s.field("r", S.option(S.string)),
|
|
202
|
+
s: ?s.field("s", S.option(S.string)),
|
|
203
|
+
yParity: ?s.field("yParity", S.option(S.string)),
|
|
204
|
+
// EIP-1559 fields
|
|
205
|
+
maxPriorityFeePerGas: ?s.field("maxPriorityFeePerGas", S.option(hexBigintSchema)),
|
|
206
|
+
maxFeePerGas: ?s.field("maxFeePerGas", S.option(hexBigintSchema)),
|
|
207
|
+
// EIP-4844 blob fields
|
|
208
|
+
maxFeePerBlobGas: ?s.field("maxFeePerBlobGas", S.option(hexBigintSchema)),
|
|
209
|
+
blobVersionedHashes: ?s.field("blobVersionedHashes", S.option(S.array(S.string))),
|
|
210
|
+
// TODO: Fields to add:
|
|
211
|
+
// pub access_list: Option<Vec<AccessList>>,
|
|
212
|
+
// pub authorization_list: Option<Vec<Authorization>>,
|
|
213
|
+
// // OP stack fields
|
|
214
|
+
// pub deposit_receipt_version: Option<Quantity>,
|
|
215
|
+
// pub mint: Option<Quantity>,
|
|
216
|
+
// pub source_hash: Option<Hash>,
|
|
217
|
+
})
|
|
218
|
+
|
|
219
|
+
let route = makeRpcRoute(
|
|
220
|
+
"eth_getTransactionByHash",
|
|
221
|
+
S.tuple1(S.string),
|
|
222
|
+
S.null(transactionSchema),
|
|
223
|
+
)
|
|
224
|
+
}
|
package/src/sources/Rpc.res.mjs
CHANGED
|
@@ -187,6 +187,36 @@ var GetBlockHeight = {
|
|
|
187
187
|
route: route$2
|
|
188
188
|
};
|
|
189
189
|
|
|
190
|
+
var transactionSchema = S$RescriptSchema.object(function (s) {
|
|
191
|
+
return {
|
|
192
|
+
from: s.f("from", S$RescriptSchema.option(S$RescriptSchema.string)),
|
|
193
|
+
to: s.f("to", S$RescriptSchema.option(S$RescriptSchema.string)),
|
|
194
|
+
gas: s.f("gas", S$RescriptSchema.option(hexBigintSchema)),
|
|
195
|
+
gasPrice: s.f("gasPrice", S$RescriptSchema.option(hexBigintSchema)),
|
|
196
|
+
hash: s.f("hash", S$RescriptSchema.option(S$RescriptSchema.string)),
|
|
197
|
+
input: s.f("input", S$RescriptSchema.option(S$RescriptSchema.string)),
|
|
198
|
+
nonce: s.f("nonce", S$RescriptSchema.option(hexBigintSchema)),
|
|
199
|
+
transactionIndex: s.f("transactionIndex", S$RescriptSchema.option(hexIntSchema)),
|
|
200
|
+
value: s.f("value", S$RescriptSchema.option(hexBigintSchema)),
|
|
201
|
+
v: s.f("v", S$RescriptSchema.option(S$RescriptSchema.string)),
|
|
202
|
+
r: s.f("r", S$RescriptSchema.option(S$RescriptSchema.string)),
|
|
203
|
+
s: s.f("s", S$RescriptSchema.option(S$RescriptSchema.string)),
|
|
204
|
+
yParity: s.f("yParity", S$RescriptSchema.option(S$RescriptSchema.string)),
|
|
205
|
+
maxPriorityFeePerGas: s.f("maxPriorityFeePerGas", S$RescriptSchema.option(hexBigintSchema)),
|
|
206
|
+
maxFeePerGas: s.f("maxFeePerGas", S$RescriptSchema.option(hexBigintSchema)),
|
|
207
|
+
maxFeePerBlobGas: s.f("maxFeePerBlobGas", S$RescriptSchema.option(hexBigintSchema)),
|
|
208
|
+
blobVersionedHashes: s.f("blobVersionedHashes", S$RescriptSchema.option(S$RescriptSchema.array(S$RescriptSchema.string))),
|
|
209
|
+
type: s.f("type", S$RescriptSchema.option(hexIntSchema))
|
|
210
|
+
};
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
var route$3 = makeRpcRoute("eth_getTransactionByHash", S$RescriptSchema.tuple1(S$RescriptSchema.string), S$RescriptSchema.$$null(transactionSchema));
|
|
214
|
+
|
|
215
|
+
var GetTransactionByHash = {
|
|
216
|
+
transactionSchema: transactionSchema,
|
|
217
|
+
route: route$3
|
|
218
|
+
};
|
|
219
|
+
|
|
190
220
|
export {
|
|
191
221
|
makeRpcRoute ,
|
|
192
222
|
makeHexSchema ,
|
|
@@ -195,5 +225,6 @@ export {
|
|
|
195
225
|
GetLogs ,
|
|
196
226
|
GetBlockByNumber ,
|
|
197
227
|
GetBlockHeight ,
|
|
228
|
+
GetTransactionByHash ,
|
|
198
229
|
}
|
|
199
230
|
/* hexBigintSchema Not a pure module */
|
|
@@ -503,10 +503,12 @@ let make = (
|
|
|
503
503
|
|
|
504
504
|
let mutSuggestedBlockIntervals = Js.Dict.empty()
|
|
505
505
|
|
|
506
|
+
let client = Rest.client(url)
|
|
507
|
+
|
|
506
508
|
let makeTransactionLoader = () =>
|
|
507
509
|
LazyLoader.make(
|
|
508
510
|
~loaderFn=transactionHash =>
|
|
509
|
-
|
|
511
|
+
Rpc.GetTransactionByHash.route->Rest.fetch(transactionHash, ~client),
|
|
510
512
|
~onError=(am, ~exn) => {
|
|
511
513
|
Logging.error({
|
|
512
514
|
"err": exn->Utils.prettifyExn,
|
|
@@ -560,7 +562,12 @@ let make = (
|
|
|
560
562
|
)
|
|
561
563
|
let getEventTransactionOrThrow = makeThrowingGetEventTransaction(
|
|
562
564
|
~getTransactionFields=Ethers.JsonRpcProvider.makeGetTransactionFields(
|
|
563
|
-
~getTransactionByHash=
|
|
565
|
+
~getTransactionByHash=async transactionHash => {
|
|
566
|
+
switch await transactionLoader.contents->LazyLoader.get(transactionHash) {
|
|
567
|
+
| Some(tx) => tx
|
|
568
|
+
| None => Js.Exn.raiseError(`Transaction not found for hash: ${transactionHash}`)
|
|
569
|
+
}
|
|
570
|
+
},
|
|
564
571
|
~lowercaseAddresses,
|
|
565
572
|
),
|
|
566
573
|
)
|
|
@@ -902,8 +909,6 @@ let make = (
|
|
|
902
909
|
->Promise.catch(exn => exn->Error->Promise.resolve)
|
|
903
910
|
}
|
|
904
911
|
|
|
905
|
-
let client = Rest.client(url)
|
|
906
|
-
|
|
907
912
|
{
|
|
908
913
|
name,
|
|
909
914
|
sourceFor,
|
|
@@ -518,9 +518,10 @@ function make(param) {
|
|
|
518
518
|
var provider = Ethers.JsonRpcProvider.make(url, chain);
|
|
519
519
|
var getSelectionConfig = memoGetSelectionConfig(chain);
|
|
520
520
|
var mutSuggestedBlockIntervals = {};
|
|
521
|
+
var client = Rest.client(url, undefined);
|
|
521
522
|
var makeTransactionLoader = function () {
|
|
522
523
|
return LazyLoader.make((function (transactionHash) {
|
|
523
|
-
return
|
|
524
|
+
return Rest.$$fetch(Rpc.GetTransactionByHash.route, transactionHash, client);
|
|
524
525
|
}), (function (am, exn) {
|
|
525
526
|
Logging.error({
|
|
526
527
|
err: Utils.prettifyExn(exn),
|
|
@@ -559,8 +560,13 @@ function make(param) {
|
|
|
559
560
|
var getEventBlockOrThrow = makeThrowingGetEventBlock(function (blockNumber) {
|
|
560
561
|
return LazyLoader.get(blockLoader.contents, blockNumber);
|
|
561
562
|
});
|
|
562
|
-
var getEventTransactionOrThrow = makeThrowingGetEventTransaction(Ethers.JsonRpcProvider.makeGetTransactionFields((function (
|
|
563
|
-
|
|
563
|
+
var getEventTransactionOrThrow = makeThrowingGetEventTransaction(Ethers.JsonRpcProvider.makeGetTransactionFields((async function (transactionHash) {
|
|
564
|
+
var tx = await LazyLoader.get(transactionLoader.contents, transactionHash);
|
|
565
|
+
if (tx !== undefined) {
|
|
566
|
+
return tx;
|
|
567
|
+
} else {
|
|
568
|
+
return Js_exn.raiseError("Transaction not found for hash: " + transactionHash);
|
|
569
|
+
}
|
|
564
570
|
}), lowercaseAddresses));
|
|
565
571
|
var contractNameAbiMapping = {};
|
|
566
572
|
Belt_Array.forEach(param.contracts, (function (contract) {
|
|
@@ -819,7 +825,6 @@ function make(param) {
|
|
|
819
825
|
});
|
|
820
826
|
}));
|
|
821
827
|
};
|
|
822
|
-
var client = Rest.client(url, undefined);
|
|
823
828
|
return {
|
|
824
829
|
name: name,
|
|
825
830
|
sourceFor: param.sourceFor,
|