@certik/skynet 0.24.0 → 0.25.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/CHANGELOG.md +9 -0
- package/README.md +8 -2
- package/dist/api.js +38 -38
- package/dist/app.js +279 -279
- package/dist/deploy.js +19 -19
- package/dist/dynamodb.js +22 -22
- package/dist/graphql.d.ts +2 -1
- package/dist/graphql.js +11 -4
- package/dist/indexer.js +132 -132
- package/dist/por.d.ts +1 -1
- package/dist/slack.d.ts +1 -1
- package/dist/slack.js +1 -1
- package/examples/api.ts +0 -0
- package/examples/indexer.ts +0 -0
- package/examples/mode-indexer.ts +0 -0
- package/package.json +1 -10
- package/src/graphql.ts +14 -4
- package/src/por.ts +18 -23
- package/.vscode/settings.json +0 -5
- package/dist/databricks.d.ts +0 -3
- package/dist/databricks.js +0 -208
- package/src/databricks.ts +0 -82
package/dist/dynamodb.js
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
// src/util.ts
|
|
2
|
+
function range(startAt, endAt, step) {
|
|
3
|
+
const arr = [];
|
|
4
|
+
for (let i = startAt;i <= endAt; i += step) {
|
|
5
|
+
arr.push([i, Math.min(endAt, i + step - 1)]);
|
|
6
|
+
}
|
|
7
|
+
return arr;
|
|
8
|
+
}
|
|
9
|
+
function arrayGroup(array, groupSize) {
|
|
10
|
+
const groups = [];
|
|
11
|
+
for (let i = 0;i < array.length; i += groupSize) {
|
|
12
|
+
groups.push(array.slice(i, i + groupSize));
|
|
13
|
+
}
|
|
14
|
+
return groups;
|
|
15
|
+
}
|
|
16
|
+
function fillRange(start, end) {
|
|
17
|
+
const result = [];
|
|
18
|
+
for (let i = start;i <= end; i++) {
|
|
19
|
+
result.push(i);
|
|
20
|
+
}
|
|
21
|
+
return result;
|
|
22
|
+
}
|
|
1
23
|
// src/object-hash.ts
|
|
2
24
|
import xh from "@node-rs/xxhash";
|
|
3
25
|
function getHash(obj) {
|
|
@@ -124,28 +146,6 @@ function memoize(func, options) {
|
|
|
124
146
|
}
|
|
125
147
|
return pMemoize(func, options);
|
|
126
148
|
}
|
|
127
|
-
// src/util.ts
|
|
128
|
-
function range(startAt, endAt, step) {
|
|
129
|
-
const arr = [];
|
|
130
|
-
for (let i = startAt;i <= endAt; i += step) {
|
|
131
|
-
arr.push([i, Math.min(endAt, i + step - 1)]);
|
|
132
|
-
}
|
|
133
|
-
return arr;
|
|
134
|
-
}
|
|
135
|
-
function arrayGroup(array, groupSize) {
|
|
136
|
-
const groups = [];
|
|
137
|
-
for (let i = 0;i < array.length; i += groupSize) {
|
|
138
|
-
groups.push(array.slice(i, i + groupSize));
|
|
139
|
-
}
|
|
140
|
-
return groups;
|
|
141
|
-
}
|
|
142
|
-
function fillRange(start, end) {
|
|
143
|
-
const result = [];
|
|
144
|
-
for (let i = start;i <= end; i++) {
|
|
145
|
-
result.push(i);
|
|
146
|
-
}
|
|
147
|
-
return result;
|
|
148
|
-
}
|
|
149
149
|
// src/dynamodb.ts
|
|
150
150
|
import {
|
|
151
151
|
DynamoDBDocumentClient,
|
package/dist/graphql.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
type GraphqlVariables = {
|
|
2
2
|
[key: string]: unknown;
|
|
3
3
|
};
|
|
4
|
-
|
|
4
|
+
type GraphQLVersion = "v1" | "v2";
|
|
5
|
+
export declare function gql<T>(query: string, variables?: GraphqlVariables, version?: GraphQLVersion): Promise<T>;
|
|
5
6
|
export {};
|
package/dist/graphql.js
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
// src/graphql.ts
|
|
2
|
-
async function gql(query, variables = {}) {
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
async function gql(query, variables = {}, version = "v1") {
|
|
3
|
+
if (!["v1", "v2"].includes(version)) {
|
|
4
|
+
throw new Error(`Invalid GraphQL version: ${version}`);
|
|
5
|
+
}
|
|
6
|
+
let endpoint = process.env["SKYNET_GRAPHQL_ENDPOINT"];
|
|
7
|
+
let apiKey = process.env["SKYNET_GRAPHQL_API_KEY"];
|
|
8
|
+
if (version === "v2") {
|
|
9
|
+
endpoint = process.env["SKYNET_GRAPHQL_ENDPOINT_V2"];
|
|
10
|
+
apiKey = process.env["SKYNET_GRAPHQL_API_KEY_V2"];
|
|
11
|
+
}
|
|
5
12
|
if (!endpoint || !apiKey) {
|
|
6
|
-
throw new Error(
|
|
13
|
+
throw new Error(`Missing GraphQL ${version} endpoint or API key`);
|
|
7
14
|
}
|
|
8
15
|
const res = await fetch(endpoint, {
|
|
9
16
|
method: "POST",
|
package/dist/indexer.js
CHANGED
|
@@ -1,41 +1,3 @@
|
|
|
1
|
-
// src/selector.ts
|
|
2
|
-
function getSelectorDesc(selector) {
|
|
3
|
-
return Object.keys(selector).map((name) => {
|
|
4
|
-
return ` --${name.padEnd(14)}${selector[name].desc || selector[name].description || ""}`;
|
|
5
|
-
}).join(`
|
|
6
|
-
`);
|
|
7
|
-
}
|
|
8
|
-
function getSelectorFlags(selector) {
|
|
9
|
-
return Object.keys(selector).reduce((acc, name) => {
|
|
10
|
-
const flag = {
|
|
11
|
-
type: selector[name].type || "string",
|
|
12
|
-
...selector[name]
|
|
13
|
-
};
|
|
14
|
-
if (!selector[name].optional && selector[name].isRequired !== false) {
|
|
15
|
-
flag.isRequired = true;
|
|
16
|
-
}
|
|
17
|
-
return { ...acc, [name]: flag };
|
|
18
|
-
}, {});
|
|
19
|
-
}
|
|
20
|
-
function toSelectorString(selectorFlags, delim = ",") {
|
|
21
|
-
return Object.keys(selectorFlags).sort().map((flag) => {
|
|
22
|
-
return `${flag}=${selectorFlags[flag]}`;
|
|
23
|
-
}).join(delim);
|
|
24
|
-
}
|
|
25
|
-
function normalizeSelectorValue(v) {
|
|
26
|
-
return v.replace(/[^A-Za-z0-9]+/g, "-");
|
|
27
|
-
}
|
|
28
|
-
function getJobName(name, selectorFlags, mode) {
|
|
29
|
-
const selectorNamePart = Object.keys(selectorFlags).sort().map((name2) => selectorFlags[name2]).join("-");
|
|
30
|
-
let jobName = name;
|
|
31
|
-
if (mode) {
|
|
32
|
-
jobName += `-${mode}`;
|
|
33
|
-
}
|
|
34
|
-
if (selectorNamePart.length > 0) {
|
|
35
|
-
jobName += `-${normalizeSelectorValue(selectorNamePart)}`;
|
|
36
|
-
}
|
|
37
|
-
return jobName;
|
|
38
|
-
}
|
|
39
1
|
// src/env.ts
|
|
40
2
|
function ensureAndGet(envName, defaultValue) {
|
|
41
3
|
return process.env[envName] || defaultValue;
|
|
@@ -55,63 +17,56 @@ function isProduction() {
|
|
|
55
17
|
function isDev() {
|
|
56
18
|
return getEnvironment() === "dev";
|
|
57
19
|
}
|
|
58
|
-
// src/
|
|
59
|
-
function
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
if (Array.isArray(o)) {
|
|
64
|
-
return `[${o.map(print).join(", ")}]`;
|
|
20
|
+
// src/util.ts
|
|
21
|
+
function range(startAt, endAt, step) {
|
|
22
|
+
const arr = [];
|
|
23
|
+
for (let i = startAt;i <= endAt; i += step) {
|
|
24
|
+
arr.push([i, Math.min(endAt, i + step - 1)]);
|
|
65
25
|
}
|
|
66
|
-
|
|
67
|
-
|
|
26
|
+
return arr;
|
|
27
|
+
}
|
|
28
|
+
function arrayGroup(array, groupSize) {
|
|
29
|
+
const groups = [];
|
|
30
|
+
for (let i = 0;i < array.length; i += groupSize) {
|
|
31
|
+
groups.push(array.slice(i, i + groupSize));
|
|
68
32
|
}
|
|
69
|
-
return
|
|
33
|
+
return groups;
|
|
70
34
|
}
|
|
71
|
-
function
|
|
72
|
-
|
|
73
|
-
for (let i =
|
|
74
|
-
|
|
35
|
+
function fillRange(start, end) {
|
|
36
|
+
const result = [];
|
|
37
|
+
for (let i = start;i <= end; i++) {
|
|
38
|
+
result.push(i);
|
|
75
39
|
}
|
|
76
|
-
return
|
|
40
|
+
return result;
|
|
77
41
|
}
|
|
78
|
-
|
|
79
|
-
|
|
42
|
+
// src/date.ts
|
|
43
|
+
var MS_IN_A_DAY = 3600 * 24 * 1000;
|
|
44
|
+
function getDateOnly(date) {
|
|
45
|
+
return new Date(date).toISOString().split("T")[0];
|
|
80
46
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
},
|
|
92
|
-
error: function(...args) {
|
|
93
|
-
if (true) {
|
|
94
|
-
console.error(`${timestamp()} ${getLine(args)}`);
|
|
95
|
-
}
|
|
47
|
+
function findDateAfter(date, n) {
|
|
48
|
+
const d = new Date(date);
|
|
49
|
+
const after = new Date(d.getTime() + MS_IN_A_DAY * n);
|
|
50
|
+
return getDateOnly(after);
|
|
51
|
+
}
|
|
52
|
+
function daysInRange(from, to) {
|
|
53
|
+
const fromTime = new Date(from).getTime();
|
|
54
|
+
const toTime = new Date(to).getTime();
|
|
55
|
+
if (fromTime > toTime) {
|
|
56
|
+
throw new Error(`range to date couldn't be earlier than range from date`);
|
|
96
57
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
console.log(`[${timestamp()}]`, ...args);
|
|
102
|
-
}
|
|
103
|
-
},
|
|
104
|
-
log: function(...args) {
|
|
105
|
-
if (true) {
|
|
106
|
-
console.log(`[${timestamp()}]`, ...args);
|
|
107
|
-
}
|
|
108
|
-
},
|
|
109
|
-
error: function(...args) {
|
|
110
|
-
if (true) {
|
|
111
|
-
console.error(`[${timestamp()}]`, ...args);
|
|
112
|
-
}
|
|
58
|
+
const daysBetween = Math.floor((toTime - fromTime) / MS_IN_A_DAY);
|
|
59
|
+
const dates = [getDateOnly(new Date(fromTime))];
|
|
60
|
+
for (let i = 1;i <= daysBetween; i += 1) {
|
|
61
|
+
dates.push(getDateOnly(new Date(fromTime + i * MS_IN_A_DAY)));
|
|
113
62
|
}
|
|
114
|
-
|
|
63
|
+
return dates;
|
|
64
|
+
}
|
|
65
|
+
function dateRange(from, to, step) {
|
|
66
|
+
const days = daysInRange(from, to);
|
|
67
|
+
const windows = arrayGroup(days, step);
|
|
68
|
+
return windows.map((w) => [w[0], w[w.length - 1]]);
|
|
69
|
+
}
|
|
115
70
|
// src/object-hash.ts
|
|
116
71
|
import xh from "@node-rs/xxhash";
|
|
117
72
|
function getHash(obj) {
|
|
@@ -238,28 +193,63 @@ function memoize(func, options) {
|
|
|
238
193
|
}
|
|
239
194
|
return pMemoize(func, options);
|
|
240
195
|
}
|
|
241
|
-
// src/
|
|
242
|
-
function
|
|
243
|
-
|
|
244
|
-
for (let i = startAt;i <= endAt; i += step) {
|
|
245
|
-
arr.push([i, Math.min(endAt, i + step - 1)]);
|
|
246
|
-
}
|
|
247
|
-
return arr;
|
|
196
|
+
// src/log.ts
|
|
197
|
+
function isObject(a) {
|
|
198
|
+
return !!a && a.constructor === Object;
|
|
248
199
|
}
|
|
249
|
-
function
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
groups.push(array.slice(i, i + groupSize));
|
|
200
|
+
function print(o) {
|
|
201
|
+
if (Array.isArray(o)) {
|
|
202
|
+
return `[${o.map(print).join(", ")}]`;
|
|
253
203
|
}
|
|
254
|
-
|
|
204
|
+
if (isObject(o)) {
|
|
205
|
+
return `{${Object.keys(o).map((k) => `${k}: ${o[k]}`).join(", ")}}`;
|
|
206
|
+
}
|
|
207
|
+
return `${o}`;
|
|
255
208
|
}
|
|
256
|
-
function
|
|
257
|
-
|
|
258
|
-
for (let i =
|
|
259
|
-
|
|
209
|
+
function getLine(params) {
|
|
210
|
+
let line = "";
|
|
211
|
+
for (let i = 0, l = params.length;i < l; i++) {
|
|
212
|
+
line += `${print(params[i])} `.replace(/\n/gm, "\t");
|
|
260
213
|
}
|
|
261
|
-
return
|
|
214
|
+
return line.trim();
|
|
262
215
|
}
|
|
216
|
+
function timestamp() {
|
|
217
|
+
return new Date().toISOString();
|
|
218
|
+
}
|
|
219
|
+
var inline = {
|
|
220
|
+
debug: function(...args) {
|
|
221
|
+
if (true) {
|
|
222
|
+
console.log(`${timestamp()} ${getLine(args)}`);
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
log: function(...args) {
|
|
226
|
+
if (true) {
|
|
227
|
+
console.log(`${timestamp()} ${getLine(args)}`);
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
error: function(...args) {
|
|
231
|
+
if (true) {
|
|
232
|
+
console.error(`${timestamp()} ${getLine(args)}`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
var logger = {
|
|
237
|
+
debug: function(...args) {
|
|
238
|
+
if (true) {
|
|
239
|
+
console.log(`[${timestamp()}]`, ...args);
|
|
240
|
+
}
|
|
241
|
+
},
|
|
242
|
+
log: function(...args) {
|
|
243
|
+
if (true) {
|
|
244
|
+
console.log(`[${timestamp()}]`, ...args);
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
error: function(...args) {
|
|
248
|
+
if (true) {
|
|
249
|
+
console.error(`[${timestamp()}]`, ...args);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
};
|
|
263
253
|
// src/dynamodb.ts
|
|
264
254
|
import {
|
|
265
255
|
DynamoDBDocumentClient,
|
|
@@ -574,6 +564,44 @@ async function deleteRecordsByHashKey(tableName, indexName, hashKeyValue, verbos
|
|
|
574
564
|
}
|
|
575
565
|
return totalDeleted;
|
|
576
566
|
}
|
|
567
|
+
// src/selector.ts
|
|
568
|
+
function getSelectorDesc(selector) {
|
|
569
|
+
return Object.keys(selector).map((name) => {
|
|
570
|
+
return ` --${name.padEnd(14)}${selector[name].desc || selector[name].description || ""}`;
|
|
571
|
+
}).join(`
|
|
572
|
+
`);
|
|
573
|
+
}
|
|
574
|
+
function getSelectorFlags(selector) {
|
|
575
|
+
return Object.keys(selector).reduce((acc, name) => {
|
|
576
|
+
const flag = {
|
|
577
|
+
type: selector[name].type || "string",
|
|
578
|
+
...selector[name]
|
|
579
|
+
};
|
|
580
|
+
if (!selector[name].optional && selector[name].isRequired !== false) {
|
|
581
|
+
flag.isRequired = true;
|
|
582
|
+
}
|
|
583
|
+
return { ...acc, [name]: flag };
|
|
584
|
+
}, {});
|
|
585
|
+
}
|
|
586
|
+
function toSelectorString(selectorFlags, delim = ",") {
|
|
587
|
+
return Object.keys(selectorFlags).sort().map((flag) => {
|
|
588
|
+
return `${flag}=${selectorFlags[flag]}`;
|
|
589
|
+
}).join(delim);
|
|
590
|
+
}
|
|
591
|
+
function normalizeSelectorValue(v) {
|
|
592
|
+
return v.replace(/[^A-Za-z0-9]+/g, "-");
|
|
593
|
+
}
|
|
594
|
+
function getJobName(name, selectorFlags, mode) {
|
|
595
|
+
const selectorNamePart = Object.keys(selectorFlags).sort().map((name2) => selectorFlags[name2]).join("-");
|
|
596
|
+
let jobName = name;
|
|
597
|
+
if (mode) {
|
|
598
|
+
jobName += `-${mode}`;
|
|
599
|
+
}
|
|
600
|
+
if (selectorNamePart.length > 0) {
|
|
601
|
+
jobName += `-${normalizeSelectorValue(selectorNamePart)}`;
|
|
602
|
+
}
|
|
603
|
+
return jobName;
|
|
604
|
+
}
|
|
577
605
|
// src/cli.ts
|
|
578
606
|
import path from "path";
|
|
579
607
|
import fs from "fs";
|
|
@@ -609,34 +637,6 @@ function detectBin() {
|
|
|
609
637
|
const wd = detectDirectory(process.argv[1], "package.json");
|
|
610
638
|
return process.argv[1].slice(wd.length + path.sep.length).replace(path.sep, "/");
|
|
611
639
|
}
|
|
612
|
-
// src/date.ts
|
|
613
|
-
var MS_IN_A_DAY = 3600 * 24 * 1000;
|
|
614
|
-
function getDateOnly(date) {
|
|
615
|
-
return new Date(date).toISOString().split("T")[0];
|
|
616
|
-
}
|
|
617
|
-
function findDateAfter(date, n) {
|
|
618
|
-
const d = new Date(date);
|
|
619
|
-
const after = new Date(d.getTime() + MS_IN_A_DAY * n);
|
|
620
|
-
return getDateOnly(after);
|
|
621
|
-
}
|
|
622
|
-
function daysInRange(from, to) {
|
|
623
|
-
const fromTime = new Date(from).getTime();
|
|
624
|
-
const toTime = new Date(to).getTime();
|
|
625
|
-
if (fromTime > toTime) {
|
|
626
|
-
throw new Error(`range to date couldn't be earlier than range from date`);
|
|
627
|
-
}
|
|
628
|
-
const daysBetween = Math.floor((toTime - fromTime) / MS_IN_A_DAY);
|
|
629
|
-
const dates = [getDateOnly(new Date(fromTime))];
|
|
630
|
-
for (let i = 1;i <= daysBetween; i += 1) {
|
|
631
|
-
dates.push(getDateOnly(new Date(fromTime + i * MS_IN_A_DAY)));
|
|
632
|
-
}
|
|
633
|
-
return dates;
|
|
634
|
-
}
|
|
635
|
-
function dateRange(from, to, step) {
|
|
636
|
-
const days = daysInRange(from, to);
|
|
637
|
-
const windows = arrayGroup(days, step);
|
|
638
|
-
return windows.map((w) => [w[0], w[w.length - 1]]);
|
|
639
|
-
}
|
|
640
640
|
// src/indexer.ts
|
|
641
641
|
import meow from "meow";
|
|
642
642
|
var STATE_TABLE_NAME = "skynet-" + getEnvironment() + "-indexer-state";
|
package/dist/por.d.ts
CHANGED
package/dist/slack.d.ts
CHANGED
package/dist/slack.js
CHANGED
|
@@ -16,7 +16,7 @@ async function postMessageToConversation({
|
|
|
16
16
|
const client = getClient(token);
|
|
17
17
|
const post = typeof conversationId === "string" ? { channel: conversationId, text: message } : message;
|
|
18
18
|
if (verbose) {
|
|
19
|
-
console.log(`posting to slack
|
|
19
|
+
console.log(`posting to slack:`, JSON.stringify(post, null, 2));
|
|
20
20
|
}
|
|
21
21
|
await client.chat.postMessage(post);
|
|
22
22
|
} catch (error) {
|
package/examples/api.ts
CHANGED
|
File without changes
|
package/examples/indexer.ts
CHANGED
|
File without changes
|
package/examples/mode-indexer.ts
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@certik/skynet",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.1",
|
|
4
4
|
"description": "Skynet Shared JS library",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -32,10 +32,6 @@
|
|
|
32
32
|
"import": "./dist/const.js",
|
|
33
33
|
"types": "./dist/const.d.ts"
|
|
34
34
|
},
|
|
35
|
-
"./databricks": {
|
|
36
|
-
"import": "./dist/databricks.js",
|
|
37
|
-
"types": "./dist/databricks.d.ts"
|
|
38
|
-
},
|
|
39
35
|
"./date": {
|
|
40
36
|
"import": "./dist/date.js",
|
|
41
37
|
"types": "./dist/date.d.ts"
|
|
@@ -114,7 +110,6 @@
|
|
|
114
110
|
"@aws-sdk/client-s3": "^3.975.0",
|
|
115
111
|
"@aws-sdk/client-sqs": "^3.975.0",
|
|
116
112
|
"@aws-sdk/lib-dynamodb": "^3.975.0",
|
|
117
|
-
"@databricks/sql": "^1.12.0",
|
|
118
113
|
"@elastic/elasticsearch": "^8.19.1",
|
|
119
114
|
"@node-rs/xxhash": "^1.7.6",
|
|
120
115
|
"@slack/web-api": "^7.13.0",
|
|
@@ -145,9 +140,5 @@
|
|
|
145
140
|
"license": "MIT",
|
|
146
141
|
"publishConfig": {
|
|
147
142
|
"access": "public"
|
|
148
|
-
},
|
|
149
|
-
"patchedDependencies": {
|
|
150
|
-
"@databricks/sql@1.9.0": "patches/@databricks%2Fsql@1.9.0.patch",
|
|
151
|
-
"@databricks/sql@1.12.0": "patches/@databricks%2Fsql@1.12.0.patch"
|
|
152
143
|
}
|
|
153
144
|
}
|
package/src/graphql.ts
CHANGED
|
@@ -12,12 +12,22 @@ type GraphQLResponse<TData> = {
|
|
|
12
12
|
errors?: GraphQLError[];
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
type GraphQLVersion = "v1" | "v2";
|
|
16
|
+
|
|
17
|
+
export async function gql<T>(query: string, variables: GraphqlVariables = {}, version: GraphQLVersion = "v1") {
|
|
18
|
+
if (!["v1", "v2"].includes(version)) {
|
|
19
|
+
throw new Error(`Invalid GraphQL version: ${version}`);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let endpoint = process.env["SKYNET_GRAPHQL_ENDPOINT"];
|
|
23
|
+
let apiKey = process.env["SKYNET_GRAPHQL_API_KEY"];
|
|
24
|
+
if (version === "v2") {
|
|
25
|
+
endpoint = process.env["SKYNET_GRAPHQL_ENDPOINT_V2"];
|
|
26
|
+
apiKey = process.env["SKYNET_GRAPHQL_API_KEY_V2"];
|
|
27
|
+
}
|
|
18
28
|
|
|
19
29
|
if (!endpoint || !apiKey) {
|
|
20
|
-
throw new Error(
|
|
30
|
+
throw new Error(`Missing GraphQL ${version} endpoint or API key`);
|
|
21
31
|
}
|
|
22
32
|
|
|
23
33
|
const res = await fetch(endpoint, {
|
package/src/por.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CryptoHasher }
|
|
1
|
+
import { CryptoHasher } from "bun";
|
|
2
2
|
|
|
3
3
|
export interface UserLiability {
|
|
4
4
|
userHash: string;
|
|
@@ -11,7 +11,7 @@ export interface MerkleProof {
|
|
|
11
11
|
balance: number;
|
|
12
12
|
token?: string;
|
|
13
13
|
proof: string[];
|
|
14
|
-
positions: (
|
|
14
|
+
positions: ("left" | "right")[];
|
|
15
15
|
rootHash: string;
|
|
16
16
|
leafIndex: number;
|
|
17
17
|
hashFunction?: (data: string) => string;
|
|
@@ -53,28 +53,27 @@ export class MerkleTreePoR {
|
|
|
53
53
|
return this.hashFunction(data);
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
|
|
57
56
|
// hash user data
|
|
58
57
|
private createLeafHash(user: UserLiability): string {
|
|
59
|
-
const leafData = `${user.userHash}:${user.balance}:${user.token ||
|
|
58
|
+
const leafData = `${user.userHash}:${user.balance}:${user.token || ""}`;
|
|
60
59
|
return this.hash(leafData);
|
|
61
60
|
}
|
|
62
61
|
|
|
63
62
|
private buildTree(): void {
|
|
64
63
|
if (this.userData.length === 0) {
|
|
65
|
-
throw new Error(
|
|
64
|
+
throw new Error("Cannot build tree with empty user data");
|
|
66
65
|
}
|
|
67
66
|
|
|
68
67
|
// Create leaf hashes and store user mapping
|
|
69
68
|
this.leaves = this.userData.map((user, index) => {
|
|
70
69
|
const leafHash = this.createLeafHash(user);
|
|
71
|
-
this.userMap.set(`${user.userHash}:${user.token ||
|
|
70
|
+
this.userMap.set(`${user.userHash}:${user.token || ""}`, index);
|
|
72
71
|
return leafHash;
|
|
73
72
|
});
|
|
74
73
|
|
|
75
74
|
// Start with leaf level
|
|
76
75
|
let currentLevel = this.leaves;
|
|
77
|
-
this.tree.push(currentLevel.map(hash => ({ hash })));
|
|
76
|
+
this.tree.push(currentLevel.map((hash) => ({ hash })));
|
|
78
77
|
|
|
79
78
|
// Build tree bottom-up
|
|
80
79
|
while (currentLevel.length > 1) {
|
|
@@ -83,22 +82,18 @@ export class MerkleTreePoR {
|
|
|
83
82
|
|
|
84
83
|
for (let i = 0; i < currentLevel.length; i += 2) {
|
|
85
84
|
const left = currentLevel[i];
|
|
86
|
-
const right = i + 1 < currentLevel.length
|
|
87
|
-
? currentLevel[i + 1]
|
|
88
|
-
: left; // Duplicate if odd number
|
|
85
|
+
const right = i + 1 < currentLevel.length ? currentLevel[i + 1] : left; // Duplicate if odd number
|
|
89
86
|
|
|
90
87
|
const parentHash = this.hash(left + right);
|
|
91
88
|
nextLevel.push(parentHash);
|
|
92
89
|
|
|
93
90
|
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;
|
|
91
|
+
const rightNode = i + 1 < currentLevel.length ? this.tree[this.tree.length - 1][i + 1] : leftNode;
|
|
97
92
|
|
|
98
93
|
nextLevelNodes.push({
|
|
99
94
|
hash: parentHash,
|
|
100
95
|
left: leftNode,
|
|
101
|
-
right: rightNode
|
|
96
|
+
right: rightNode,
|
|
102
97
|
});
|
|
103
98
|
}
|
|
104
99
|
|
|
@@ -110,14 +105,14 @@ export class MerkleTreePoR {
|
|
|
110
105
|
// get root hash of created tree
|
|
111
106
|
getRootHash(): string {
|
|
112
107
|
if (this.tree.length === 0) {
|
|
113
|
-
throw new Error(
|
|
108
|
+
throw new Error("Merkle tree not built");
|
|
114
109
|
}
|
|
115
110
|
return this.tree[this.tree.length - 1][0].hash;
|
|
116
111
|
}
|
|
117
112
|
|
|
118
113
|
// generate merkle proof
|
|
119
114
|
generateProof(userHash: string, token?: string): MerkleProof {
|
|
120
|
-
const key = `${userHash}:${token ||
|
|
115
|
+
const key = `${userHash}:${token || ""}`;
|
|
121
116
|
const leafIndex = this.userMap.get(key);
|
|
122
117
|
if (leafIndex === undefined) {
|
|
123
118
|
throw new Error(`${userHash} not found in merkle tree for token ${token}`);
|
|
@@ -125,7 +120,7 @@ export class MerkleTreePoR {
|
|
|
125
120
|
|
|
126
121
|
const user = this.userData[leafIndex];
|
|
127
122
|
const proof: string[] = [];
|
|
128
|
-
const positions: (
|
|
123
|
+
const positions: ("left" | "right")[] = [];
|
|
129
124
|
|
|
130
125
|
let currentIndex = leafIndex;
|
|
131
126
|
|
|
@@ -137,11 +132,11 @@ export class MerkleTreePoR {
|
|
|
137
132
|
|
|
138
133
|
if (siblingIndex < currentLevelSize) {
|
|
139
134
|
proof.push(this.tree[level][siblingIndex].hash);
|
|
140
|
-
positions.push(isRightNode ?
|
|
135
|
+
positions.push(isRightNode ? "left" : "right");
|
|
141
136
|
} else {
|
|
142
137
|
// When odd number, the last node is duplicated
|
|
143
138
|
proof.push(this.tree[level][currentIndex].hash);
|
|
144
|
-
positions.push(isRightNode ?
|
|
139
|
+
positions.push(isRightNode ? "left" : "right");
|
|
145
140
|
}
|
|
146
141
|
|
|
147
142
|
currentIndex = Math.floor(currentIndex / 2);
|
|
@@ -155,21 +150,21 @@ export class MerkleTreePoR {
|
|
|
155
150
|
positions,
|
|
156
151
|
rootHash: this.getRootHash(),
|
|
157
152
|
leafIndex,
|
|
158
|
-
hashFunction: this.hashFunction !== this.defaultSHA256Hash ? this.hashFunction : undefined
|
|
153
|
+
hashFunction: this.hashFunction !== this.defaultSHA256Hash ? this.hashFunction : undefined,
|
|
159
154
|
};
|
|
160
155
|
}
|
|
161
156
|
|
|
162
157
|
// verify inclusion using proof
|
|
163
158
|
static verifyProof(merkleProof: MerkleProof): boolean {
|
|
164
|
-
const leafData = `${merkleProof.userHash}:${merkleProof.balance}:${merkleProof.token ||
|
|
159
|
+
const leafData = `${merkleProof.userHash}:${merkleProof.balance}:${merkleProof.token || ""}`;
|
|
165
160
|
const hashFunction = merkleProof.hashFunction || MerkleTreePoR.defaultSHA256Hash;
|
|
166
161
|
let currentHash = hashFunction(leafData);
|
|
167
|
-
|
|
162
|
+
|
|
168
163
|
for (let i = 0; i < merkleProof.proof.length; i++) {
|
|
169
164
|
const siblingHash = merkleProof.proof[i];
|
|
170
165
|
const position = merkleProof.positions[i];
|
|
171
166
|
|
|
172
|
-
if (position ===
|
|
167
|
+
if (position === "left") {
|
|
173
168
|
currentHash = hashFunction(siblingHash + currentHash);
|
|
174
169
|
} else {
|
|
175
170
|
currentHash = hashFunction(currentHash + siblingHash);
|
package/.vscode/settings.json
DELETED
package/dist/databricks.d.ts
DELETED