@certik/skynet 0.20.2 → 0.22.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/CHANGELOG.md +17 -0
- package/abi.ts +2 -4
- package/api.ts +7 -7
- package/app.ts +6 -12
- package/availability.ts +37 -7
- package/bun.lockb +0 -0
- package/const.ts +1 -1
- package/date.ts +1 -1
- package/deploy.ts +4 -4
- package/dist/abi.d.ts +112 -0
- package/dist/abi.d.ts.map +1 -0
- package/dist/abi.js +616 -0
- package/dist/address.d.ts +3 -0
- package/dist/address.d.ts.map +1 -0
- package/dist/address.js +69 -0
- package/dist/api.d.ts +32 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +35174 -0
- package/dist/app.d.ts +102 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +71714 -0
- package/dist/availability.d.ts +24 -0
- package/dist/availability.d.ts.map +1 -0
- package/dist/availability.js +926 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +86 -0
- package/dist/const.d.ts +35 -0
- package/dist/const.d.ts.map +1 -0
- package/dist/const.js +207 -0
- package/dist/databricks.d.ts +4 -0
- package/dist/databricks.d.ts.map +1 -0
- package/dist/databricks.js +84920 -0
- package/dist/date.d.ts +6 -0
- package/dist/date.d.ts.map +1 -0
- package/dist/date.js +101 -0
- package/dist/deploy.d.ts +76 -0
- package/dist/deploy.d.ts.map +1 -0
- package/dist/deploy.js +17506 -0
- package/dist/dynamodb.d.ts +17 -0
- package/dist/dynamodb.d.ts.map +1 -0
- package/dist/dynamodb.js +27365 -0
- package/dist/env.d.ts +7 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +71 -0
- package/dist/graphql.d.ts +6 -0
- package/dist/graphql.d.ts.map +1 -0
- package/dist/graphql.js +73 -0
- package/dist/indexer.d.ts +70 -0
- package/dist/indexer.d.ts.map +1 -0
- package/dist/indexer.js +36979 -0
- package/dist/log.d.ts +14 -0
- package/dist/log.d.ts.map +1 -0
- package/dist/log.js +108 -0
- package/dist/object-hash.d.ts +2 -0
- package/dist/object-hash.d.ts.map +1 -0
- package/dist/object-hash.js +446 -0
- package/dist/opsgenie.d.ts +21 -0
- package/dist/opsgenie.d.ts.map +1 -0
- package/dist/opsgenie.js +320 -0
- package/dist/por.d.ts +38 -0
- package/dist/por.d.ts.map +1 -0
- package/dist/por.js +164 -0
- package/dist/s3.d.ts +21 -0
- package/dist/s3.d.ts.map +1 -0
- package/dist/s3.js +28878 -0
- package/dist/search.d.ts +6 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +37754 -0
- package/dist/selector.d.ts +18 -0
- package/dist/selector.d.ts.map +1 -0
- package/dist/selector.js +89 -0
- package/dist/slack.d.ts +9 -0
- package/dist/slack.d.ts.map +1 -0
- package/dist/slack.js +16844 -0
- package/dist/util.d.ts +5 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +72 -0
- package/dist/xxhash.win32-x64-msvc-hrdz34v7.node +0 -0
- package/examples/api.ts +1 -1
- package/examples/indexer.ts +1 -1
- package/examples/mode-indexer.ts +1 -1
- package/indexer.ts +11 -11
- package/log.ts +22 -4
- package/object-hash.ts +66 -0
- package/package.json +102 -4
- package/por.ts +181 -0
- package/search.ts +2 -2
- package/tsconfig.build.json +24 -0
- package/tsconfig.json +5 -5
- package/web3.ts +0 -41
package/dist/util.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
declare function range(startAt: number, endAt: number, step: number): [number, number][];
|
|
2
|
+
declare function arrayGroup<T>(array: T[], groupSize: number): T[][];
|
|
3
|
+
declare function fillRange(start: number, end: number): number[];
|
|
4
|
+
export { arrayGroup, range, fillRange };
|
|
5
|
+
//# sourceMappingURL=util.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../util.ts"],"names":[],"mappings":"AACA,iBAAS,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,sBAQ1D;AAED,iBAAS,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,SAQnD;AAKD,iBAAS,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,YAQ5C;AAED,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC"}
|
package/dist/util.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __toESM = (mod, isNodeMode, target) => {
|
|
9
|
+
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
10
|
+
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
11
|
+
for (let key of __getOwnPropNames(mod))
|
|
12
|
+
if (!__hasOwnProp.call(to, key))
|
|
13
|
+
__defProp(to, key, {
|
|
14
|
+
get: () => mod[key],
|
|
15
|
+
enumerable: true
|
|
16
|
+
});
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __moduleCache = /* @__PURE__ */ new WeakMap;
|
|
20
|
+
var __toCommonJS = (from) => {
|
|
21
|
+
var entry = __moduleCache.get(from), desc;
|
|
22
|
+
if (entry)
|
|
23
|
+
return entry;
|
|
24
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
25
|
+
if (from && typeof from === "object" || typeof from === "function")
|
|
26
|
+
__getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
|
|
27
|
+
get: () => from[key],
|
|
28
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
29
|
+
}));
|
|
30
|
+
__moduleCache.set(from, entry);
|
|
31
|
+
return entry;
|
|
32
|
+
};
|
|
33
|
+
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
34
|
+
var __export = (target, all) => {
|
|
35
|
+
for (var name in all)
|
|
36
|
+
__defProp(target, name, {
|
|
37
|
+
get: all[name],
|
|
38
|
+
enumerable: true,
|
|
39
|
+
configurable: true,
|
|
40
|
+
set: (newValue) => all[name] = () => newValue
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
44
|
+
var __require = import.meta.require;
|
|
45
|
+
|
|
46
|
+
// util.ts
|
|
47
|
+
function range(startAt, endAt, step) {
|
|
48
|
+
const arr = [];
|
|
49
|
+
for (let i = startAt;i <= endAt; i += step) {
|
|
50
|
+
arr.push([i, Math.min(endAt, i + step - 1)]);
|
|
51
|
+
}
|
|
52
|
+
return arr;
|
|
53
|
+
}
|
|
54
|
+
function arrayGroup(array, groupSize) {
|
|
55
|
+
const groups = [];
|
|
56
|
+
for (let i = 0;i < array.length; i += groupSize) {
|
|
57
|
+
groups.push(array.slice(i, i + groupSize));
|
|
58
|
+
}
|
|
59
|
+
return groups;
|
|
60
|
+
}
|
|
61
|
+
function fillRange(start, end) {
|
|
62
|
+
const result = [];
|
|
63
|
+
for (let i = start;i <= end; i++) {
|
|
64
|
+
result.push(i);
|
|
65
|
+
}
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
export {
|
|
69
|
+
range,
|
|
70
|
+
fillRange,
|
|
71
|
+
arrayGroup
|
|
72
|
+
};
|
|
Binary file
|
package/examples/api.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// $ examples/api --help
|
|
9
9
|
|
|
10
10
|
import type { Request, Response, NextFunction } from "express";
|
|
11
|
-
import { api, SENSITIVE_VALUE } from "../app
|
|
11
|
+
import { api, SENSITIVE_VALUE } from "../app";
|
|
12
12
|
|
|
13
13
|
// an example middleware
|
|
14
14
|
async function exampleMiddleware(req: Request, res: Response, next: NextFunction) {
|
package/examples/indexer.ts
CHANGED
package/examples/mode-indexer.ts
CHANGED
package/indexer.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import meow from "meow";
|
|
2
|
-
import { createRecord, getRecordByKey } from "./dynamodb
|
|
3
|
-
import { getEnvironment } from "./env
|
|
4
|
-
import { exponentialRetry } from "./availability
|
|
5
|
-
import { range as numberRange, fillRange as fillNumberRange } from "./util
|
|
6
|
-
import { getSelectorDesc, getSelectorFlags, toSelectorString } from "./selector
|
|
7
|
-
import type { SelectorFlags, Selector } from "./selector
|
|
8
|
-
import { getBinaryName } from "./cli
|
|
9
|
-
import { inline } from "./log
|
|
10
|
-
import { findDateAfter, dateRange, daysInRange as fillDateRange } from "./date
|
|
2
|
+
import { createRecord, getRecordByKey } from "./dynamodb";
|
|
3
|
+
import { getEnvironment } from "./env";
|
|
4
|
+
import { exponentialRetry } from "./availability";
|
|
5
|
+
import { range as numberRange, fillRange as fillNumberRange } from "./util";
|
|
6
|
+
import { getSelectorDesc, getSelectorFlags, toSelectorString } from "./selector";
|
|
7
|
+
import type { SelectorFlags, Selector } from "./selector";
|
|
8
|
+
import { getBinaryName } from "./cli";
|
|
9
|
+
import { inline } from "./log";
|
|
10
|
+
import { findDateAfter, dateRange, daysInRange as fillDateRange } from "./date";
|
|
11
11
|
|
|
12
12
|
const STATE_TABLE_NAME = "skynet-" + getEnvironment() + "-indexer-state";
|
|
13
13
|
|
|
@@ -643,7 +643,7 @@ ${selector ? getSelectorDesc(selector) : ""}
|
|
|
643
643
|
);
|
|
644
644
|
|
|
645
645
|
try {
|
|
646
|
-
return runMode(cli.flags);
|
|
646
|
+
return runMode(cli.flags as ModeIndexerFlags<TSelector>);
|
|
647
647
|
} catch (err) {
|
|
648
648
|
inline.error(err);
|
|
649
649
|
process.exit(1);
|
|
@@ -735,7 +735,7 @@ ${selector ? getSelectorDesc(selector) : ""}
|
|
|
735
735
|
inline.log(`[INDEXER] build successfully in ${Date.now() - startTime}ms`);
|
|
736
736
|
}
|
|
737
737
|
|
|
738
|
-
return runBuild(cli.flags).catch((err) => {
|
|
738
|
+
return runBuild(cli.flags as ModeIndexerFlags<TSelector>).catch((err) => {
|
|
739
739
|
inline.error(err);
|
|
740
740
|
process.exit(1);
|
|
741
741
|
});
|
package/log.ts
CHANGED
|
@@ -34,20 +34,38 @@ function timestamp() {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
const inline = {
|
|
37
|
+
debug: function (...args: unknown[]) {
|
|
38
|
+
if (process.env.NODE_ENV === "development") {
|
|
39
|
+
console.log(`${timestamp()} ${getLine(args)}`);
|
|
40
|
+
}
|
|
41
|
+
},
|
|
37
42
|
log: function (...args: unknown[]) {
|
|
38
|
-
|
|
43
|
+
if (process.env.NODE_ENV !== "test") {
|
|
44
|
+
console.log(`${timestamp()} ${getLine(args)}`);
|
|
45
|
+
}
|
|
39
46
|
},
|
|
40
47
|
error: function (...args: unknown[]) {
|
|
41
|
-
|
|
48
|
+
if (process.env.NODE_ENV !== "test") {
|
|
49
|
+
console.error(`${timestamp()} ${getLine(args)}`);
|
|
50
|
+
}
|
|
42
51
|
},
|
|
43
52
|
};
|
|
44
53
|
|
|
45
54
|
const logger = {
|
|
55
|
+
debug: function (...args: unknown[]) {
|
|
56
|
+
if (process.env.NODE_ENV === "development") {
|
|
57
|
+
console.log(`[${timestamp()}]`, ...args);
|
|
58
|
+
}
|
|
59
|
+
},
|
|
46
60
|
log: function (...args: unknown[]) {
|
|
47
|
-
|
|
61
|
+
if (process.env.NODE_ENV !== "test") {
|
|
62
|
+
console.log(`[${timestamp()}]`, ...args);
|
|
63
|
+
}
|
|
48
64
|
},
|
|
49
65
|
error: function (...args: unknown[]) {
|
|
50
|
-
|
|
66
|
+
if (process.env.NODE_ENV !== "test") {
|
|
67
|
+
console.error(`[${timestamp()}]`, ...args);
|
|
68
|
+
}
|
|
51
69
|
},
|
|
52
70
|
};
|
|
53
71
|
|
package/object-hash.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import xh from "@node-rs/xxhash";
|
|
2
|
+
|
|
3
|
+
export function getHash(obj: unknown) {
|
|
4
|
+
const xxh3 = xh.xxh3.Xxh3.withSeed();
|
|
5
|
+
hash(obj, xxh3);
|
|
6
|
+
return xxh3.digest().toString(16);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function hash(obj: unknown, xxh3: xh.xxh3.Xxh3) {
|
|
10
|
+
if (obj === null) {
|
|
11
|
+
xxh3.update("null");
|
|
12
|
+
} else if (obj === undefined) {
|
|
13
|
+
xxh3.update("undefined");
|
|
14
|
+
} else if (typeof obj === "string") {
|
|
15
|
+
xxh3.update(obj);
|
|
16
|
+
} else if (typeof obj === "number") {
|
|
17
|
+
xxh3.update(obj.toString());
|
|
18
|
+
} else if (typeof obj === "boolean") {
|
|
19
|
+
xxh3.update(obj.toString());
|
|
20
|
+
} else if (typeof obj === "bigint") {
|
|
21
|
+
xxh3.update(obj.toString());
|
|
22
|
+
} else if (obj instanceof Date) {
|
|
23
|
+
xxh3.update(obj.toISOString());
|
|
24
|
+
} else if (Array.isArray(obj)) {
|
|
25
|
+
arrayHash(obj, xxh3);
|
|
26
|
+
} else if (obj instanceof Set) {
|
|
27
|
+
setHash(obj, xxh3);
|
|
28
|
+
} else if (obj instanceof Map) {
|
|
29
|
+
mapHash(obj, xxh3);
|
|
30
|
+
} else if (typeof obj === "object") {
|
|
31
|
+
objectHash(obj, xxh3);
|
|
32
|
+
} else {
|
|
33
|
+
throw new Error(`Unsupported type: ${obj}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function arrayHash(array: unknown[], xxh3: xh.xxh3.Xxh3) {
|
|
38
|
+
xxh3.update("[");
|
|
39
|
+
for (const obj of array) {
|
|
40
|
+
hash(obj, xxh3);
|
|
41
|
+
}
|
|
42
|
+
xxh3.update("]");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
46
|
+
function setHash(_set: Set<unknown>, _xxh3: xh.xxh3.Xxh3) {
|
|
47
|
+
throw new Error("Set hashing not implemented");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function mapHash(map: Map<unknown, unknown>, xxh3: xh.xxh3.Xxh3) {
|
|
51
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
52
|
+
const array = Array.from(map.entries()).sort(([aKey], [bKey]) => (aKey as any).localeCompare(bKey));
|
|
53
|
+
for (const [key, value] of array) {
|
|
54
|
+
hash(key, xxh3);
|
|
55
|
+
hash(value, xxh3);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
60
|
+
function objectHash(obj: any, xxh3: xh.xxh3.Xxh3) {
|
|
61
|
+
const array = Object.entries(obj).sort(([aKey], [bKey]) => aKey.localeCompare(bKey));
|
|
62
|
+
for (const [key, value] of array) {
|
|
63
|
+
hash(key, xxh3);
|
|
64
|
+
hash(value, xxh3);
|
|
65
|
+
}
|
|
66
|
+
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,106 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@certik/skynet",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.0",
|
|
4
4
|
"description": "Skynet Shared JS library",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"
|
|
6
|
+
"exports": {
|
|
7
|
+
"./abi": {
|
|
8
|
+
"import": "./dist/abi.js",
|
|
9
|
+
"types": "./dist/abi.d.ts"
|
|
10
|
+
},
|
|
11
|
+
"./address": {
|
|
12
|
+
"import": "./dist/address.js",
|
|
13
|
+
"types": "./dist/address.d.ts"
|
|
14
|
+
},
|
|
15
|
+
"./api": {
|
|
16
|
+
"import": "./dist/api.js",
|
|
17
|
+
"types": "./dist/api.d.ts"
|
|
18
|
+
},
|
|
19
|
+
"./app": {
|
|
20
|
+
"import": "./dist/app.js",
|
|
21
|
+
"types": "./dist/app.d.ts"
|
|
22
|
+
},
|
|
23
|
+
"./availability": {
|
|
24
|
+
"import": "./dist/availability.js",
|
|
25
|
+
"types": "./dist/availability.d.ts"
|
|
26
|
+
},
|
|
27
|
+
"./cli": {
|
|
28
|
+
"import": "./dist/cli.js",
|
|
29
|
+
"types": "./dist/cli.d.ts"
|
|
30
|
+
},
|
|
31
|
+
"./const": {
|
|
32
|
+
"import": "./dist/const.js",
|
|
33
|
+
"types": "./dist/const.d.ts"
|
|
34
|
+
},
|
|
35
|
+
"./databricks": {
|
|
36
|
+
"import": "./dist/databricks.js",
|
|
37
|
+
"types": "./dist/databricks.d.ts"
|
|
38
|
+
},
|
|
39
|
+
"./date": {
|
|
40
|
+
"import": "./dist/date.js",
|
|
41
|
+
"types": "./dist/date.d.ts"
|
|
42
|
+
},
|
|
43
|
+
"./deploy": {
|
|
44
|
+
"import": "./dist/deploy.js",
|
|
45
|
+
"types": "./dist/deploy.d.ts"
|
|
46
|
+
},
|
|
47
|
+
"./dynamodb": {
|
|
48
|
+
"import": "./dist/dynamodb.js",
|
|
49
|
+
"types": "./dist/dynamodb.d.ts"
|
|
50
|
+
},
|
|
51
|
+
"./env": {
|
|
52
|
+
"import": "./dist/env.js",
|
|
53
|
+
"types": "./dist/env.d.ts"
|
|
54
|
+
},
|
|
55
|
+
"./graphql": {
|
|
56
|
+
"import": "./dist/graphql.js",
|
|
57
|
+
"types": "./dist/graphql.d.ts"
|
|
58
|
+
},
|
|
59
|
+
"./indexer": {
|
|
60
|
+
"import": "./dist/indexer.js",
|
|
61
|
+
"types": "./dist/indexer.d.ts"
|
|
62
|
+
},
|
|
63
|
+
"./log": {
|
|
64
|
+
"import": "./dist/log.js",
|
|
65
|
+
"types": "./dist/log.d.ts"
|
|
66
|
+
},
|
|
67
|
+
"./object-hash": {
|
|
68
|
+
"import": "./dist/object-hash.js",
|
|
69
|
+
"types": "./dist/object-hash.d.ts"
|
|
70
|
+
},
|
|
71
|
+
"./opsgenie": {
|
|
72
|
+
"import": "./dist/opsgenie.js",
|
|
73
|
+
"types": "./dist/opsgenie.d.ts"
|
|
74
|
+
},
|
|
75
|
+
"./por": {
|
|
76
|
+
"import": "./dist/por.js",
|
|
77
|
+
"types": "./dist/por.d.ts"
|
|
78
|
+
},
|
|
79
|
+
"./s3": {
|
|
80
|
+
"import": "./dist/s3.js",
|
|
81
|
+
"types": "./dist/s3.d.ts"
|
|
82
|
+
},
|
|
83
|
+
"./search": {
|
|
84
|
+
"import": "./dist/search.js",
|
|
85
|
+
"types": "./dist/search.d.ts"
|
|
86
|
+
},
|
|
87
|
+
"./selector": {
|
|
88
|
+
"import": "./dist/selector.js",
|
|
89
|
+
"types": "./dist/selector.d.ts"
|
|
90
|
+
},
|
|
91
|
+
"./slack": {
|
|
92
|
+
"import": "./dist/slack.js",
|
|
93
|
+
"types": "./dist/slack.d.ts"
|
|
94
|
+
},
|
|
95
|
+
"./util": {
|
|
96
|
+
"import": "./dist/util.js",
|
|
97
|
+
"types": "./dist/util.d.ts"
|
|
98
|
+
}
|
|
99
|
+
},
|
|
7
100
|
"author": "CertiK Engineering",
|
|
8
101
|
"scripts": {
|
|
102
|
+
"build": "bun build --outdir dist --target bun --format esm *.ts && tsc --project tsconfig.build.json --emitDeclarationOnly",
|
|
103
|
+
"clean": "rimraf dist",
|
|
9
104
|
"lint": "eslint '*.ts' test/*.ts",
|
|
10
105
|
"test": "doppler run -- bun test",
|
|
11
106
|
"format": "prettier --write '*.ts' '**/*.ts'",
|
|
@@ -21,14 +116,17 @@
|
|
|
21
116
|
"@aws-sdk/lib-dynamodb": "^3.758.0",
|
|
22
117
|
"@databricks/sql": "^1.9.0",
|
|
23
118
|
"@elastic/elasticsearch": "^8.17.1",
|
|
119
|
+
"@node-rs/xxhash": "^1.7.6",
|
|
24
120
|
"@slack/web-api": "^6.13.0",
|
|
25
121
|
"chalk": "^5.4.1",
|
|
26
122
|
"execa": "^9.5.2",
|
|
27
123
|
"express": "^4.21.2",
|
|
28
124
|
"md5": "^2.3.0",
|
|
29
125
|
"meow": "^13.2.0",
|
|
126
|
+
"p-memoize": "^7.1.1",
|
|
127
|
+
"p-throttle": "^7.0.0",
|
|
128
|
+
"quick-lru": "^7.0.0",
|
|
30
129
|
"type-fest": "^4.35.0",
|
|
31
|
-
"web3": "^4.16.0",
|
|
32
130
|
"which": "^5.0.0"
|
|
33
131
|
},
|
|
34
132
|
"devDependencies": {
|
|
@@ -43,7 +141,7 @@
|
|
|
43
141
|
"eslint-plugin-prettier": "^5.2.3",
|
|
44
142
|
"prettier": "^3.5.2",
|
|
45
143
|
"typescript": "^5.8.2",
|
|
46
|
-
"
|
|
144
|
+
"rimraf": "^6.0.1"
|
|
47
145
|
},
|
|
48
146
|
"license": "MIT",
|
|
49
147
|
"publishConfig": {
|
package/por.ts
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { CryptoHasher } from "bun";
|
|
2
|
+
|
|
3
|
+
export interface UserLiability {
|
|
4
|
+
userHash: string;
|
|
5
|
+
balance: number;
|
|
6
|
+
token?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface MerkleProof {
|
|
10
|
+
userHash: string;
|
|
11
|
+
balance: number;
|
|
12
|
+
token?: string;
|
|
13
|
+
proof: string[];
|
|
14
|
+
positions: ('left' | 'right')[];
|
|
15
|
+
rootHash: string;
|
|
16
|
+
leafIndex: number;
|
|
17
|
+
hashFunction?: (data: string) => string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface MerkleNode {
|
|
21
|
+
hash: string;
|
|
22
|
+
left?: MerkleNode;
|
|
23
|
+
right?: MerkleNode;
|
|
24
|
+
data?: UserLiability;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export class MerkleTreePoR {
|
|
28
|
+
private leaves: string[] = [];
|
|
29
|
+
private tree: MerkleNode[][] = [];
|
|
30
|
+
private userMap: Map<string, number> = new Map();
|
|
31
|
+
private userData: UserLiability[] = [];
|
|
32
|
+
private hashFunction: (data: string) => string;
|
|
33
|
+
|
|
34
|
+
constructor(users: UserLiability[], hashFunction?: (data: string) => string) {
|
|
35
|
+
this.userData = [...users];
|
|
36
|
+
this.hashFunction = hashFunction || this.defaultSHA256Hash;
|
|
37
|
+
this.buildTree();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Default SHA-256 hash function
|
|
41
|
+
private static defaultSHA256Hash(data: string): string {
|
|
42
|
+
const hasher = new CryptoHasher("sha256");
|
|
43
|
+
hasher.update(data);
|
|
44
|
+
return hasher.digest("hex");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private defaultSHA256Hash(data: string): string {
|
|
48
|
+
return MerkleTreePoR.defaultSHA256Hash(data);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Configurable hash function
|
|
52
|
+
private hash(data: string): string {
|
|
53
|
+
return this.hashFunction(data);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
// hash user data
|
|
58
|
+
private createLeafHash(user: UserLiability): string {
|
|
59
|
+
const leafData = `${user.userHash}:${user.balance}:${user.token || ''}`;
|
|
60
|
+
return this.hash(leafData);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
private buildTree(): void {
|
|
64
|
+
if (this.userData.length === 0) {
|
|
65
|
+
throw new Error('Cannot build tree with empty user data');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Create leaf hashes and store user mapping
|
|
69
|
+
this.leaves = this.userData.map((user, index) => {
|
|
70
|
+
const leafHash = this.createLeafHash(user);
|
|
71
|
+
this.userMap.set(`${user.userHash}:${user.token || ''}`, index);
|
|
72
|
+
return leafHash;
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Start with leaf level
|
|
76
|
+
let currentLevel = this.leaves;
|
|
77
|
+
this.tree.push(currentLevel.map(hash => ({ hash })));
|
|
78
|
+
|
|
79
|
+
// Build tree bottom-up
|
|
80
|
+
while (currentLevel.length > 1) {
|
|
81
|
+
const nextLevel: string[] = [];
|
|
82
|
+
const nextLevelNodes: MerkleNode[] = [];
|
|
83
|
+
|
|
84
|
+
for (let i = 0; i < currentLevel.length; i += 2) {
|
|
85
|
+
const left = currentLevel[i];
|
|
86
|
+
const right = i + 1 < currentLevel.length
|
|
87
|
+
? currentLevel[i + 1]
|
|
88
|
+
: left; // Duplicate if odd number
|
|
89
|
+
|
|
90
|
+
const parentHash = this.hash(left + right);
|
|
91
|
+
nextLevel.push(parentHash);
|
|
92
|
+
|
|
93
|
+
const leftNode = this.tree[this.tree.length - 1][i];
|
|
94
|
+
const rightNode = i + 1 < currentLevel.length
|
|
95
|
+
? this.tree[this.tree.length - 1][i + 1]
|
|
96
|
+
: leftNode;
|
|
97
|
+
|
|
98
|
+
nextLevelNodes.push({
|
|
99
|
+
hash: parentHash,
|
|
100
|
+
left: leftNode,
|
|
101
|
+
right: rightNode
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
currentLevel = nextLevel;
|
|
106
|
+
this.tree.push(nextLevelNodes);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// get root hash of created tree
|
|
111
|
+
getRootHash(): string {
|
|
112
|
+
if (this.tree.length === 0) {
|
|
113
|
+
throw new Error('Merkle tree not built');
|
|
114
|
+
}
|
|
115
|
+
return this.tree[this.tree.length - 1][0].hash;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// generate merkle proof
|
|
119
|
+
generateProof(userHash: string, token?: string): MerkleProof {
|
|
120
|
+
const key = `${userHash}:${token || ''}`;
|
|
121
|
+
const leafIndex = this.userMap.get(key);
|
|
122
|
+
if (leafIndex === undefined) {
|
|
123
|
+
throw new Error(`${userHash} not found in merkle tree for token ${token}`);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const user = this.userData[leafIndex];
|
|
127
|
+
const proof: string[] = [];
|
|
128
|
+
const positions: ('left' | 'right')[] = [];
|
|
129
|
+
|
|
130
|
+
let currentIndex = leafIndex;
|
|
131
|
+
|
|
132
|
+
// Walk up the tree collecting sibling hashes
|
|
133
|
+
for (let level = 0; level < this.tree.length - 1; level++) {
|
|
134
|
+
const currentLevelSize = this.tree[level].length;
|
|
135
|
+
const isRightNode = currentIndex % 2 === 1;
|
|
136
|
+
const siblingIndex = isRightNode ? currentIndex - 1 : currentIndex + 1;
|
|
137
|
+
|
|
138
|
+
if (siblingIndex < currentLevelSize) {
|
|
139
|
+
proof.push(this.tree[level][siblingIndex].hash);
|
|
140
|
+
positions.push(isRightNode ? 'left' : 'right');
|
|
141
|
+
} else {
|
|
142
|
+
// When odd number, the last node is duplicated
|
|
143
|
+
proof.push(this.tree[level][currentIndex].hash);
|
|
144
|
+
positions.push(isRightNode ? 'left' : 'right');
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
currentIndex = Math.floor(currentIndex / 2);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return {
|
|
151
|
+
userHash: user.userHash,
|
|
152
|
+
balance: user.balance,
|
|
153
|
+
token: user.token,
|
|
154
|
+
proof,
|
|
155
|
+
positions,
|
|
156
|
+
rootHash: this.getRootHash(),
|
|
157
|
+
leafIndex,
|
|
158
|
+
hashFunction: this.hashFunction !== this.defaultSHA256Hash ? this.hashFunction : undefined
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// verify inclusion using proof
|
|
163
|
+
static verifyProof(merkleProof: MerkleProof): boolean {
|
|
164
|
+
const leafData = `${merkleProof.userHash}:${merkleProof.balance}:${merkleProof.token || ''}`;
|
|
165
|
+
const hashFunction = merkleProof.hashFunction || MerkleTreePoR.defaultSHA256Hash;
|
|
166
|
+
let currentHash = hashFunction(leafData);
|
|
167
|
+
|
|
168
|
+
for (let i = 0; i < merkleProof.proof.length; i++) {
|
|
169
|
+
const siblingHash = merkleProof.proof[i];
|
|
170
|
+
const position = merkleProof.positions[i];
|
|
171
|
+
|
|
172
|
+
if (position === 'left') {
|
|
173
|
+
currentHash = hashFunction(siblingHash + currentHash);
|
|
174
|
+
} else {
|
|
175
|
+
currentHash = hashFunction(currentHash + siblingHash);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return currentHash === merkleProof.rootHash;
|
|
180
|
+
}
|
|
181
|
+
}
|
package/search.ts
CHANGED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "./tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"noEmit": false,
|
|
5
|
+
"emitDeclarationOnly": true,
|
|
6
|
+
"outDir": "dist",
|
|
7
|
+
"declaration": true,
|
|
8
|
+
"declarationMap": true,
|
|
9
|
+
"target": "ES2020",
|
|
10
|
+
"module": "ES2020",
|
|
11
|
+
"moduleResolution": "bundler",
|
|
12
|
+
"allowImportingTsExtensions": false,
|
|
13
|
+
"verbatimModuleSyntax": false
|
|
14
|
+
},
|
|
15
|
+
"include": [
|
|
16
|
+
"*.ts"
|
|
17
|
+
],
|
|
18
|
+
"exclude": [
|
|
19
|
+
"test/**/*",
|
|
20
|
+
"examples/**/*",
|
|
21
|
+
"dist",
|
|
22
|
+
"node_modules"
|
|
23
|
+
]
|
|
24
|
+
}
|
package/tsconfig.json
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
3
|
// Enable latest features
|
|
4
|
-
"lib": [
|
|
4
|
+
"lib": [
|
|
5
|
+
"ESNext",
|
|
6
|
+
"DOM"
|
|
7
|
+
],
|
|
5
8
|
"target": "ESNext",
|
|
6
9
|
"module": "ESNext",
|
|
7
10
|
"moduleDetection": "force",
|
|
8
11
|
"allowJs": true,
|
|
9
|
-
|
|
10
12
|
// Bundler mode
|
|
11
13
|
"moduleResolution": "bundler",
|
|
12
14
|
"allowImportingTsExtensions": true,
|
|
13
15
|
"verbatimModuleSyntax": true,
|
|
14
16
|
"noEmit": true,
|
|
15
|
-
|
|
16
17
|
// Best practices
|
|
17
|
-
"strict":
|
|
18
|
+
"strict": false,
|
|
18
19
|
"skipLibCheck": true,
|
|
19
20
|
"noFallthroughCasesInSwitch": true,
|
|
20
|
-
|
|
21
21
|
// Some stricter flags
|
|
22
22
|
"noUnusedLocals": true,
|
|
23
23
|
"noUnusedParameters": true,
|