envio 3.13.0 → 3.14.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/bin.mjs +10 -1
- package/index.d.ts +11 -0
- package/package.json +8 -20
- package/rescript.json +1 -4
- package/src/Config.res +69 -100
- package/src/Config.res.mjs +50 -63
- package/src/Core.res +46 -6
- package/src/Core.res.mjs +41 -4
- package/src/EventConfigBuilder.res +4 -10
- package/src/EventConfigBuilder.res.mjs +1 -3
- package/src/ExitOnCaughtUp.res +5 -1
- package/src/ExitOnCaughtUp.res.mjs +8 -3
- package/src/HandlerLoader.res +74 -32
- package/src/HandlerLoader.res.mjs +69 -23
- package/src/HandlerTypeCheck.mjs +14 -0
- package/src/HandlerTypeCheckWorker.mjs +68 -0
- package/src/Internal.res +1 -1
- package/src/Main.res +17 -12
- package/src/Main.res.mjs +9 -3
- package/src/NodeVersion.mjs +13 -0
- package/src/Persistence.res +79 -38
- package/src/Persistence.res.mjs +41 -10
- package/src/PgStorage.res +62 -34
- package/src/PgStorage.res.mjs +65 -31
- package/src/ResumePlan.res +172 -0
- package/src/ResumePlan.res.mjs +122 -0
- package/src/Supervisor.res +8 -8
- package/src/Supervisor.res.mjs +6 -1
- package/src/TestIndexer.res +14 -4
- package/src/TestIndexer.res.mjs +3 -2
- package/src/TsModuleHooks.mjs +121 -0
- package/src/Utils.res +0 -8
- package/src/Worker.res +8 -0
- package/src/Worker.res.mjs +11 -0
- package/src/bindings/NodeJs.res +8 -7
- package/src/bindings/NodeJs.res.mjs +0 -3
- package/src/bindings/Pino.res +2 -2
- package/src/db/InternalTable.res +52 -2
- package/src/db/InternalTable.res.mjs +32 -3
- package/src/sources/FuelHyperSync.res +2 -0
- package/src/sources/FuelHyperSync.res.mjs +1 -0
- package/src/sources/FuelHyperSync.resi +1 -0
- package/src/sources/FuelHyperSyncClient.res +25 -8
- package/src/sources/FuelHyperSyncClient.res.mjs +8 -2
- package/src/sources/FuelHyperSyncSource.res +24 -22
- package/src/sources/FuelHyperSyncSource.res.mjs +18 -13
- package/src/tui/InitApi.res +85 -0
- package/src/tui/{components/CustomHooks.res.mjs → InitApi.res.mjs} +11 -64
- package/src/tui/Tui.res +142 -249
- package/src/tui/Tui.res.mjs +123 -332
- package/src/Js.shim.ts +0 -11
- package/src/bindings/DateFns.res +0 -74
- package/src/bindings/DateFns.res.mjs +0 -22
- package/src/sources/FuelSDK.res +0 -38
- package/src/sources/FuelSDK.res.mjs +0 -27
- package/src/sources/vendored-fuel-abi-coder.js +0 -1792
- package/src/tui/bindings/Ink.res +0 -369
- package/src/tui/bindings/Ink.res.mjs +0 -66
- package/src/tui/bindings/Style.res +0 -123
- package/src/tui/bindings/Style.res.mjs +0 -2
- package/src/tui/components/BufferedProgressBar.res +0 -40
- package/src/tui/components/BufferedProgressBar.res.mjs +0 -57
- package/src/tui/components/CustomHooks.res +0 -122
- package/src/tui/components/Messages.res +0 -40
- package/src/tui/components/Messages.res.mjs +0 -71
- package/src/tui/components/SyncETA.res +0 -179
- package/src/tui/components/SyncETA.res.mjs +0 -249
- package/src/tui/components/TuiData.res +0 -98
- package/src/tui/components/TuiData.res.mjs +0 -73
package/src/db/InternalTable.res
CHANGED
|
@@ -159,12 +159,14 @@ WHERE "${table.tableName}"."chain_id" = dead.chain_id
|
|
|
159
159
|
->Utils.Promise.ignoreValue
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
-
let makeGetRowsQuery = (~pgSchema) =>
|
|
162
|
+
let makeGetRowsQuery = (~pgSchema, ~onlyConfig=false) =>
|
|
163
163
|
`SELECT "chain_id" as "chainId",
|
|
164
164
|
"address" as "address",
|
|
165
165
|
"contract_id" as "contractId",
|
|
166
166
|
"registration_block" as "registrationBlock"
|
|
167
|
-
FROM "${pgSchema}"."${table.tableName}"
|
|
167
|
+
FROM "${pgSchema}"."${table.tableName}"${onlyConfig
|
|
168
|
+
? ` WHERE "registration_block" = ${AddressRows.configRegistrationBlock->Int.toString}`
|
|
169
|
+
: ""};`
|
|
168
170
|
}
|
|
169
171
|
|
|
170
172
|
module Chains = {
|
|
@@ -391,6 +393,54 @@ WHERE "${(#id: field :> string)}" = $2
|
|
|
391
393
|
checkpointId: string,
|
|
392
394
|
}
|
|
393
395
|
|
|
396
|
+
let readStoredChains = async (sql, ~pgSchema): array<ResumePlan.storedChain> => {
|
|
397
|
+
let (rows, configAddressRows) = await Promise.all2((
|
|
398
|
+
sql
|
|
399
|
+
->Postgres.unsafe(
|
|
400
|
+
`SELECT "${(#id: field :> string)}" as "id",
|
|
401
|
+
"${(#ecosystem: field :> string)}" as "ecosystem",
|
|
402
|
+
"${(#start_block: field :> string)}" as "startBlock",
|
|
403
|
+
"${(#end_block: field :> string)}" as "endBlock",
|
|
404
|
+
"${(#max_reorg_depth: field :> string)}" as "maxReorgDepth"
|
|
405
|
+
FROM "${pgSchema}"."${table.tableName}";`,
|
|
406
|
+
)
|
|
407
|
+
->(
|
|
408
|
+
Utils.magic: promise<array<unknown>> => promise<
|
|
409
|
+
array<{
|
|
410
|
+
"id": ChainId.t,
|
|
411
|
+
"ecosystem": string,
|
|
412
|
+
"startBlock": int,
|
|
413
|
+
"endBlock": Null.t<int>,
|
|
414
|
+
"maxReorgDepth": int,
|
|
415
|
+
}>,
|
|
416
|
+
>
|
|
417
|
+
),
|
|
418
|
+
sql
|
|
419
|
+
->Postgres.unsafe(EnvioAddresses.makeGetRowsQuery(~pgSchema, ~onlyConfig=true))
|
|
420
|
+
->(Utils.magic: promise<array<unknown>> => promise<array<AddressRows.row>>),
|
|
421
|
+
))
|
|
422
|
+
let configAddressesByChain = Dict.make()
|
|
423
|
+
configAddressRows->Array.forEach(addressRow =>
|
|
424
|
+
configAddressesByChain->Utils.Dict.push(
|
|
425
|
+
addressRow.chainId->ChainId.normalizeOrThrow->ChainId.toString,
|
|
426
|
+
addressRow,
|
|
427
|
+
)
|
|
428
|
+
)
|
|
429
|
+
rows->Array.map((row): ResumePlan.storedChain => {
|
|
430
|
+
let id = row["id"]->ChainId.normalizeOrThrow
|
|
431
|
+
{
|
|
432
|
+
id,
|
|
433
|
+
ecosystem: row["ecosystem"],
|
|
434
|
+
startBlock: row["startBlock"],
|
|
435
|
+
endBlock: row["endBlock"]->Null.toOption,
|
|
436
|
+
maxReorgDepth: row["maxReorgDepth"],
|
|
437
|
+
configAddresses: configAddressesByChain
|
|
438
|
+
->Utils.Dict.dangerouslyGetNonOption(id->ChainId.toString)
|
|
439
|
+
->Option.getOr([]),
|
|
440
|
+
}
|
|
441
|
+
})
|
|
442
|
+
}
|
|
443
|
+
|
|
394
444
|
let makeGetInitialStateQuery = (~pgSchema) => {
|
|
395
445
|
`SELECT "${(#id: field :> string)}" as "id",
|
|
396
446
|
"${(#start_block: field :> string)}" as "startBlock",
|
|
@@ -133,12 +133,15 @@ function $$delete(sql, pgSchema, keys, chainIdModeOpt) {
|
|
|
133
133
|
], {prepare: true});
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
function makeGetRowsQuery(pgSchema) {
|
|
136
|
+
function makeGetRowsQuery(pgSchema, onlyConfigOpt) {
|
|
137
|
+
let onlyConfig = onlyConfigOpt !== undefined ? onlyConfigOpt : false;
|
|
137
138
|
return `SELECT "chain_id" as "chainId",
|
|
138
139
|
"address" as "address",
|
|
139
140
|
"contract_id" as "contractId",
|
|
140
141
|
"registration_block" as "registrationBlock"
|
|
141
|
-
FROM "` + pgSchema + `"."` + table$1.tableName + `"
|
|
142
|
+
FROM "` + pgSchema + `"."` + table$1.tableName + `"` + (
|
|
143
|
+
onlyConfig ? ` WHERE "registration_block" = ` + AddressRows.configRegistrationBlock.toString() : ""
|
|
144
|
+
) + `;`;
|
|
142
145
|
}
|
|
143
146
|
|
|
144
147
|
let EnvioAddresses = {
|
|
@@ -264,6 +267,31 @@ WHERE "` + "id" + `" = $2
|
|
|
264
267
|
AND "` + "ready_at" + `" IS NULL;`;
|
|
265
268
|
}
|
|
266
269
|
|
|
270
|
+
async function readStoredChains(sql, pgSchema) {
|
|
271
|
+
let match = await Promise.all([
|
|
272
|
+
sql.unsafe(`SELECT "` + "id" + `" as "id",
|
|
273
|
+
"` + "ecosystem" + `" as "ecosystem",
|
|
274
|
+
"` + "start_block" + `" as "startBlock",
|
|
275
|
+
"` + "end_block" + `" as "endBlock",
|
|
276
|
+
"` + "max_reorg_depth" + `" as "maxReorgDepth"
|
|
277
|
+
FROM "` + pgSchema + `"."` + table$2.tableName + `";`),
|
|
278
|
+
sql.unsafe(makeGetRowsQuery(pgSchema, true))
|
|
279
|
+
]);
|
|
280
|
+
let configAddressesByChain = {};
|
|
281
|
+
match[1].forEach(addressRow => Utils.Dict.push(configAddressesByChain, ChainId.toString(ChainId.normalizeOrThrow(addressRow.chainId)), addressRow));
|
|
282
|
+
return match[0].map(row => {
|
|
283
|
+
let id = ChainId.normalizeOrThrow(row.id);
|
|
284
|
+
return {
|
|
285
|
+
id: id,
|
|
286
|
+
ecosystem: row.ecosystem,
|
|
287
|
+
startBlock: row.startBlock,
|
|
288
|
+
endBlock: Primitive_option.fromNull(row.endBlock),
|
|
289
|
+
maxReorgDepth: row.maxReorgDepth,
|
|
290
|
+
configAddresses: Stdlib_Option.getOr(configAddressesByChain[ChainId.toString(id)], [])
|
|
291
|
+
};
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
|
|
267
295
|
function makeGetInitialStateQuery(pgSchema) {
|
|
268
296
|
return `SELECT "` + "id" + `" as "id",
|
|
269
297
|
"` + "start_block" + `" as "startBlock",
|
|
@@ -282,7 +310,7 @@ FROM "` + pgSchema + `"."` + table$2.tableName + `";`;
|
|
|
282
310
|
async function getInitialState(sql, pgSchema) {
|
|
283
311
|
let match = await Promise.all([
|
|
284
312
|
sql.unsafe(makeGetInitialStateQuery(pgSchema)),
|
|
285
|
-
sql.unsafe(makeGetRowsQuery(pgSchema))
|
|
313
|
+
sql.unsafe(makeGetRowsQuery(pgSchema, undefined))
|
|
286
314
|
]);
|
|
287
315
|
let addressRowsByChainId = AddressRows.group(match[1]);
|
|
288
316
|
return match[0].map(rawInitialState => {
|
|
@@ -384,6 +412,7 @@ let Chains = {
|
|
|
384
412
|
metaFields: metaFields,
|
|
385
413
|
makeMetaFieldsUpdateQuery: makeMetaFieldsUpdateQuery,
|
|
386
414
|
makeSetReadyAtQuery: makeSetReadyAtQuery,
|
|
415
|
+
readStoredChains: readStoredChains,
|
|
387
416
|
makeGetInitialStateQuery: makeGetInitialStateQuery,
|
|
388
417
|
getInitialState: getInitialState,
|
|
389
418
|
blockTimeToDb: blockTimeToDb,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
type logsQueryPage = {
|
|
2
2
|
items: array<FuelHyperSyncClient.EventItems.item>,
|
|
3
|
+
rejectedLogData: array<FuelHyperSyncClient.EventItems.rejectedLogData>,
|
|
3
4
|
// Blocks referenced by `items`, one per height.
|
|
4
5
|
nextBlock: int,
|
|
5
6
|
archiveHeight: int,
|
|
@@ -72,6 +73,7 @@ module GetLogs = {
|
|
|
72
73
|
}
|
|
73
74
|
{
|
|
74
75
|
items: res.items,
|
|
76
|
+
rejectedLogData: res.rejectedLogData,
|
|
75
77
|
nextBlock: res.nextBlock,
|
|
76
78
|
archiveHeight: res.archiveHeight->Option.getOr(0), // TODO: FIXME: Shouldn't have a default here
|
|
77
79
|
blockStore,
|
|
@@ -64,6 +64,7 @@ async function query(client, fromBlock, toBlock, registrationIndexes, addressSet
|
|
|
64
64
|
}
|
|
65
65
|
return {
|
|
66
66
|
items: res.items,
|
|
67
|
+
rejectedLogData: res.rejectedLogData,
|
|
67
68
|
nextBlock: res.nextBlock,
|
|
68
69
|
archiveHeight: Stdlib_Option.getOr(res.archiveHeight, 0),
|
|
69
70
|
blockStore: match[1]
|
|
@@ -27,6 +27,9 @@ module Registration = {
|
|
|
27
27
|
kind: kind,
|
|
28
28
|
// The LogData `rb` value as a decimal string; absent for other kinds.
|
|
29
29
|
logId?: string,
|
|
30
|
+
// The contract's Fuel ABI, which LogData receipts are decoded against in
|
|
31
|
+
// Rust; absent for other kinds.
|
|
32
|
+
abi?: JSON.t,
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
let fromOnEventRegistrations = (
|
|
@@ -35,12 +38,12 @@ module Registration = {
|
|
|
35
38
|
onEventRegistrations->Array.map(reg => {
|
|
36
39
|
let eventConfig =
|
|
37
40
|
reg.eventConfig->(Utils.magic: Internal.eventConfig => Internal.fuelEventConfig)
|
|
38
|
-
let (kind, logId) = switch eventConfig.kind {
|
|
39
|
-
| LogData({logId}) => (LogData, Some(logId))
|
|
40
|
-
| Mint => (Mint, None)
|
|
41
|
-
| Burn => (Burn, None)
|
|
42
|
-
| Transfer => (Transfer, None)
|
|
43
|
-
| Call => (Call, None)
|
|
41
|
+
let (kind, logId, abi) = switch eventConfig.kind {
|
|
42
|
+
| LogData({logId, abi}) => (LogData, Some(logId), Some(abi))
|
|
43
|
+
| Mint => (Mint, None, None)
|
|
44
|
+
| Burn => (Burn, None, None)
|
|
45
|
+
| Transfer => (Transfer, None, None)
|
|
46
|
+
| Call => (Call, None, None)
|
|
44
47
|
}
|
|
45
48
|
{
|
|
46
49
|
index: reg.index,
|
|
@@ -50,6 +53,7 @@ module Registration = {
|
|
|
50
53
|
startBlock: reg.startBlock,
|
|
51
54
|
kind,
|
|
52
55
|
?logId,
|
|
56
|
+
?abi,
|
|
53
57
|
}
|
|
54
58
|
})
|
|
55
59
|
}
|
|
@@ -70,7 +74,8 @@ module EventItems = {
|
|
|
70
74
|
}
|
|
71
75
|
|
|
72
76
|
// One routed receipt with its kind-specific columns flattened: LogData
|
|
73
|
-
// carries `
|
|
77
|
+
// carries `params` decoded against the ABI (a receipt its logged type
|
|
78
|
+
// rejects is dropped in Rust), Mint/Burn carry `val`/`subId`,
|
|
74
79
|
// Transfer/TransferOut/Call carry `amount`/`assetId`/`to` (TransferOut's
|
|
75
80
|
// wallet recipient normalised into `to`).
|
|
76
81
|
type item = {
|
|
@@ -79,7 +84,7 @@ module EventItems = {
|
|
|
79
84
|
txId: string,
|
|
80
85
|
blockHeight: int,
|
|
81
86
|
srcAddress: Address.t,
|
|
82
|
-
|
|
87
|
+
params?: Internal.eventParams,
|
|
83
88
|
subId?: string,
|
|
84
89
|
val?: bigint,
|
|
85
90
|
amount?: bigint,
|
|
@@ -87,10 +92,22 @@ module EventItems = {
|
|
|
87
92
|
to?: string,
|
|
88
93
|
}
|
|
89
94
|
|
|
95
|
+
// The page's first LogData receipt a contract-bound registration's ABI
|
|
96
|
+
// rejected, with how many it rejected. The receipts themselves are dropped.
|
|
97
|
+
type rejectedLogData = {
|
|
98
|
+
onEventRegistrationIndex: int,
|
|
99
|
+
blockHeight: int,
|
|
100
|
+
receiptIndex: int,
|
|
101
|
+
txId: string,
|
|
102
|
+
dataLength: int,
|
|
103
|
+
count: int,
|
|
104
|
+
}
|
|
105
|
+
|
|
90
106
|
type response = {
|
|
91
107
|
archiveHeight: option<int>,
|
|
92
108
|
nextBlock: int,
|
|
93
109
|
items: array<item>,
|
|
110
|
+
rejectedLogData: array<rejectedLogData>,
|
|
94
111
|
}
|
|
95
112
|
}
|
|
96
113
|
|
|
@@ -13,24 +13,28 @@ function fromOnEventRegistrations(onEventRegistrations) {
|
|
|
13
13
|
case "Mint" :
|
|
14
14
|
match$1 = [
|
|
15
15
|
"Mint",
|
|
16
|
+
undefined,
|
|
16
17
|
undefined
|
|
17
18
|
];
|
|
18
19
|
break;
|
|
19
20
|
case "Burn" :
|
|
20
21
|
match$1 = [
|
|
21
22
|
"Burn",
|
|
23
|
+
undefined,
|
|
22
24
|
undefined
|
|
23
25
|
];
|
|
24
26
|
break;
|
|
25
27
|
case "Transfer" :
|
|
26
28
|
match$1 = [
|
|
27
29
|
"Transfer",
|
|
30
|
+
undefined,
|
|
28
31
|
undefined
|
|
29
32
|
];
|
|
30
33
|
break;
|
|
31
34
|
case "Call" :
|
|
32
35
|
match$1 = [
|
|
33
36
|
"Call",
|
|
37
|
+
undefined,
|
|
34
38
|
undefined
|
|
35
39
|
];
|
|
36
40
|
break;
|
|
@@ -38,7 +42,8 @@ function fromOnEventRegistrations(onEventRegistrations) {
|
|
|
38
42
|
} else {
|
|
39
43
|
match$1 = [
|
|
40
44
|
"LogData",
|
|
41
|
-
match.logId
|
|
45
|
+
match.logId,
|
|
46
|
+
match.abi
|
|
42
47
|
];
|
|
43
48
|
}
|
|
44
49
|
return {
|
|
@@ -48,7 +53,8 @@ function fromOnEventRegistrations(onEventRegistrations) {
|
|
|
48
53
|
isWildcard: reg.isWildcard,
|
|
49
54
|
startBlock: reg.startBlock,
|
|
50
55
|
kind: match$1[0],
|
|
51
|
-
logId: match$1[1]
|
|
56
|
+
logId: match$1[1],
|
|
57
|
+
abi: match$1[2]
|
|
52
58
|
};
|
|
53
59
|
});
|
|
54
60
|
}
|
|
@@ -16,6 +16,9 @@ let make = ({chainId, endpointUrl, apiToken, onEventRegistrations, addressStore}
|
|
|
16
16
|
// Per source, so one rejected token is reported once rather than on every
|
|
17
17
|
// height retry for the life of the process.
|
|
18
18
|
let unauthorizedWarned = ref(false)
|
|
19
|
+
// Registration indexes already warned about undecodable LogData — a stale
|
|
20
|
+
// ABI rejects every receipt, so one line per event is enough.
|
|
21
|
+
let rejectedLogDataWarned = Utils.Set.make()
|
|
19
22
|
|
|
20
23
|
let apiToken = apiToken->HyperSync.requireApiToken
|
|
21
24
|
|
|
@@ -106,6 +109,24 @@ let make = ({chainId, endpointUrl, apiToken, onEventRegistrations, addressStore}
|
|
|
106
109
|
|
|
107
110
|
let parsingTimeRef = Performance.now()
|
|
108
111
|
|
|
112
|
+
pageUnsafe.rejectedLogData->Array.forEach(rejected => {
|
|
113
|
+
if !(rejectedLogDataWarned->Utils.Set.has(rejected.onEventRegistrationIndex)) {
|
|
114
|
+
rejectedLogDataWarned->Utils.Set.add(rejected.onEventRegistrationIndex)->ignore
|
|
115
|
+
let eventConfig = (
|
|
116
|
+
onEventRegistrations->Array.getUnsafe(rejected.onEventRegistrationIndex)
|
|
117
|
+
).eventConfig
|
|
118
|
+
logger->Logging.childWarn({
|
|
119
|
+
"msg": `Skipped ${eventConfig.contractName}.${eventConfig.name} LogData receipts whose data doesn't decode against the contract ABI. Check that the ABI matches the deployed contract.`,
|
|
120
|
+
"chainId": chainId,
|
|
121
|
+
"blockNumber": rejected.blockHeight,
|
|
122
|
+
"logIndex": rejected.receiptIndex,
|
|
123
|
+
"txId": rejected.txId,
|
|
124
|
+
"dataLength": rejected.dataLength,
|
|
125
|
+
"skippedInPage": rejected.count,
|
|
126
|
+
})
|
|
127
|
+
}
|
|
128
|
+
})
|
|
129
|
+
|
|
109
130
|
let parsedQueueItems = pageUnsafe.items->Array.map(item => {
|
|
110
131
|
// Routing happened in Rust; the item references its registration by
|
|
111
132
|
// chain-scoped index.
|
|
@@ -116,24 +137,8 @@ let make = ({chainId, endpointUrl, apiToken, onEventRegistrations, addressStore}
|
|
|
116
137
|
)
|
|
117
138
|
|
|
118
139
|
let params = switch eventConfig.kind {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
// crosses the boundary.
|
|
122
|
-
let data = item.data->Option.getOr("")
|
|
123
|
-
try decode(data) catch {
|
|
124
|
-
| exn => {
|
|
125
|
-
let params = {
|
|
126
|
-
"chainId": chainId,
|
|
127
|
-
"blockNumber": item.blockHeight,
|
|
128
|
-
"logIndex": item.receiptIndex,
|
|
129
|
-
}
|
|
130
|
-
let logger = Logging.createChildFrom(~logger, ~params)
|
|
131
|
-
exn->ErrorHandling.mkLogAndRaise(
|
|
132
|
-
~msg="Failed to decode Fuel LogData receipt, please double check your ABI.",
|
|
133
|
-
~logger,
|
|
134
|
-
)
|
|
135
|
-
}
|
|
136
|
-
}
|
|
140
|
+
// Rust only routes a LogData receipt once its data decoded.
|
|
141
|
+
| LogData(_) => item.params->Option.getUnsafe
|
|
137
142
|
| Mint | Burn =>
|
|
138
143
|
(
|
|
139
144
|
{
|
|
@@ -213,10 +218,7 @@ let make = ({chainId, endpointUrl, apiToken, onEventRegistrations, addressStore}
|
|
|
213
218
|
let timerRef = Performance.now()
|
|
214
219
|
let height = try await client->FuelHyperSyncClient.getHeight catch {
|
|
215
220
|
| exn =>
|
|
216
|
-
exn->HyperSync.rethrowLoggingUnauthorized(
|
|
217
|
-
~warned=unauthorizedWarned,
|
|
218
|
-
~product="HyperFuel",
|
|
219
|
-
)
|
|
221
|
+
exn->HyperSync.rethrowLoggingUnauthorized(~warned=unauthorizedWarned, ~product="HyperFuel")
|
|
220
222
|
}
|
|
221
223
|
let seconds = timerRef->Performance.secondsSince
|
|
222
224
|
{height, requestStats: [{method: "getHeight", seconds}]}
|
|
@@ -18,6 +18,7 @@ function make(param) {
|
|
|
18
18
|
let unauthorizedWarned = {
|
|
19
19
|
contents: false
|
|
20
20
|
};
|
|
21
|
+
let rejectedLogDataWarned = new Set();
|
|
21
22
|
let apiToken = HyperSync.requireApiToken(param.apiToken);
|
|
22
23
|
let client;
|
|
23
24
|
try {
|
|
@@ -82,6 +83,22 @@ function make(param) {
|
|
|
82
83
|
let knownHeight$1 = pageUnsafe.archiveHeight;
|
|
83
84
|
let heighestBlockQueried = pageUnsafe.nextBlock - 1 | 0;
|
|
84
85
|
let parsingTimeRef = Performance.now();
|
|
86
|
+
pageUnsafe.rejectedLogData.forEach(rejected => {
|
|
87
|
+
if (rejectedLogDataWarned.has(rejected.onEventRegistrationIndex)) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
rejectedLogDataWarned.add(rejected.onEventRegistrationIndex);
|
|
91
|
+
let eventConfig = onEventRegistrations[rejected.onEventRegistrationIndex].eventConfig;
|
|
92
|
+
Logging.childWarn(logger, {
|
|
93
|
+
msg: `Skipped ` + eventConfig.contractName + `.` + eventConfig.name + ` LogData receipts whose data doesn't decode against the contract ABI. Check that the ABI matches the deployed contract.`,
|
|
94
|
+
chainId: chainId,
|
|
95
|
+
blockNumber: rejected.blockHeight,
|
|
96
|
+
logIndex: rejected.receiptIndex,
|
|
97
|
+
txId: rejected.txId,
|
|
98
|
+
dataLength: rejected.dataLength,
|
|
99
|
+
skippedInPage: rejected.count
|
|
100
|
+
});
|
|
101
|
+
});
|
|
85
102
|
let parsedQueueItems = pageUnsafe.items.map(item => {
|
|
86
103
|
let onEventRegistration = onEventRegistrations[item.onEventRegistrationIndex];
|
|
87
104
|
let eventConfig = onEventRegistration.eventConfig;
|
|
@@ -100,19 +117,7 @@ function make(param) {
|
|
|
100
117
|
break;
|
|
101
118
|
}
|
|
102
119
|
} else {
|
|
103
|
-
|
|
104
|
-
try {
|
|
105
|
-
params = match.decode(data);
|
|
106
|
-
} catch (raw_exn) {
|
|
107
|
-
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
108
|
-
let params$1 = {
|
|
109
|
-
chainId: chainId,
|
|
110
|
-
blockNumber: item.blockHeight,
|
|
111
|
-
logIndex: item.receiptIndex
|
|
112
|
-
};
|
|
113
|
-
let logger$1 = Logging.createChildFrom(logger, params$1);
|
|
114
|
-
params = ErrorHandling.mkLogAndRaise(logger$1, "Failed to decode Fuel LogData receipt, please double check your ABI.", exn);
|
|
115
|
-
}
|
|
120
|
+
params = item.params;
|
|
116
121
|
}
|
|
117
122
|
switch (exit) {
|
|
118
123
|
case 1 :
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
type ecosystem = | @as("evm") Evm | @as("fuel") Fuel | @as("svm") Svm
|
|
2
|
+
type body = {
|
|
3
|
+
envioVersion: string,
|
|
4
|
+
envioApiToken: option<string>,
|
|
5
|
+
ecosystem: ecosystem,
|
|
6
|
+
hyperSyncNetworks: array<ChainId.t>,
|
|
7
|
+
rpcNetworks: array<ChainId.t>,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
let bodySchema = S.object(s => {
|
|
11
|
+
envioVersion: s.field("envioVersion", S.string),
|
|
12
|
+
envioApiToken: s.field("envioApiToken", S.option(S.string)),
|
|
13
|
+
ecosystem: s.field("ecosystem", S.enum([Evm, Fuel, Svm])),
|
|
14
|
+
hyperSyncNetworks: s.field("hyperSyncNetworks", S.array(ChainId.schema)),
|
|
15
|
+
rpcNetworks: s.field("rpcNetworks", S.array(ChainId.schema)),
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
let makeBody = (~envioVersion, ~envioApiToken, ~config: Config.t) => {
|
|
19
|
+
let hyperSyncNetworks = []
|
|
20
|
+
let rpcNetworks = []
|
|
21
|
+
config.chainMap
|
|
22
|
+
->ChainMap.values
|
|
23
|
+
->Array.forEach(({sourceConfig, id}) => {
|
|
24
|
+
let usesHyperSync = switch sourceConfig {
|
|
25
|
+
| Config.EvmSourceConfig({hypersync: Some(_)}) => true
|
|
26
|
+
| Config.EvmSourceConfig({hypersync: None}) => false
|
|
27
|
+
| Config.FuelSourceConfig(_) => true // Fuel always uses HyperFuel
|
|
28
|
+
| Config.SvmSourceConfig(_) => false
|
|
29
|
+
| Config.SimulateSourceConfig(_) => false
|
|
30
|
+
| Config.CustomSources(sources) => sources->Array.some(s => s.poweredByHyperSync)
|
|
31
|
+
}
|
|
32
|
+
switch usesHyperSync {
|
|
33
|
+
| true => hyperSyncNetworks
|
|
34
|
+
| false => rpcNetworks
|
|
35
|
+
}
|
|
36
|
+
->Array.push(id)
|
|
37
|
+
->ignore
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
{
|
|
41
|
+
envioVersion,
|
|
42
|
+
envioApiToken,
|
|
43
|
+
ecosystem: (config.ecosystem.name :> ecosystem),
|
|
44
|
+
hyperSyncNetworks,
|
|
45
|
+
rpcNetworks,
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
type messageColor =
|
|
50
|
+
| @as("primary") Primary
|
|
51
|
+
| @as("secondary") Secondary
|
|
52
|
+
| @as("info") Info
|
|
53
|
+
| @as("danger") Danger
|
|
54
|
+
| @as("success") Success
|
|
55
|
+
| @as("white") White
|
|
56
|
+
| @as("gray") Gray
|
|
57
|
+
|
|
58
|
+
type message = {
|
|
59
|
+
color: messageColor,
|
|
60
|
+
content: string,
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
let messageSchema = S.object(s => {
|
|
64
|
+
color: s.field("color", S.enum([Primary, Secondary, Info, Danger, Success, White, Gray])),
|
|
65
|
+
content: s.field("content", S.string),
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
let client = Rest.client(Env.envioAppUrl ++ "/api")
|
|
69
|
+
|
|
70
|
+
let route = Rest.route(() => {
|
|
71
|
+
method: Post,
|
|
72
|
+
path: "/hyperindex/init",
|
|
73
|
+
input: s => s.body(bodySchema),
|
|
74
|
+
responses: [s => s.field("messages", S.array(messageSchema))],
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
let getMessages = async (~config) => {
|
|
78
|
+
let envioVersion = Utils.EnvioPackage.value.version
|
|
79
|
+
let body = makeBody(~envioVersion, ~envioApiToken=Env.envioApiToken, ~config)
|
|
80
|
+
|
|
81
|
+
switch await route->Rest.fetch(body, ~client) {
|
|
82
|
+
| exception exn => Error(exn)
|
|
83
|
+
| messages => Ok(messages)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
|
-
import * as Env from "
|
|
4
|
-
import * as Rest from "
|
|
5
|
-
import * as Utils from "
|
|
6
|
-
import * as
|
|
7
|
-
import * as
|
|
8
|
-
import * as Logging from "../../Logging.res.mjs";
|
|
9
|
-
import * as ChainMap from "../../ChainMap.res.mjs";
|
|
3
|
+
import * as Env from "../Env.res.mjs";
|
|
4
|
+
import * as Rest from "../vendored/Rest.res.mjs";
|
|
5
|
+
import * as Utils from "../Utils.res.mjs";
|
|
6
|
+
import * as ChainId from "../ChainId.res.mjs";
|
|
7
|
+
import * as ChainMap from "../ChainMap.res.mjs";
|
|
10
8
|
import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
|
|
11
9
|
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
12
10
|
|
|
@@ -56,25 +54,6 @@ function makeBody(envioVersion, envioApiToken, config) {
|
|
|
56
54
|
};
|
|
57
55
|
}
|
|
58
56
|
|
|
59
|
-
function toTheme(color) {
|
|
60
|
-
switch (color) {
|
|
61
|
-
case "primary" :
|
|
62
|
-
return "#9860E5";
|
|
63
|
-
case "secondary" :
|
|
64
|
-
return "#FFBB2F";
|
|
65
|
-
case "info" :
|
|
66
|
-
return "#6CBFEE";
|
|
67
|
-
case "danger" :
|
|
68
|
-
return "#FF8269";
|
|
69
|
-
case "success" :
|
|
70
|
-
return "#3B8C3D";
|
|
71
|
-
case "white" :
|
|
72
|
-
return "white";
|
|
73
|
-
case "gray" :
|
|
74
|
-
return "gray";
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
57
|
let messageSchema = S$RescriptSchema.object(s => ({
|
|
79
58
|
color: s.f("color", S$RescriptSchema.$$enum([
|
|
80
59
|
"primary",
|
|
@@ -118,44 +97,12 @@ async function getMessages(config) {
|
|
|
118
97
|
};
|
|
119
98
|
}
|
|
120
99
|
|
|
121
|
-
let InitApi = {
|
|
122
|
-
bodySchema: bodySchema,
|
|
123
|
-
makeBody: makeBody,
|
|
124
|
-
toTheme: toTheme,
|
|
125
|
-
messageSchema: messageSchema,
|
|
126
|
-
client: client,
|
|
127
|
-
route: route,
|
|
128
|
-
getMessages: getMessages
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
function useMessages(config) {
|
|
132
|
-
let match = React.useState(() => "Loading");
|
|
133
|
-
let setRequest = match[1];
|
|
134
|
-
React.useEffect(() => {
|
|
135
|
-
getMessages(config).then(res => {
|
|
136
|
-
if (res.TAG === "Ok") {
|
|
137
|
-
let data = res._0;
|
|
138
|
-
return setRequest(param => ({
|
|
139
|
-
TAG: "Data",
|
|
140
|
-
_0: data
|
|
141
|
-
}));
|
|
142
|
-
}
|
|
143
|
-
let e = res._0;
|
|
144
|
-
Logging.error({
|
|
145
|
-
msg: "Failed to load messages from envio server",
|
|
146
|
-
err: Utils.prettifyExn(e)
|
|
147
|
-
});
|
|
148
|
-
setRequest(param => ({
|
|
149
|
-
TAG: "Err",
|
|
150
|
-
_0: e
|
|
151
|
-
}));
|
|
152
|
-
});
|
|
153
|
-
}, []);
|
|
154
|
-
return match[0];
|
|
155
|
-
}
|
|
156
|
-
|
|
157
100
|
export {
|
|
158
|
-
|
|
159
|
-
|
|
101
|
+
bodySchema,
|
|
102
|
+
makeBody,
|
|
103
|
+
messageSchema,
|
|
104
|
+
client,
|
|
105
|
+
route,
|
|
106
|
+
getMessages,
|
|
160
107
|
}
|
|
161
108
|
/* bodySchema Not a pure module */
|