@eclesia/indexer-engine 2.3.1
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/dist/emitter/index.d.ts +16 -0
- package/dist/emitter/index.d.ts.map +1 -0
- package/dist/emitter/index.js +62 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +44 -0
- package/dist/indexer/index.d.ts +50 -0
- package/dist/indexer/index.d.ts.map +1 -0
- package/dist/indexer/index.js +629 -0
- package/dist/promise-queue/index.d.ts +17 -0
- package/dist/promise-queue/index.d.ts.map +1 -0
- package/dist/promise-queue/index.js +75 -0
- package/dist/types/index.d.ts +97 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/utils/bech32.d.ts +5 -0
- package/dist/utils/bech32.d.ts.map +1 -0
- package/dist/utils/bech32.js +25 -0
- package/dist/utils/bigint.d.ts +3 -0
- package/dist/utils/bigint.d.ts.map +1 -0
- package/dist/utils/bigint.js +8 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +19 -0
- package/dist/utils/text.d.ts +2 -0
- package/dist/utils/text.d.ts.map +1 -0
- package/dist/utils/text.js +12 -0
- package/package.json +50 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { WithHeightAndUUID } from "../types";
|
|
2
|
+
export declare class EclesiaEmitter {
|
|
3
|
+
private emitter;
|
|
4
|
+
handled: Map<string, number>;
|
|
5
|
+
constructor();
|
|
6
|
+
emit<EType extends keyof (WithHeightAndUUID<EventMap>) & string>(eventName: EType, eventArg: WithHeightAndUUID<EventMap>[EType] & {
|
|
7
|
+
uuid?: string;
|
|
8
|
+
}): void;
|
|
9
|
+
on<TEventName extends keyof WithHeightAndUUID<EventMap> & string | "_unhandled">(eventName: TEventName, handler: TEventName extends "_unhandled" ? (eventArg: {
|
|
10
|
+
type: string;
|
|
11
|
+
event: unknown;
|
|
12
|
+
uuid: string;
|
|
13
|
+
}) => void : (eventArg: TEventName extends keyof WithHeightAndUUID<EventMap> ? WithHeightAndUUID<EventMap>[TEventName] : never) => void): void;
|
|
14
|
+
off<TEventName extends keyof WithHeightAndUUID<EventMap> & string>(eventName: TEventName, handler: (eventArg: WithHeightAndUUID<EventMap>[TEventName]) => void): void;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/emitter/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAE7C,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAsB;IAE9B,OAAO,sBAA6B;;IAM3C,IAAI,CAAC,KAAK,SAAS,MAAM,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,GAAG,MAAM,EAC7D,SAAS,EAAE,KAAK,EAChB,QAAQ,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE;IAYlE,EAAE,CAAC,UAAU,SAAS,MAAM,iBAAiB,CAAC,QAAQ,CAAC,GAAG,MAAM,GAAG,YAAY,EAAE,SAAS,EAAE,UAAU,EACpG,OAAO,EAAE,UAAU,SAAS,YAAY,GACpC,CAAC,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAC1B,KAAK,EAAE,OAAO,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;KAAE,KAAK,IAAI,GACxB,CAAC,QAAQ,EAAE,UAAU,SAAS,MAAM,iBAAiB,CAAC,QAAQ,CAAC,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC,UAAU,CAAC,GAAG,KAAK,KAAK,IAAI;IAwBhI,GAAG,CAAC,UAAU,SAAS,MAAM,iBAAiB,CAAC,QAAQ,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,UAAU,EACtF,OAAO,EAAE,CAAC,QAAQ,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAC,UAAU,CAAC,KAAK,IAAI;CASvE"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.EclesiaEmitter = void 0;
|
|
7
|
+
const events_1 = __importDefault(require("events"));
|
|
8
|
+
class EclesiaEmitter {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.emitter = new events_1.default();
|
|
11
|
+
this.handled = new Map();
|
|
12
|
+
this.emitter.setMaxListeners(0);
|
|
13
|
+
}
|
|
14
|
+
emit(eventName, eventArg) {
|
|
15
|
+
if (this.handled.has(eventName)) {
|
|
16
|
+
this.emitter.emit(eventName, eventArg);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
this.emitter.emit("_unhandled", {
|
|
20
|
+
type: eventName,
|
|
21
|
+
event: eventArg,
|
|
22
|
+
uuid: eventArg.uuid
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
on(eventName, handler) {
|
|
27
|
+
const count = this.handled.get(eventName);
|
|
28
|
+
if (count) {
|
|
29
|
+
this.handled.set(eventName, count + 1);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
this.handled.set(eventName, 1);
|
|
33
|
+
}
|
|
34
|
+
this.emitter.on(eventName, async (eventData) => {
|
|
35
|
+
try {
|
|
36
|
+
await handler(eventData);
|
|
37
|
+
if (eventName !== "uuid" && eventName !== "_unhandled" && eventData.uuid) {
|
|
38
|
+
this.emit("uuid", { status: true,
|
|
39
|
+
uuid: eventData.uuid });
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
if (eventName !== "uuid" && eventName !== "_unhandled" && eventData.uuid) {
|
|
44
|
+
this.emit("uuid", { status: false,
|
|
45
|
+
error: error,
|
|
46
|
+
uuid: eventData.uuid });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
off(eventName, handler) {
|
|
52
|
+
const count = this.handled.get(eventName);
|
|
53
|
+
if (count && count > 1) {
|
|
54
|
+
this.handled.set(eventName, count - 1);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
this.handled.delete(eventName);
|
|
58
|
+
}
|
|
59
|
+
this.emitter.off(eventName, handler);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
exports.EclesiaEmitter = EclesiaEmitter;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,OAAO,KAAK,KAAK,MAAM,SAAS,CAAC;AACjC,OAAO,KAAK,KAAK,MAAM,SAAS,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
19
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
20
|
+
};
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.Utils = exports.Types = void 0;
|
|
40
|
+
__exportStar(require("./emitter"), exports);
|
|
41
|
+
__exportStar(require("./indexer"), exports);
|
|
42
|
+
__exportStar(require("./promise-queue"), exports);
|
|
43
|
+
exports.Types = __importStar(require("./types"));
|
|
44
|
+
exports.Utils = __importStar(require("./utils"));
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { CometClient } from "@cosmjs/tendermint-rpc";
|
|
2
|
+
import winston from "winston";
|
|
3
|
+
import { EclesiaEmitter } from "../emitter";
|
|
4
|
+
import { EcleciaIndexerConfig, EmitFunc, WithHeightAndUUID } from "../types";
|
|
5
|
+
export declare const defaultIndexerConfig: {
|
|
6
|
+
startHeight: number;
|
|
7
|
+
batchSize: number;
|
|
8
|
+
modules: never[];
|
|
9
|
+
getNextHeight: () => number;
|
|
10
|
+
logLevel: EcleciaIndexerConfig["logLevel"];
|
|
11
|
+
usePolling: boolean;
|
|
12
|
+
pollingInterval: number;
|
|
13
|
+
processGenesis: boolean;
|
|
14
|
+
minimal: boolean;
|
|
15
|
+
init: () => Promise<void>;
|
|
16
|
+
beginTransaction: () => Promise<void>;
|
|
17
|
+
endTransaction: (_status: boolean) => Promise<void>;
|
|
18
|
+
};
|
|
19
|
+
export declare class EcleciaIndexer extends EclesiaEmitter {
|
|
20
|
+
private config;
|
|
21
|
+
private fastify;
|
|
22
|
+
private blockQueue;
|
|
23
|
+
private latestHeight;
|
|
24
|
+
private heightToProcess;
|
|
25
|
+
private initialized;
|
|
26
|
+
private retryCount;
|
|
27
|
+
client: CometClient;
|
|
28
|
+
log: winston.Logger;
|
|
29
|
+
private debugTime;
|
|
30
|
+
private healthCheck;
|
|
31
|
+
private subscription;
|
|
32
|
+
constructor(config: EcleciaIndexerConfig);
|
|
33
|
+
private setStatus;
|
|
34
|
+
private blockListener;
|
|
35
|
+
private isMinimal;
|
|
36
|
+
connect(): Promise<boolean>;
|
|
37
|
+
private debugTimes;
|
|
38
|
+
start(): Promise<void>;
|
|
39
|
+
asyncEmit: EmitFunc<keyof WithHeightAndUUID<EventMap>>;
|
|
40
|
+
private processBlock;
|
|
41
|
+
private fetcher;
|
|
42
|
+
callABCI(path: string, data: Uint8Array, height?: number): Promise<Uint8Array<ArrayBufferLike>>;
|
|
43
|
+
private newBlockReceived;
|
|
44
|
+
private pollForBlock;
|
|
45
|
+
private readGenesis;
|
|
46
|
+
private setArrayReader;
|
|
47
|
+
private setValueReader;
|
|
48
|
+
private parseGenesis;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/indexer/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAuC,WAAW,EAA4B,MAAM,wBAAwB,CAAC;AAkBpH,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C,OAAO,EAAc,oBAAoB,EAAE,QAAQ,EAAqB,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAI5G,eAAO,MAAM,oBAAoB;;;;;cAKX,oBAAoB,CAAC,UAAU,CAAC;;;;;;;8BAO1B,OAAO;CAClC,CAAC;AAEF,qBAAa,cAAe,SAAQ,cAAc;IAChD,OAAO,CAAC,MAAM,CAAuB;IAErC,OAAO,CAAC,OAAO,CAAkB;IAEjC,OAAO,CAAC,UAAU,CAAa;IAE/B,OAAO,CAAC,YAAY,CAAU;IAE9B,OAAO,CAAC,eAAe,CAAU;IAEjC,OAAO,CAAC,WAAW,CAAS;IAE5B,OAAO,CAAC,UAAU,CAAK;IAEhB,MAAM,EAAG,WAAW,CAAC;IAErB,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC;IAE3B,OAAO,CAAC,SAAS,CAAiC;IAElD,OAAO,CAAC,WAAW,CAEjB;IAEF,OAAO,CAAC,YAAY,CAA6D;gBAErE,MAAM,EAAE,oBAAoB;IAyDxC,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,aAAa,CAInB;IAEF,OAAO,CAAC,SAAS;IAQJ,OAAO;IAYpB,OAAO,CAAC,UAAU;IAUL,KAAK;IAyIX,SAAS,EAAE,QAAQ,CAAC,MAAM,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAoC3D;YAEY,YAAY;YA6HZ,OAAO;IA2CR,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,MAAM;IAoBrE,OAAO,CAAC,gBAAgB;YAqCV,YAAY;IAY1B,OAAO,CAAC,WAAW;YAQL,cAAc;YAyBd,cAAc;YAuBd,YAAY;CAiD3B"}
|
|
@@ -0,0 +1,629 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.EcleciaIndexer = exports.defaultIndexerConfig = void 0;
|
|
7
|
+
const node_crypto_1 = require("node:crypto");
|
|
8
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
9
|
+
const tendermint_rpc_1 = require("@cosmjs/tendermint-rpc");
|
|
10
|
+
const tendermint_rpc_2 = require("@cosmjs/tendermint-rpc");
|
|
11
|
+
const tx_1 = require("cosmjs-types/cosmos/authz/v1beta1/tx");
|
|
12
|
+
const query_1 = require("cosmjs-types/cosmos/staking/v1beta1/query");
|
|
13
|
+
const tx_2 = require("cosmjs-types/cosmos/tx/v1beta1/tx");
|
|
14
|
+
const fastify_1 = __importDefault(require("fastify"));
|
|
15
|
+
const stream_chain_1 = require("stream-chain");
|
|
16
|
+
const stream_json_1 = require("stream-json");
|
|
17
|
+
const Pick_1 = require("stream-json/filters/Pick");
|
|
18
|
+
const StreamArray_1 = require("stream-json/streamers/StreamArray");
|
|
19
|
+
const StreamValues_1 = require("stream-json/streamers/StreamValues");
|
|
20
|
+
const Batch_1 = require("stream-json/utils/Batch");
|
|
21
|
+
const uuid_1 = require("uuid");
|
|
22
|
+
const winston_1 = __importDefault(require("winston"));
|
|
23
|
+
const emitter_1 = require("../emitter");
|
|
24
|
+
const promise_queue_1 = require("../promise-queue");
|
|
25
|
+
const utils_1 = require("../utils");
|
|
26
|
+
exports.defaultIndexerConfig = {
|
|
27
|
+
startHeight: 1,
|
|
28
|
+
batchSize: 500,
|
|
29
|
+
modules: [],
|
|
30
|
+
getNextHeight: () => 1,
|
|
31
|
+
logLevel: "info",
|
|
32
|
+
usePolling: false,
|
|
33
|
+
pollingInterval: 5000,
|
|
34
|
+
processGenesis: false,
|
|
35
|
+
minimal: true,
|
|
36
|
+
init: () => Promise.resolve(),
|
|
37
|
+
beginTransaction: () => Promise.resolve(),
|
|
38
|
+
endTransaction: (_status) => Promise.resolve()
|
|
39
|
+
};
|
|
40
|
+
class EcleciaIndexer extends emitter_1.EclesiaEmitter {
|
|
41
|
+
constructor(config) {
|
|
42
|
+
super();
|
|
43
|
+
this.initialized = false;
|
|
44
|
+
this.retryCount = 0;
|
|
45
|
+
this.debugTime = null;
|
|
46
|
+
this.healthCheck = {
|
|
47
|
+
status: "CONNECTING"
|
|
48
|
+
};
|
|
49
|
+
this.subscription = null;
|
|
50
|
+
this.blockListener = {
|
|
51
|
+
next: (data) => {
|
|
52
|
+
this.newBlockReceived(data.header.height);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
this.asyncEmit = async (type, event) => {
|
|
56
|
+
event.uuid = (0, uuid_1.v4)();
|
|
57
|
+
this.debugTimes();
|
|
58
|
+
// More than 1 listener can be registered for an event type
|
|
59
|
+
// Fortunately these are all set up during module init() so we have a consistent count
|
|
60
|
+
// so we can count responses to resolve when complete
|
|
61
|
+
// values are irrelevant as promise resolution is only used for flow control
|
|
62
|
+
let listenerCount = this.handled.get(type);
|
|
63
|
+
if (!listenerCount) {
|
|
64
|
+
// Setting listenerCount to 1 (the unhandled listener)
|
|
65
|
+
listenerCount = 1;
|
|
66
|
+
}
|
|
67
|
+
let listenersResponded = 0;
|
|
68
|
+
const prom = new Promise((resolve, reject) => {
|
|
69
|
+
const returnFunc = (ev) => {
|
|
70
|
+
if (ev.uuid == event.uuid) {
|
|
71
|
+
if (ev.status) {
|
|
72
|
+
listenersResponded++;
|
|
73
|
+
if (listenersResponded == listenerCount) {
|
|
74
|
+
// All listeners have done their thing so we can remove listener, resolve and continue execution
|
|
75
|
+
this.off("uuid", returnFunc);
|
|
76
|
+
this.debugTimes(type);
|
|
77
|
+
resolve();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
// At least 1 listener is reporting an error. Reject and handle exception at the original asyncEmit location
|
|
82
|
+
reject(ev.error);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
this.on("uuid", returnFunc);
|
|
87
|
+
});
|
|
88
|
+
this.emit(type, event);
|
|
89
|
+
return prom;
|
|
90
|
+
};
|
|
91
|
+
this.config = {
|
|
92
|
+
...exports.defaultIndexerConfig,
|
|
93
|
+
...config
|
|
94
|
+
};
|
|
95
|
+
if (!this.config.minimal) {
|
|
96
|
+
this.blockQueue = new promise_queue_1.PromiseQueue(this.config.batchSize);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
this.blockQueue = new promise_queue_1.PromiseQueue(this.config.batchSize);
|
|
100
|
+
}
|
|
101
|
+
const { printf } = winston_1.default.format;
|
|
102
|
+
const eclesiaFormat = printf(({ level, message, timestamp }) => {
|
|
103
|
+
return `${timestamp} [${level.toUpperCase()}]:\t${message}`;
|
|
104
|
+
});
|
|
105
|
+
this.log = winston_1.default.createLogger({
|
|
106
|
+
level: this.config.logLevel,
|
|
107
|
+
defaultMeta: { service: "Eclesia Indexer" },
|
|
108
|
+
transports: [
|
|
109
|
+
new winston_1.default.transports.File({
|
|
110
|
+
filename: "error.log",
|
|
111
|
+
level: "error"
|
|
112
|
+
}),
|
|
113
|
+
new winston_1.default.transports.File({ filename: "combined.log" }),
|
|
114
|
+
new winston_1.default.transports.Console({
|
|
115
|
+
format: winston_1.default.format.combine(winston_1.default.format.splat(), winston_1.default.format.timestamp(), eclesiaFormat, winston_1.default.format.colorize({ all: true }))
|
|
116
|
+
})
|
|
117
|
+
]
|
|
118
|
+
});
|
|
119
|
+
this.fastify = (0, fastify_1.default)({
|
|
120
|
+
logger: false
|
|
121
|
+
});
|
|
122
|
+
this.on("_unhandled", (msg) => {
|
|
123
|
+
if (msg.uuid) {
|
|
124
|
+
this.log.verbose("Unhandled event: " + msg.type);
|
|
125
|
+
this.emit("uuid", {
|
|
126
|
+
status: true,
|
|
127
|
+
uuid: msg.uuid
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
this.fastify.get("/health", async (_request, reply) => {
|
|
132
|
+
const code = this.healthCheck.status == "OK" ? 200 : 503;
|
|
133
|
+
reply.code(code).send(this.healthCheck);
|
|
134
|
+
});
|
|
135
|
+
this.fastify.listen({
|
|
136
|
+
port: 80,
|
|
137
|
+
host: "0.0.0.0"
|
|
138
|
+
}, (err) => {
|
|
139
|
+
if (err) {
|
|
140
|
+
this.log.error(err);
|
|
141
|
+
process.exit(1);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
setStatus(status) {
|
|
146
|
+
this.healthCheck.status = status;
|
|
147
|
+
}
|
|
148
|
+
isMinimal(_blockqueue) {
|
|
149
|
+
if (this.config.minimal) {
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
async connect() {
|
|
157
|
+
try {
|
|
158
|
+
this.client = await (0, tendermint_rpc_2.connectComet)(this.config.rpcUrl);
|
|
159
|
+
this.log.info("Connected to RPC");
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
this.log.error(error);
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
debugTimes(label) {
|
|
168
|
+
if (this.debugTime && this.config.logLevel == "debug") {
|
|
169
|
+
const hrTime = process.hrtime(this.debugTime);
|
|
170
|
+
this.log.debug("Process time for " + label + ": " + Number(hrTime[0] * 1000 + hrTime[1] / 1000000) + "ms");
|
|
171
|
+
this.debugTime = null;
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
this.debugTime = process.hrtime();
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
async start() {
|
|
178
|
+
this.debugTime = null;
|
|
179
|
+
if (!this.initialized) {
|
|
180
|
+
try {
|
|
181
|
+
if (this.config.init) {
|
|
182
|
+
await this.config.init();
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
catch (e) {
|
|
186
|
+
this.log.error("Failed to initialize indexer: " + e);
|
|
187
|
+
this.setStatus("FAILED");
|
|
188
|
+
throw e;
|
|
189
|
+
}
|
|
190
|
+
if (this.config.processGenesis) {
|
|
191
|
+
try {
|
|
192
|
+
if (this.config.genesisPath) {
|
|
193
|
+
await this.parseGenesis();
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
catch (e) {
|
|
197
|
+
this.log.error("Failed to parse genesis: " + e);
|
|
198
|
+
this.setStatus("FAILED");
|
|
199
|
+
throw e;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
this.initialized = true;
|
|
203
|
+
}
|
|
204
|
+
this.subscription = this.client.subscribeNewBlock ? this.client.subscribeNewBlock() : null;
|
|
205
|
+
try {
|
|
206
|
+
await this.connect();
|
|
207
|
+
const status = await this.client.status();
|
|
208
|
+
this.latestHeight = status.syncInfo.latestBlockHeight;
|
|
209
|
+
this.blockQueue.clear();
|
|
210
|
+
this.log.info("Current chain height: " + this.latestHeight);
|
|
211
|
+
this.heightToProcess = await this.config.getNextHeight();
|
|
212
|
+
if (this.config.usePolling) {
|
|
213
|
+
this.pollForBlock();
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
if (this.subscription) {
|
|
217
|
+
this.subscription.addListener(this.blockListener);
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
throw new Error("Could not subscribe to new blocks");
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
catch (e) {
|
|
225
|
+
this.log.error("Failed to set up block listening: " + e);
|
|
226
|
+
this.setStatus("FAILED");
|
|
227
|
+
throw e;
|
|
228
|
+
}
|
|
229
|
+
this.fetcher().catch((e) => {
|
|
230
|
+
throw new Error("Error in fetching service: " + e);
|
|
231
|
+
});
|
|
232
|
+
const hrTime = process.hrtime();
|
|
233
|
+
let ms = hrTime[0] * 1000000 + hrTime[1] / 1000;
|
|
234
|
+
while (this.blockQueue.size() > 0) {
|
|
235
|
+
// await the dequeued promise is essentially awaiting fetched data for that block
|
|
236
|
+
try {
|
|
237
|
+
// Index block inside a db transaction to ensure data consistency
|
|
238
|
+
await this.config.beginTransaction();
|
|
239
|
+
this.log.silly("Started db tx");
|
|
240
|
+
let height, timestamp;
|
|
241
|
+
if (this.isMinimal(this.blockQueue)) {
|
|
242
|
+
const toProcess = await this.blockQueue.dequeue();
|
|
243
|
+
this.log.silly("Retrieved block data");
|
|
244
|
+
if (!toProcess) {
|
|
245
|
+
throw new Error("Could not fetch block");
|
|
246
|
+
}
|
|
247
|
+
height = toProcess[0].block.header.height;
|
|
248
|
+
timestamp = (0, tendermint_rpc_1.toRfc3339WithNanoseconds)(toProcess[0].block.header.time);
|
|
249
|
+
await this.processBlock(toProcess[0], toProcess[1]);
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
const toProcess = await this.blockQueue.dequeue();
|
|
253
|
+
this.log.silly("Retrieved block data");
|
|
254
|
+
if (!toProcess) {
|
|
255
|
+
throw new Error("Could not fetch block");
|
|
256
|
+
}
|
|
257
|
+
this.log.silly("Decoded block");
|
|
258
|
+
height = toProcess[0].block.header.height;
|
|
259
|
+
timestamp = (0, tendermint_rpc_1.toRfc3339WithNanoseconds)(toProcess[0].block.header.time);
|
|
260
|
+
await this.processBlock(toProcess[0], toProcess[1], query_1.QueryValidatorsResponse.decode(toProcess[2]).validators);
|
|
261
|
+
}
|
|
262
|
+
// Emit events to trigger periodic operations every 50, 100 and 1000 blocks
|
|
263
|
+
if (height % 1000 == 0) {
|
|
264
|
+
const hrTime = process.hrtime();
|
|
265
|
+
const newms = hrTime[0] * 1000000 + hrTime[1] / 1000;
|
|
266
|
+
const duration = newms - ms;
|
|
267
|
+
ms = newms;
|
|
268
|
+
const rate = 1000000000 / duration;
|
|
269
|
+
this.log.info("Processing:" + rate.toFixed(2) + "blocks/sec");
|
|
270
|
+
await this.asyncEmit("periodic/1000", {
|
|
271
|
+
value: null,
|
|
272
|
+
height,
|
|
273
|
+
timestamp
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
if (height % 100 == 0) {
|
|
277
|
+
await this.asyncEmit("periodic/100", {
|
|
278
|
+
value: null,
|
|
279
|
+
height,
|
|
280
|
+
timestamp
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
if (height % 50 == 0) {
|
|
284
|
+
await this.asyncEmit("periodic/50", {
|
|
285
|
+
value: null,
|
|
286
|
+
height,
|
|
287
|
+
timestamp
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
this.log.silly("Handled periodic events");
|
|
291
|
+
await this.config.endTransaction(true);
|
|
292
|
+
this.log.silly("Committed db tx");
|
|
293
|
+
}
|
|
294
|
+
catch (e) {
|
|
295
|
+
this.log.error("" + e);
|
|
296
|
+
this.setStatus("FAILED");
|
|
297
|
+
await this.config.endTransaction(false);
|
|
298
|
+
if (this.subscription) {
|
|
299
|
+
this.subscription.removeListener(this.blockListener);
|
|
300
|
+
}
|
|
301
|
+
this.retryCount++;
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
this.retryCount = 0;
|
|
305
|
+
this.setStatus("OK");
|
|
306
|
+
}
|
|
307
|
+
if (this.retryCount < 3) {
|
|
308
|
+
this.log.debug("Indexer retryCount: " + this.retryCount);
|
|
309
|
+
this.log.info("Indexer is restarting");
|
|
310
|
+
this.start();
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
async processBlock(block, block_results, validators) {
|
|
314
|
+
const height = block.block.header.height;
|
|
315
|
+
this.log.debug("Processing block: %d", height);
|
|
316
|
+
this.log.silly("Started db tx");
|
|
317
|
+
// Initialize height & timestamp to be used for this block-processing run
|
|
318
|
+
const timestamp = (0, tendermint_rpc_1.toRfc3339WithNanoseconds)(block.block.header.time);
|
|
319
|
+
// Use & await asyncEmit to ensure db insertions in order
|
|
320
|
+
// Emit block information to any interested modules.
|
|
321
|
+
// Primarily the required block module listens to this
|
|
322
|
+
await this.asyncEmit("block", {
|
|
323
|
+
value: {
|
|
324
|
+
block,
|
|
325
|
+
block_results
|
|
326
|
+
},
|
|
327
|
+
height,
|
|
328
|
+
timestamp
|
|
329
|
+
});
|
|
330
|
+
this.log.silly("Modules handled block event");
|
|
331
|
+
// Deal with begin_block events first
|
|
332
|
+
await this.asyncEmit("begin_block", {
|
|
333
|
+
value: {
|
|
334
|
+
events: block_results.beginBlockEvents,
|
|
335
|
+
validators
|
|
336
|
+
},
|
|
337
|
+
height,
|
|
338
|
+
timestamp
|
|
339
|
+
});
|
|
340
|
+
this.log.silly("Modules handled begin_block events");
|
|
341
|
+
// Then individual tx_events
|
|
342
|
+
await this.asyncEmit("tx_events", {
|
|
343
|
+
value: block_results.results,
|
|
344
|
+
height,
|
|
345
|
+
timestamp
|
|
346
|
+
});
|
|
347
|
+
this.log.silly("Modules handled tx events");
|
|
348
|
+
// Emit details and result for each tx msg separately
|
|
349
|
+
for (let t = 0; t < block.block.txs.length; t++) {
|
|
350
|
+
const tx = tx_2.Tx.decode(block.block.txs[t]);
|
|
351
|
+
const result = block_results.results[t].code;
|
|
352
|
+
const txlog = block_results.results[t].log;
|
|
353
|
+
if (result != 0) {
|
|
354
|
+
// Tx failed. Ignore
|
|
355
|
+
continue;
|
|
356
|
+
}
|
|
357
|
+
if (tx.body && tx.body.memo != "") {
|
|
358
|
+
const txHash = (0, node_crypto_1.createHash)("sha256").update(block.block.txs[t]).digest("hex");
|
|
359
|
+
await this.asyncEmit("tx_memo", {
|
|
360
|
+
value: {
|
|
361
|
+
txHash,
|
|
362
|
+
txBody: tx.body
|
|
363
|
+
},
|
|
364
|
+
height,
|
|
365
|
+
timestamp
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
// parsing log rather than using events directly in order to have msg_index available to filter appropriate events for each msg
|
|
369
|
+
const events = txlog
|
|
370
|
+
? JSON.parse(txlog)
|
|
371
|
+
: [];
|
|
372
|
+
const msgs = tx.body?.messages;
|
|
373
|
+
if (msgs) {
|
|
374
|
+
for (let i = 0; i < msgs.length; i++) {
|
|
375
|
+
this.log.silly("Indexer broadcasting msg for handling: " + msgs[i].typeUrl);
|
|
376
|
+
const msgevents = msgs.length > 1
|
|
377
|
+
? events.find((x) => x.msg_index == i)?.events
|
|
378
|
+
: events[0].events;
|
|
379
|
+
await this.asyncEmit(msgs[i].typeUrl, {
|
|
380
|
+
value: {
|
|
381
|
+
tx: msgs[i].value,
|
|
382
|
+
events: msgevents
|
|
383
|
+
},
|
|
384
|
+
height,
|
|
385
|
+
timestamp
|
|
386
|
+
});
|
|
387
|
+
if (msgs[i].typeUrl == "/cosmos.authz.v1beta1.MsgExec") {
|
|
388
|
+
const authzMsgs = tx_1.MsgExec.decode(msgs[i].value).msgs;
|
|
389
|
+
if (authzMsgs) {
|
|
390
|
+
for (let r = 0; r < authzMsgs.length; r++) {
|
|
391
|
+
this.log.silly("Indexer broadcasting msg for handling: " + authzMsgs[i].typeUrl);
|
|
392
|
+
const authzMsgEvents = msgevents?.reduce((events, evt) => {
|
|
393
|
+
if (evt.attributes.filter(x => (0, utils_1.decodeAttr)(x.key) == "authz_msg_index" && (0, utils_1.decodeAttr)(x.value) == "" + r).length > 0) {
|
|
394
|
+
events.push(evt);
|
|
395
|
+
}
|
|
396
|
+
return events;
|
|
397
|
+
}, []);
|
|
398
|
+
await this.asyncEmit(authzMsgs[i].typeUrl, {
|
|
399
|
+
value: {
|
|
400
|
+
tx: authzMsgs[i].value,
|
|
401
|
+
events: authzMsgEvents
|
|
402
|
+
},
|
|
403
|
+
height,
|
|
404
|
+
timestamp
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
this.log.silly("Modules handled msg events");
|
|
413
|
+
// Then deal with end_block events
|
|
414
|
+
await this.asyncEmit("end_block", {
|
|
415
|
+
value: block_results.endBlockEvents,
|
|
416
|
+
height,
|
|
417
|
+
timestamp
|
|
418
|
+
});
|
|
419
|
+
this.log.silly("Modules handled end_block events");
|
|
420
|
+
}
|
|
421
|
+
async fetcher() {
|
|
422
|
+
let error = false;
|
|
423
|
+
for (let i = this.heightToProcess; i <= this.latestHeight; i++) {
|
|
424
|
+
this.log.debug("Fetching: " + i);
|
|
425
|
+
try {
|
|
426
|
+
if (this.isMinimal(this.blockQueue)) {
|
|
427
|
+
const toIndex = Promise.all([
|
|
428
|
+
this.client.block(i),
|
|
429
|
+
this.client.blockResults(i)
|
|
430
|
+
]).catch((_e) => {
|
|
431
|
+
this.log.error("Error fetching block: " + i);
|
|
432
|
+
return Promise.resolve([]);
|
|
433
|
+
});
|
|
434
|
+
this.blockQueue.enqueue(toIndex);
|
|
435
|
+
}
|
|
436
|
+
else {
|
|
437
|
+
const q = query_1.QueryValidatorsRequest.fromPartial({ pagination: { limit: 1000n } });
|
|
438
|
+
const vals = query_1.QueryValidatorsRequest.encode(q).finish();
|
|
439
|
+
const toIndex = Promise.all([
|
|
440
|
+
this.client.block(i),
|
|
441
|
+
this.client.blockResults(i),
|
|
442
|
+
this.callABCI("/cosmos.staking.v1beta1.Query/Validators", vals, i)
|
|
443
|
+
]).catch((_e) => {
|
|
444
|
+
this.log.error("Error fetching block: " + i);
|
|
445
|
+
return Promise.resolve([]);
|
|
446
|
+
});
|
|
447
|
+
this.blockQueue.enqueue(toIndex);
|
|
448
|
+
}
|
|
449
|
+
await this.blockQueue.continue();
|
|
450
|
+
}
|
|
451
|
+
catch (e) {
|
|
452
|
+
this.log.error(e);
|
|
453
|
+
error = true;
|
|
454
|
+
break;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
if (!error) {
|
|
458
|
+
this.blockQueue.setSynced();
|
|
459
|
+
this.log.info("Synced to latest height");
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
async callABCI(path, data, height) {
|
|
463
|
+
const timeout = new Promise((resolve) => {
|
|
464
|
+
setTimeout(resolve, 30000);
|
|
465
|
+
});
|
|
466
|
+
const abciq = await Promise.race([
|
|
467
|
+
this.client.abciQuery({
|
|
468
|
+
path,
|
|
469
|
+
data,
|
|
470
|
+
height: height
|
|
471
|
+
}),
|
|
472
|
+
timeout
|
|
473
|
+
]);
|
|
474
|
+
if (abciq) {
|
|
475
|
+
return abciq.value;
|
|
476
|
+
}
|
|
477
|
+
else {
|
|
478
|
+
this.setStatus("FAILED");
|
|
479
|
+
throw new Error("RPC not responding. Query at: " + path);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
newBlockReceived(height) {
|
|
483
|
+
this.log.info("Received new block: %d", height);
|
|
484
|
+
// If we are synced, add to end of queue
|
|
485
|
+
if (this.blockQueue.synced) {
|
|
486
|
+
try {
|
|
487
|
+
if (this.isMinimal(this.blockQueue)) {
|
|
488
|
+
this.blockQueue.enqueue(Promise.all([
|
|
489
|
+
this.client.block(height),
|
|
490
|
+
this.client.blockResults(height)
|
|
491
|
+
]).catch((_e) => {
|
|
492
|
+
this.log.error("Error fetching block: " + height);
|
|
493
|
+
return Promise.resolve([]);
|
|
494
|
+
}));
|
|
495
|
+
}
|
|
496
|
+
else {
|
|
497
|
+
const q = query_1.QueryValidatorsRequest.fromPartial({ pagination: { limit: 1000n } });
|
|
498
|
+
const vals = query_1.QueryValidatorsRequest.encode(q).finish();
|
|
499
|
+
this.blockQueue.enqueue(Promise.all([
|
|
500
|
+
this.client.block(height),
|
|
501
|
+
this.client.blockResults(height),
|
|
502
|
+
this.callABCI("/cosmos.staking.v1beta1.Query/Validators", vals, height)
|
|
503
|
+
]).catch((_e) => {
|
|
504
|
+
this.log.error("Error fetching block: " + height);
|
|
505
|
+
return Promise.resolve([]);
|
|
506
|
+
}));
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
catch (e) {
|
|
510
|
+
this.log.error("" + e);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
else {
|
|
514
|
+
this.latestHeight = height;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
async pollForBlock() {
|
|
518
|
+
const status = await this.client.status();
|
|
519
|
+
if (status.syncInfo.latestBlockHeight > this.latestHeight) {
|
|
520
|
+
while (this.latestHeight < status.syncInfo.latestBlockHeight) {
|
|
521
|
+
this.newBlockReceived(this.latestHeight + 1);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
setTimeout(() => {
|
|
525
|
+
this.pollForBlock();
|
|
526
|
+
}, this.config.pollingInterval);
|
|
527
|
+
}
|
|
528
|
+
readGenesis() {
|
|
529
|
+
if (this.config.genesisPath) {
|
|
530
|
+
return node_fs_1.default.createReadStream(this.config.genesisPath).pipe((0, stream_json_1.parser)());
|
|
531
|
+
}
|
|
532
|
+
else {
|
|
533
|
+
throw new Error("Genesis path not set");
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
async setArrayReader(path, processor) {
|
|
537
|
+
const readPromise = new Promise((resolve, reject) => {
|
|
538
|
+
try {
|
|
539
|
+
const filters = path.split(".");
|
|
540
|
+
const pickers = filters.map((filter) => (0, Pick_1.pick)({ filter }));
|
|
541
|
+
let counter = 0;
|
|
542
|
+
(0, stream_chain_1.chain)([this.readGenesis(), ...pickers, (0, StreamArray_1.streamArray)(), (0, Batch_1.batch)({ batchSize: 1000 }), processor])
|
|
543
|
+
.on("data", (data) => {
|
|
544
|
+
if (data && Array.isArray(data)) {
|
|
545
|
+
counter = counter + data.length;
|
|
546
|
+
}
|
|
547
|
+
})
|
|
548
|
+
.on("end", () => {
|
|
549
|
+
this.log.info(`Processed ${counter} entries`);
|
|
550
|
+
resolve(true);
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
catch (_e) {
|
|
554
|
+
this.log.verbose("Error in setArrayReader: " + _e);
|
|
555
|
+
reject();
|
|
556
|
+
}
|
|
557
|
+
});
|
|
558
|
+
return readPromise;
|
|
559
|
+
}
|
|
560
|
+
async setValueReader(path, processor) {
|
|
561
|
+
const readPromise = new Promise((resolve, reject) => {
|
|
562
|
+
try {
|
|
563
|
+
const filters = path.split(".");
|
|
564
|
+
const pickers = filters.map((filter) => (0, Pick_1.pick)({ filter }));
|
|
565
|
+
let counter = 0;
|
|
566
|
+
(0, stream_chain_1.chain)([this.readGenesis(), ...pickers, (0, StreamValues_1.streamValues)(), processor])
|
|
567
|
+
.on("data", (_data) => {
|
|
568
|
+
counter++;
|
|
569
|
+
})
|
|
570
|
+
.on("end", () => {
|
|
571
|
+
this.log.info(`Processed ${counter} entries`);
|
|
572
|
+
resolve(true);
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
catch (_e) {
|
|
576
|
+
reject();
|
|
577
|
+
}
|
|
578
|
+
});
|
|
579
|
+
return readPromise;
|
|
580
|
+
}
|
|
581
|
+
async parseGenesis() {
|
|
582
|
+
this.log.info("Parsing genesis");
|
|
583
|
+
await this.config.beginTransaction();
|
|
584
|
+
try {
|
|
585
|
+
this.log.info("Starting genesis import");
|
|
586
|
+
this.log.debug("Importing genesis file...");
|
|
587
|
+
for (const [key, _value] of this.handled) {
|
|
588
|
+
if (key.startsWith("genesis/")) {
|
|
589
|
+
const genesisEntry = key.split("/");
|
|
590
|
+
this.log.verbose("Importing " + key + "...");
|
|
591
|
+
if (genesisEntry[1] == "array") {
|
|
592
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
593
|
+
await this.setArrayReader(genesisEntry[2], async (data) => {
|
|
594
|
+
await this.asyncEmit(key, { value: data.map((x) => x.value) });
|
|
595
|
+
return data;
|
|
596
|
+
});
|
|
597
|
+
}
|
|
598
|
+
else {
|
|
599
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
600
|
+
await this.setValueReader(genesisEntry[2], async (data) => {
|
|
601
|
+
await this.asyncEmit(key, { value: data.value });
|
|
602
|
+
return data;
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
this.log.info("Importing gen TXs...");
|
|
608
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
609
|
+
await this.setArrayReader("app_state.genutil.gen_txs", async (data) => {
|
|
610
|
+
for (let j = 0; j < data.length; j++) {
|
|
611
|
+
const gentx = data[j].value;
|
|
612
|
+
for (let i = 0; i < gentx.body.messages.length; i++) {
|
|
613
|
+
const msg = gentx.body.messages[i];
|
|
614
|
+
await this.asyncEmit(("gentx" + msg["@type"]), { value: msg });
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
return data;
|
|
618
|
+
});
|
|
619
|
+
await this.config.endTransaction(true);
|
|
620
|
+
this.log.info("Finished importing");
|
|
621
|
+
}
|
|
622
|
+
catch (e) {
|
|
623
|
+
await this.config.endTransaction(false);
|
|
624
|
+
this.log.error("Failed to import genesis");
|
|
625
|
+
throw e;
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
exports.EcleciaIndexer = EcleciaIndexer;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare class PromiseQueue<T> {
|
|
2
|
+
private items;
|
|
3
|
+
private enqueuer;
|
|
4
|
+
private batcher;
|
|
5
|
+
synced: boolean;
|
|
6
|
+
private batchSize;
|
|
7
|
+
private continuePromise;
|
|
8
|
+
constructor(batchSize: number);
|
|
9
|
+
enqueue(item: T | PromiseLike<T>): void;
|
|
10
|
+
clear(): void;
|
|
11
|
+
dequeue(): Promise<T>;
|
|
12
|
+
continue(): Promise<boolean>;
|
|
13
|
+
setSynced(): void;
|
|
14
|
+
isEmpty(): boolean;
|
|
15
|
+
size(): number;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/promise-queue/index.ts"],"names":[],"mappings":"AAOA,qBAAa,YAAY,CAAC,CAAC;IACzB,OAAO,CAAC,KAAK,CAAoB;IAEjC,OAAO,CAAC,QAAQ,CAAqC;IAErD,OAAO,CAAC,OAAO,CAA0B;IAElC,MAAM,UAAS;IAEtB,OAAO,CAAC,SAAS,CAAS;IAE1B,OAAO,CAAC,eAAe,CAAmB;gBAE9B,SAAS,EAAE,MAAM;IAY7B,OAAO,CAAC,IAAI,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC;IAiBhC,KAAK;IAWL,OAAO,IAMU,OAAO,CAAC,CAAC,CAAC;IAG3B,QAAQ;IAIR,SAAS;IAIT,OAAO;IAQP,IAAI;CAGL"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
This implements an "infinite" FIFO queue of fixed size.
|
|
4
|
+
await `continue()` before enqueing items to ensure fixed size (as it only resolves when space available)
|
|
5
|
+
await `dequeue()` to pop an item as it will only resolve if the next item is available
|
|
6
|
+
size() is always at minimum 1 item which is the promise that will resolve to the next item whenever it is enqueued
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.PromiseQueue = void 0;
|
|
10
|
+
class PromiseQueue {
|
|
11
|
+
constructor(batchSize) {
|
|
12
|
+
this.synced = false;
|
|
13
|
+
const nextVal = new Promise((resolve, _reject) => {
|
|
14
|
+
this.enqueuer = resolve;
|
|
15
|
+
});
|
|
16
|
+
this.batchSize = batchSize;
|
|
17
|
+
this.continuePromise = new Promise((resolve, _reject) => {
|
|
18
|
+
this.batcher = resolve;
|
|
19
|
+
});
|
|
20
|
+
this.batcher(true);
|
|
21
|
+
this.items = [nextVal];
|
|
22
|
+
}
|
|
23
|
+
enqueue(item) {
|
|
24
|
+
try {
|
|
25
|
+
this.enqueuer(item);
|
|
26
|
+
const nextVal = new Promise((resolve, _reject) => {
|
|
27
|
+
this.enqueuer = resolve;
|
|
28
|
+
});
|
|
29
|
+
this.items.unshift(nextVal);
|
|
30
|
+
if (this.size() > this.batchSize) {
|
|
31
|
+
this.continuePromise = new Promise((resolve, _reject) => {
|
|
32
|
+
this.batcher = resolve;
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
console.error("Enqueing rejected data: " + e);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
clear() {
|
|
41
|
+
const nextVal = new Promise((resolve, _reject) => {
|
|
42
|
+
this.enqueuer = resolve;
|
|
43
|
+
});
|
|
44
|
+
this.continuePromise = new Promise((resolve, _reject) => {
|
|
45
|
+
this.batcher = resolve;
|
|
46
|
+
});
|
|
47
|
+
this.batcher(true);
|
|
48
|
+
this.items = [nextVal];
|
|
49
|
+
}
|
|
50
|
+
dequeue() {
|
|
51
|
+
const item = this.items.pop();
|
|
52
|
+
if (this.size() <= this.batchSize) {
|
|
53
|
+
this.batcher(true);
|
|
54
|
+
}
|
|
55
|
+
return item;
|
|
56
|
+
}
|
|
57
|
+
continue() {
|
|
58
|
+
return this.continuePromise;
|
|
59
|
+
}
|
|
60
|
+
setSynced() {
|
|
61
|
+
this.synced = true;
|
|
62
|
+
}
|
|
63
|
+
isEmpty() {
|
|
64
|
+
if (this.items.length == 0) {
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
size() {
|
|
72
|
+
return this.items.length;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
exports.PromiseQueue = PromiseQueue;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { BlockResponse, BlockResultsResponse } from "@cosmjs/tendermint-rpc";
|
|
2
|
+
import { Event } from "@cosmjs/tendermint-rpc/build/comet38/responses";
|
|
3
|
+
import { Validator } from "cosmjs-types/cosmos/staking/v1beta1/staking";
|
|
4
|
+
import { TxBody } from "cosmjs-types/cosmos/tx/v1beta1/tx";
|
|
5
|
+
import { EcleciaIndexer } from "../indexer";
|
|
6
|
+
import { PromiseQueue } from "../promise-queue";
|
|
7
|
+
export type EcleciaIndexerConfig = {
|
|
8
|
+
startHeight?: number;
|
|
9
|
+
endHeight?: number;
|
|
10
|
+
batchSize: number;
|
|
11
|
+
modules: string[];
|
|
12
|
+
getNextHeight: () => number | PromiseLike<number>;
|
|
13
|
+
logLevel: "error" | "warn" | "info" | "http" | "verbose" | "debug" | "silly";
|
|
14
|
+
rpcUrl: string;
|
|
15
|
+
processGenesis?: boolean;
|
|
16
|
+
genesisPath?: string;
|
|
17
|
+
usePolling?: boolean;
|
|
18
|
+
pollingInterval?: number;
|
|
19
|
+
minimal?: boolean;
|
|
20
|
+
init?: () => Promise<void>;
|
|
21
|
+
beginTransaction: () => Promise<void>;
|
|
22
|
+
endTransaction: (status: boolean) => Promise<void>;
|
|
23
|
+
};
|
|
24
|
+
export type FullBlockQueue = PromiseQueue<[BlockResponse, BlockResultsResponse, Uint8Array]>;
|
|
25
|
+
export type MinimalBlockQueue = PromiseQueue<[BlockResponse, BlockResultsResponse]>;
|
|
26
|
+
export type BlockQueue = FullBlockQueue | MinimalBlockQueue;
|
|
27
|
+
export type WithHeightAndUUID<T> = {
|
|
28
|
+
[K in keyof T]: T[K] & {
|
|
29
|
+
uuid?: string;
|
|
30
|
+
height?: number;
|
|
31
|
+
timestamp?: string;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
export type EmitFunc<K extends keyof WithHeightAndUUID<EventMap>> = (t: K, e: WithHeightAndUUID<EventMap>[K]) => Promise<void | void[]>;
|
|
35
|
+
export type LogEvent = {
|
|
36
|
+
type: "log" | "info" | "warning" | "error" | "verbose" | "transient";
|
|
37
|
+
message: string;
|
|
38
|
+
};
|
|
39
|
+
export type UUIDEvent = {
|
|
40
|
+
uuid: string;
|
|
41
|
+
error?: string;
|
|
42
|
+
status: boolean;
|
|
43
|
+
};
|
|
44
|
+
export type Events = {
|
|
45
|
+
log: LogEvent;
|
|
46
|
+
uuid: UUIDEvent;
|
|
47
|
+
begin_block: {
|
|
48
|
+
value: {
|
|
49
|
+
events: BlockResultsResponse["beginBlockEvents"];
|
|
50
|
+
validators: Validator[] | undefined;
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
block: {
|
|
54
|
+
value: {
|
|
55
|
+
block: BlockResponse;
|
|
56
|
+
block_results: BlockResultsResponse;
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
end_block: {
|
|
60
|
+
value: BlockResultsResponse["endBlockEvents"];
|
|
61
|
+
};
|
|
62
|
+
tx_events: {
|
|
63
|
+
value: BlockResultsResponse["results"];
|
|
64
|
+
};
|
|
65
|
+
tx_memo: {
|
|
66
|
+
value: {
|
|
67
|
+
txHash: string;
|
|
68
|
+
txBody: TxBody;
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
_unhandled: {
|
|
72
|
+
type: string;
|
|
73
|
+
event: unknown;
|
|
74
|
+
};
|
|
75
|
+
"periodic/50": {
|
|
76
|
+
value: null;
|
|
77
|
+
};
|
|
78
|
+
"periodic/100": {
|
|
79
|
+
value: null;
|
|
80
|
+
};
|
|
81
|
+
"periodic/1000": {
|
|
82
|
+
value: null;
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
export type TxResult<T> = {
|
|
86
|
+
tx: T;
|
|
87
|
+
events: Event[];
|
|
88
|
+
};
|
|
89
|
+
export interface IndexingModule {
|
|
90
|
+
indexer: EcleciaIndexer;
|
|
91
|
+
name: string;
|
|
92
|
+
depends: string[];
|
|
93
|
+
provides: string[];
|
|
94
|
+
setup: () => Promise<void>;
|
|
95
|
+
init: (...args: any[]) => void;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
declare function toHexString(byteArray: number[]): string;
|
|
2
|
+
declare function keyHashfromAddress(address: string): string;
|
|
3
|
+
declare function chainAddressfromKeyhash(prefix: string, keyhash: string): string;
|
|
4
|
+
export { chainAddressfromKeyhash, keyHashfromAddress, toHexString };
|
|
5
|
+
//# sourceMappingURL=bech32.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bech32.d.ts","sourceRoot":"","sources":["../../src/utils/bech32.ts"],"names":[],"mappings":"AAEA,iBAAS,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,UAMvC;AACD,iBAAS,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAMnD;AACD,iBAAS,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,UAI/D;AAED,OAAO,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,WAAW,EAAE,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.chainAddressfromKeyhash = chainAddressfromKeyhash;
|
|
4
|
+
exports.keyHashfromAddress = keyHashfromAddress;
|
|
5
|
+
exports.toHexString = toHexString;
|
|
6
|
+
const bech32_1 = require("bech32");
|
|
7
|
+
function toHexString(byteArray) {
|
|
8
|
+
return Array.prototype.map
|
|
9
|
+
.call(byteArray, (byte) => {
|
|
10
|
+
return ("0" + (byte & 0xff).toString(16)).slice(-2);
|
|
11
|
+
})
|
|
12
|
+
.join("");
|
|
13
|
+
}
|
|
14
|
+
function keyHashfromAddress(address) {
|
|
15
|
+
try {
|
|
16
|
+
return toHexString(bech32_1.bech32.fromWords(bech32_1.bech32.decode(address).words));
|
|
17
|
+
}
|
|
18
|
+
catch (_e) {
|
|
19
|
+
throw new Error("Could not decode address");
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function chainAddressfromKeyhash(prefix, keyhash) {
|
|
23
|
+
const words = bech32_1.bech32.toWords(Buffer.from(keyhash, "hex"));
|
|
24
|
+
return keyhash !== "" ? bech32_1.bech32.encode(prefix, words) : "";
|
|
25
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bigint.d.ts","sourceRoot":"","sources":["../../src/utils/bigint.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,aAAa,GAAI,KAAK,OAAO,QAGlC,CAAC;AACF,OAAO,EAAE,aAAa,EAAE,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toPlainObject = void 0;
|
|
4
|
+
const toPlainObject = (obj) => {
|
|
5
|
+
return JSON.parse(JSON.stringify(obj, (key, value) => typeof value === "bigint" ? value.toString() : value // return everything else unchanged
|
|
6
|
+
));
|
|
7
|
+
};
|
|
8
|
+
exports.toPlainObject = toPlainObject;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./bech32"), exports);
|
|
18
|
+
__exportStar(require("./bigint"), exports);
|
|
19
|
+
__exportStar(require("./text"), exports);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/utils/text.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,GAAI,GAAG,UAAU,GAAG,MAAM,uBAOhD,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.decodeAttr = void 0;
|
|
4
|
+
const decodeAttr = (x) => {
|
|
5
|
+
if (typeof x === "string") {
|
|
6
|
+
return x;
|
|
7
|
+
}
|
|
8
|
+
if (x instanceof Uint8Array) {
|
|
9
|
+
return Buffer.from(x).toString();
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
exports.decodeAttr = decodeAttr;
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@eclesia/indexer-engine",
|
|
3
|
+
"version": "2.3.1",
|
|
4
|
+
"description": "Core eclesia indexer engine",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"lint": "eslint",
|
|
10
|
+
"lint:fix": "eslint --fix",
|
|
11
|
+
"test": "vitest"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist/",
|
|
15
|
+
"scripts/",
|
|
16
|
+
"templates"
|
|
17
|
+
],
|
|
18
|
+
"keywords": [],
|
|
19
|
+
"contributors": [
|
|
20
|
+
"Alex M.<alex.megalokonomos@tendermint.com>"
|
|
21
|
+
],
|
|
22
|
+
"license": "Apache-2.0",
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@eslint/js": "^9.24.0",
|
|
25
|
+
"@stylistic/eslint-plugin-ts": "^4.2.0",
|
|
26
|
+
"@types/node": "^22.14.0",
|
|
27
|
+
"@types/stream-chain": "^2.1.0",
|
|
28
|
+
"@types/stream-json": "^1.7.8",
|
|
29
|
+
"@types/uuid": "^10.0.0",
|
|
30
|
+
"eslint": "^9.24.0",
|
|
31
|
+
"eslint-plugin-simple-import-sort": "^12.1.1",
|
|
32
|
+
"typescript": "^5.8.3",
|
|
33
|
+
"typescript-eslint": "^8.29.0",
|
|
34
|
+
"vitest": "^3.1.1"
|
|
35
|
+
},
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@cosmjs/tendermint-rpc": "^0.33.1",
|
|
41
|
+
"bech32": "^2.0.0",
|
|
42
|
+
"cosmjs-types": "^0.9.0",
|
|
43
|
+
"dayjs": "^1.11.13",
|
|
44
|
+
"fastify": "^5.2.2",
|
|
45
|
+
"stream-chain": "^3.4.0",
|
|
46
|
+
"stream-json": "^1.9.1",
|
|
47
|
+
"uuid": "^11.1.0",
|
|
48
|
+
"winston": "^3.17.0"
|
|
49
|
+
}
|
|
50
|
+
}
|