envio 2.8.1 → 2.9.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/Enum.res +22 -0
- package/src/LogSelection.res +60 -0
- package/src/Utils.res +2 -0
- package/src/bindings/BigInt.res +57 -0
- package/src/bindings/Express.res +29 -0
- package/src/bindings/Postgres.res +98 -0
- package/src/bindings/Promise.res +52 -0
- package/src/db/EntityHistory.res +335 -0
- package/src/db/Schema.res +18 -0
- package/src/db/Table.res +251 -0
- package/src/sources/Rpc.res +181 -0
- package/src/vendored/Rest.res +661 -0
- package/src/vendored/Rest.resi +182 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "envio",
|
|
3
|
-
"version": "v2.
|
|
3
|
+
"version": "v2.9.0",
|
|
4
4
|
"description": "A latency and sync speed optimized, developer friendly blockchain data indexer.",
|
|
5
5
|
"bin": "./bin.js",
|
|
6
6
|
"repository": {
|
|
@@ -23,15 +23,15 @@
|
|
|
23
23
|
},
|
|
24
24
|
"homepage": "https://envio.dev",
|
|
25
25
|
"optionalDependencies": {
|
|
26
|
-
"envio-linux-x64": "v2.
|
|
27
|
-
"envio-linux-arm64": "v2.
|
|
28
|
-
"envio-darwin-x64": "v2.
|
|
29
|
-
"envio-darwin-arm64": "v2.
|
|
26
|
+
"envio-linux-x64": "v2.9.0",
|
|
27
|
+
"envio-linux-arm64": "v2.9.0",
|
|
28
|
+
"envio-darwin-x64": "v2.9.0",
|
|
29
|
+
"envio-darwin-arm64": "v2.9.0"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@envio-dev/hypersync-client": "0.6.2",
|
|
33
33
|
"rescript": "11.1.3",
|
|
34
|
-
"rescript-schema": "8.
|
|
34
|
+
"rescript-schema": "8.1.0",
|
|
35
35
|
"viem": "2.21.0"
|
|
36
36
|
},
|
|
37
37
|
"files": [
|
package/src/Enum.res
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Graphql Enum Type Variants
|
|
2
|
+
type enum<'a> = {
|
|
3
|
+
name: string,
|
|
4
|
+
variants: array<'a>,
|
|
5
|
+
schema: S.t<'a>,
|
|
6
|
+
default: 'a,
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let make = (~name, ~variants) => {
|
|
10
|
+
name,
|
|
11
|
+
variants,
|
|
12
|
+
schema: Utils.Schema.enum(variants),
|
|
13
|
+
default: switch variants->Belt.Array.get(0) {
|
|
14
|
+
| Some(v) => v
|
|
15
|
+
| None => Js.Exn.raiseError("No variants defined for enum " ++ name)
|
|
16
|
+
},
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
module type S = {
|
|
20
|
+
type t
|
|
21
|
+
let enum: enum<t>
|
|
22
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
type topicSelection = {
|
|
2
|
+
topic0: array<EvmTypes.Hex.t>,
|
|
3
|
+
topic1: array<EvmTypes.Hex.t>,
|
|
4
|
+
topic2: array<EvmTypes.Hex.t>,
|
|
5
|
+
topic3: array<EvmTypes.Hex.t>,
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
exception MissingRequiredTopic0
|
|
9
|
+
let makeTopicSelection = (~topic0, ~topic1=[], ~topic2=[], ~topic3=[]) =>
|
|
10
|
+
if topic0->Utils.Array.isEmpty {
|
|
11
|
+
Error(MissingRequiredTopic0)
|
|
12
|
+
} else {
|
|
13
|
+
{
|
|
14
|
+
topic0,
|
|
15
|
+
topic1,
|
|
16
|
+
topic2,
|
|
17
|
+
topic3,
|
|
18
|
+
}->Ok
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let hasFilters = ({topic1, topic2, topic3}: topicSelection) => {
|
|
22
|
+
[topic1, topic2, topic3]->Js.Array2.find(topic => !Utils.Array.isEmpty(topic))->Belt.Option.isSome
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
For a group of topic selections, if multiple only use topic0, then they can be compressed into one
|
|
27
|
+
selection combining the topic0s
|
|
28
|
+
*/
|
|
29
|
+
let compressTopicSelectionsOrThrow = (topicSelections: array<topicSelection>) => {
|
|
30
|
+
let topic0sOfSelectionsWithoutFilters = []
|
|
31
|
+
|
|
32
|
+
let selectionsWithFilters = []
|
|
33
|
+
|
|
34
|
+
topicSelections->Belt.Array.forEach(selection => {
|
|
35
|
+
if selection->hasFilters {
|
|
36
|
+
selectionsWithFilters->Js.Array2.push(selection)->ignore
|
|
37
|
+
} else {
|
|
38
|
+
selection.topic0->Belt.Array.forEach(topic0 => {
|
|
39
|
+
topic0sOfSelectionsWithoutFilters->Js.Array2.push(topic0)->ignore
|
|
40
|
+
})
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
switch topic0sOfSelectionsWithoutFilters {
|
|
45
|
+
| [] => selectionsWithFilters
|
|
46
|
+
| topic0 =>
|
|
47
|
+
let selectionWithoutFilters = makeTopicSelection(~topic0)->Utils.unwrapResultExn
|
|
48
|
+
Belt.Array.concat([selectionWithoutFilters], selectionsWithFilters)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
type t = {
|
|
53
|
+
addresses: array<Address.t>,
|
|
54
|
+
topicSelections: array<topicSelection>,
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let makeOrThrow = (~addresses, ~topicSelections) => {
|
|
58
|
+
let topicSelections = compressTopicSelectionsOrThrow(topicSelections)
|
|
59
|
+
{addresses, topicSelections}
|
|
60
|
+
}
|
package/src/Utils.res
CHANGED
|
@@ -222,6 +222,8 @@ let unwrapResultExn = res =>
|
|
|
222
222
|
external queueMicrotask: (unit => unit) => unit = "queueMicrotask"
|
|
223
223
|
|
|
224
224
|
module Schema = {
|
|
225
|
+
let enum = items => S.union(items->Belt.Array.mapU(S.literal))
|
|
226
|
+
|
|
225
227
|
let getNonOptionalFieldNames = schema => {
|
|
226
228
|
let acc = []
|
|
227
229
|
switch schema->S.classify {
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
%%private(
|
|
2
|
+
@inline
|
|
3
|
+
let unsafeToOption: (unit => 'a) => option<'a> = unsafeFunc => {
|
|
4
|
+
try {
|
|
5
|
+
unsafeFunc()->Some
|
|
6
|
+
} catch {
|
|
7
|
+
| Js.Exn.Error(_obj) => None
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
// constructors and methods
|
|
13
|
+
@val external fromInt: int => bigint = "BigInt"
|
|
14
|
+
@val external fromStringUnsafe: string => bigint = "BigInt"
|
|
15
|
+
@val external fromUnknownUnsafe: unknown => bigint = "BigInt"
|
|
16
|
+
let fromString = str => unsafeToOption(() => str->fromStringUnsafe)
|
|
17
|
+
@send external toString: bigint => string = "toString"
|
|
18
|
+
let toInt = (b: bigint): option<int> => b->toString->Belt.Int.fromString
|
|
19
|
+
|
|
20
|
+
//silence unused var warnings for raw bindings
|
|
21
|
+
@@warning("-27")
|
|
22
|
+
// operation
|
|
23
|
+
let add = (a: bigint, b: bigint): bigint => %raw("a + b")
|
|
24
|
+
let sub = (a: bigint, b: bigint): bigint => %raw("a - b")
|
|
25
|
+
let mul = (a: bigint, b: bigint): bigint => %raw("a * b")
|
|
26
|
+
let div = (a: bigint, b: bigint): bigint => %raw("b > 0n ? a / b : 0n")
|
|
27
|
+
let pow = (a: bigint, b: bigint): bigint => %raw("a ** b")
|
|
28
|
+
let mod = (a: bigint, b: bigint): bigint => %raw("b > 0n ? a % b : 0n")
|
|
29
|
+
|
|
30
|
+
// comparison
|
|
31
|
+
let eq = (a: bigint, b: bigint): bool => %raw("a === b")
|
|
32
|
+
let neq = (a: bigint, b: bigint): bool => %raw("a !== b")
|
|
33
|
+
let gt = (a: bigint, b: bigint): bool => %raw("a > b")
|
|
34
|
+
let gte = (a: bigint, b: bigint): bool => %raw("a >= b")
|
|
35
|
+
let lt = (a: bigint, b: bigint): bool => %raw("a < b")
|
|
36
|
+
let lte = (a: bigint, b: bigint): bool => %raw("a <= b")
|
|
37
|
+
|
|
38
|
+
module Bitwise = {
|
|
39
|
+
let shift_left = (a: bigint, b: bigint): bigint => %raw("a << b")
|
|
40
|
+
let shift_right = (a: bigint, b: bigint): bigint => %raw("a >> b")
|
|
41
|
+
let logor = (a: bigint, b: bigint): bigint => %raw("a | b")
|
|
42
|
+
let logand = (a: bigint, b: bigint): bigint => %raw("a & b")
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
let zero = fromInt(0)
|
|
46
|
+
|
|
47
|
+
let schema =
|
|
48
|
+
S.string
|
|
49
|
+
->S.setName("BigInt")
|
|
50
|
+
->S.transform(s => {
|
|
51
|
+
parser: (. string) =>
|
|
52
|
+
switch string->fromString {
|
|
53
|
+
| Some(bigInt) => bigInt
|
|
54
|
+
| None => s.fail(. "The string is not valid BigInt")
|
|
55
|
+
},
|
|
56
|
+
serializer: (. bigint) => bigint->toString,
|
|
57
|
+
})
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Inspired by https://github.com/bloodyowl/rescript-express
|
|
2
|
+
|
|
3
|
+
type app
|
|
4
|
+
|
|
5
|
+
// "default" & seem to conflict a bit right now
|
|
6
|
+
// https://github.com/rescript-lang/rescript-compiler/issues/5004
|
|
7
|
+
@module external makeCjs: unit => app = "express"
|
|
8
|
+
@module("express") external make: unit => app = "default"
|
|
9
|
+
|
|
10
|
+
type req
|
|
11
|
+
type res
|
|
12
|
+
|
|
13
|
+
type handler = (req, res) => unit
|
|
14
|
+
type middleware = (req, res, unit => unit) => unit
|
|
15
|
+
|
|
16
|
+
@module("express") external jsonMiddleware: unit => middleware = "json"
|
|
17
|
+
|
|
18
|
+
@send external use: (app, middleware) => unit = "use"
|
|
19
|
+
|
|
20
|
+
@send external get: (app, string, handler) => unit = "get"
|
|
21
|
+
|
|
22
|
+
type server
|
|
23
|
+
|
|
24
|
+
@send external listen: (app, int) => server = "listen"
|
|
25
|
+
|
|
26
|
+
// res methods
|
|
27
|
+
@send external sendStatus: (res, int) => res = "sendStatus"
|
|
28
|
+
@send external set: (res, string, string) => unit = "set"
|
|
29
|
+
@send external endWithData: (res, 'a) => res = "end"
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
type sql
|
|
2
|
+
|
|
3
|
+
type undefinedTransform = | @as(undefined) Undefined | @as(null) Null
|
|
4
|
+
|
|
5
|
+
type transformConfig = {
|
|
6
|
+
undefined?: undefinedTransform, // Transforms undefined values (eg. to null) (default: undefined)
|
|
7
|
+
// column?: 'c => 'd, // Transforms incoming column names (default: fn)
|
|
8
|
+
// value?: 'e => 'f, // Transforms incoming row values (default: fn)
|
|
9
|
+
// row?: 'g => 'h, // Transforms entire rows (default: fn)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
type connectionConfig = {
|
|
13
|
+
applicationName?: string, // Default application_name (default: 'postgres.js')
|
|
14
|
+
// Other connection parameters, see https://www.postgresql.org/docs/current/runtime-config-client.html
|
|
15
|
+
}
|
|
16
|
+
type streamDuplex
|
|
17
|
+
type buffer
|
|
18
|
+
type secureContext
|
|
19
|
+
|
|
20
|
+
type onread = {
|
|
21
|
+
buffer: Js.Nullable.t<array<int>> => array<int>,
|
|
22
|
+
callback: (int, array<int>) => unit,
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
type tlsConnectOptions = {
|
|
26
|
+
enableTrace?: bool,
|
|
27
|
+
host?: string /* Default: "localhost" */,
|
|
28
|
+
port?: int,
|
|
29
|
+
path?: string,
|
|
30
|
+
socket?: streamDuplex,
|
|
31
|
+
allowHalfOpen?: bool /* Default: false */,
|
|
32
|
+
rejectUnauthorized?: bool /* Default: true */,
|
|
33
|
+
pskCallback?: unit => unit,
|
|
34
|
+
@as("ALPNProtocols") alpnProtocols?: array<string>, //| array<Buffer> | array<typedArray> | array<DataView> | Buffer | typedArray | DataView,
|
|
35
|
+
servername?: string,
|
|
36
|
+
checkServerIdentity?: 'a. (string, 'a) => option<Js.Exn.t>,
|
|
37
|
+
session?: buffer,
|
|
38
|
+
minDHSize?: int /* Default: 1024 */,
|
|
39
|
+
highWaterMark?: int /* Default: 16 * 1024 */,
|
|
40
|
+
secureContext?: secureContext,
|
|
41
|
+
onread?: onread,
|
|
42
|
+
/* Additional properties from tls.createSecureContext() and socket.connect() */
|
|
43
|
+
// [key: string]: Js.Json.t,
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@unboxed
|
|
47
|
+
type sslOptions =
|
|
48
|
+
| Bool(bool)
|
|
49
|
+
| TLSConnectOptions(tlsConnectOptions)
|
|
50
|
+
| @as("require") Require
|
|
51
|
+
| @as("allow") Allow
|
|
52
|
+
| @as("prefer") Prefer
|
|
53
|
+
| @as("verify-full") VerifyFull
|
|
54
|
+
|
|
55
|
+
let sslOptionsSchema: S.schema<sslOptions> = Utils.Schema.enum([
|
|
56
|
+
Bool(true),
|
|
57
|
+
Bool(false),
|
|
58
|
+
Require,
|
|
59
|
+
Allow,
|
|
60
|
+
Prefer,
|
|
61
|
+
VerifyFull,
|
|
62
|
+
//No schema created for tlsConnectOptions obj
|
|
63
|
+
])
|
|
64
|
+
|
|
65
|
+
type poolConfig = {
|
|
66
|
+
host?: string, // Postgres ip address[es] or domain name[s] (default: '')
|
|
67
|
+
port?: int, // Postgres server port[s] (default: 5432)
|
|
68
|
+
path?: string, // unix socket path (usually '/tmp') (default: '')
|
|
69
|
+
database?: string, // Name of database to connect to (default: '')
|
|
70
|
+
username?: string, // Username of database user (default: '')
|
|
71
|
+
password?: string, // Password of database user (default: '')
|
|
72
|
+
ssl?: sslOptions, // true, prefer, require, tls.connect options (default: false)
|
|
73
|
+
max?: int, // Max number of connections (default: 10)
|
|
74
|
+
maxLifetime?: option<int>, // Max lifetime in seconds (more info below) (default: null)
|
|
75
|
+
idleTimeout?: int, // Idle connection timeout in seconds (default: 0)
|
|
76
|
+
connectTimeout?: int, // Connect timeout in seconds (default: 30)
|
|
77
|
+
prepare?: bool, // Automatic creation of prepared statements (default: true)
|
|
78
|
+
// types?: array<'a>, // Array of custom types, see more below (default: [])
|
|
79
|
+
onnotice?: string => unit, // Default console.log, set false to silence NOTICE (default: fn)
|
|
80
|
+
onParameter?: (string, string) => unit, // (key, value) when server param change (default: fn)
|
|
81
|
+
debug?: 'a. 'a => unit, //(connection, query, params, types) => unit, // Is called with (connection, query, params, types) (default: fn)
|
|
82
|
+
socket?: unit => unit, // fn returning custom socket to use (default: fn)
|
|
83
|
+
transform?: transformConfig,
|
|
84
|
+
connection?: connectionConfig,
|
|
85
|
+
targetSessionAttrs?: option<string>, // Use 'read-write' with multiple hosts to ensure only connecting to primary (default: null)
|
|
86
|
+
fetchTypes?: bool, // Automatically fetches types on connect on initial connection. (default: true)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@module
|
|
90
|
+
external makeSql: (~config: poolConfig) => sql = "postgres"
|
|
91
|
+
|
|
92
|
+
@send external beginSql: (sql, sql => array<promise<unit>>) => promise<unit> = "begin"
|
|
93
|
+
|
|
94
|
+
// TODO: can explore this approach (https://forum.rescript-lang.org/t/rfc-support-for-tagged-template-literals/3744)
|
|
95
|
+
// @send @variadic
|
|
96
|
+
// external sql: array<string> => (sql, array<string>) => int = "sql"
|
|
97
|
+
|
|
98
|
+
@send external unsafe: (sql, string) => promise<'a> = "unsafe"
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
type t<+'a> = promise<'a>
|
|
2
|
+
|
|
3
|
+
@new
|
|
4
|
+
external make: ((@uncurry 'a => unit, 'e => unit) => unit) => t<'a> = "Promise"
|
|
5
|
+
|
|
6
|
+
@val @scope("Promise")
|
|
7
|
+
external resolve: 'a => t<'a> = "resolve"
|
|
8
|
+
|
|
9
|
+
@send external then: (t<'a>, @uncurry 'a => t<'b>) => t<'b> = "then"
|
|
10
|
+
|
|
11
|
+
@send
|
|
12
|
+
external thenResolve: (t<'a>, @uncurry 'a => 'b) => t<'b> = "then"
|
|
13
|
+
|
|
14
|
+
@send external finally: (t<'a>, unit => unit) => t<'a> = "finally"
|
|
15
|
+
|
|
16
|
+
@scope("Promise") @val
|
|
17
|
+
external reject: exn => t<_> = "reject"
|
|
18
|
+
|
|
19
|
+
@scope("Promise") @val
|
|
20
|
+
external all: array<t<'a>> => t<array<'a>> = "all"
|
|
21
|
+
|
|
22
|
+
@scope("Promise") @val
|
|
23
|
+
external all2: ((t<'a>, t<'b>)) => t<('a, 'b)> = "all"
|
|
24
|
+
|
|
25
|
+
@scope("Promise") @val
|
|
26
|
+
external all3: ((t<'a>, t<'b>, t<'c>)) => t<('a, 'b, 'c)> = "all"
|
|
27
|
+
|
|
28
|
+
@scope("Promise") @val
|
|
29
|
+
external all4: ((t<'a>, t<'b>, t<'c>, t<'d>)) => t<('a, 'b, 'c, 'd)> = "all"
|
|
30
|
+
|
|
31
|
+
@scope("Promise") @val
|
|
32
|
+
external all5: ((t<'a>, t<'b>, t<'c>, t<'d>, t<'e>)) => t<('a, 'b, 'c, 'd, 'e)> = "all"
|
|
33
|
+
|
|
34
|
+
@scope("Promise") @val
|
|
35
|
+
external all6: ((t<'a>, t<'b>, t<'c>, t<'d>, t<'e>, t<'f>)) => t<('a, 'b, 'c, 'd, 'e, 'f)> = "all"
|
|
36
|
+
|
|
37
|
+
@send
|
|
38
|
+
external catch: (t<'a>, @uncurry exn => t<'a>) => t<'a> = "catch"
|
|
39
|
+
|
|
40
|
+
let catch = (promise: promise<'a>, callback: exn => promise<'a>): promise<'a> => {
|
|
41
|
+
catch(promise, err => {
|
|
42
|
+
callback(Js.Exn.anyToExnInternal(err))
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@scope("Promise") @val
|
|
47
|
+
external race: array<t<'a>> => t<'a> = "race"
|
|
48
|
+
|
|
49
|
+
external done: promise<'a> => unit = "%ignore"
|
|
50
|
+
|
|
51
|
+
external unsafe_async: 'a => promise<'a> = "%identity"
|
|
52
|
+
external unsafe_await: promise<'a> => 'a = "?await"
|