@certik/skynet 0.10.39 → 0.10.41
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/date.js +48 -0
- package/examples/mode-indexer +3 -3
- package/graphql.d.ts +5 -0
- package/graphql.js +30 -0
- package/indexer.js +30 -3
- package/log.js +1 -0
- package/package.json +2 -2
- package/transaction.js +3 -1
- package/inquiry.d.ts +0 -3
- package/inquiry.js +0 -15
- package/labelling.d.ts +0 -15
- package/labelling.js +0 -90
- package/rateLimit.d.ts +0 -1
- package/rateLimit.js +0 -21
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.10.41
|
|
4
|
+
|
|
5
|
+
- Added support for "date" state type for modeIndexer
|
|
6
|
+
- Retired no longer used `inquiry`, `labeling`, `rateLimit` libraries
|
|
7
|
+
|
|
8
|
+
## 0.10.40
|
|
9
|
+
|
|
10
|
+
- Added graphql (copied from frontend)
|
|
11
|
+
|
|
3
12
|
## 0.10.38 & 0.10.39
|
|
4
13
|
|
|
5
14
|
- Added x-instance-id header for api service
|
package/date.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
const { arrayGroup } = require("./util");
|
|
2
|
+
|
|
3
|
+
const MS_IN_A_DAY = 3600 * 24 * 1000;
|
|
4
|
+
|
|
5
|
+
function getDateOnly(date) {
|
|
6
|
+
return date.toISOString().split("T")[0];
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function findDateAfter(date, n) {
|
|
10
|
+
const d = new Date(date);
|
|
11
|
+
const after = new Date(d.getTime() + MS_IN_A_DAY * n);
|
|
12
|
+
|
|
13
|
+
return getDateOnly(after);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function daysInRange(from, to) {
|
|
17
|
+
const fromTime = new Date(from).getTime();
|
|
18
|
+
const toTime = new Date(to).getTime();
|
|
19
|
+
|
|
20
|
+
if (fromTime > toTime) {
|
|
21
|
+
throw new Error(`range to date couldn't be earlier than range from date`);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const daysBetween = Math.floor((toTime - fromTime) / MS_IN_A_DAY);
|
|
25
|
+
|
|
26
|
+
const dates = [getDateOnly(new Date(fromTime))];
|
|
27
|
+
|
|
28
|
+
for (let i = 1; i <= daysBetween; i += 1) {
|
|
29
|
+
dates.push(getDateOnly(new Date(fromTime + i * MS_IN_A_DAY)));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return dates;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function dateRange(from, to, step) {
|
|
36
|
+
const days = daysInRange(from, to);
|
|
37
|
+
|
|
38
|
+
const windows = arrayGroup(days, step);
|
|
39
|
+
|
|
40
|
+
return windows.map((w) => [w[0], w[w.length - 1]]);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
module.exports = {
|
|
44
|
+
getDateOnly,
|
|
45
|
+
findDateAfter,
|
|
46
|
+
daysInRange,
|
|
47
|
+
dateRange,
|
|
48
|
+
};
|
package/examples/mode-indexer
CHANGED
|
@@ -45,10 +45,10 @@ const app = modeIndexer({
|
|
|
45
45
|
env: {},
|
|
46
46
|
|
|
47
47
|
state: {
|
|
48
|
-
type: "
|
|
49
|
-
getMinId: async () =>
|
|
48
|
+
type: "date", // can be omitted, default is block
|
|
49
|
+
getMinId: async () => "2022-09-26", // default returns 1
|
|
50
50
|
getMaxId: async ({ protocol }) => {
|
|
51
|
-
return 10;
|
|
51
|
+
return "2022-10-18";
|
|
52
52
|
},
|
|
53
53
|
},
|
|
54
54
|
|
package/graphql.d.ts
ADDED
package/graphql.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const fetch = require("node-fetch");
|
|
2
|
+
|
|
3
|
+
const GRAPHQL_API_KEY = process.env.SKYNET_GRAPHQL_API_KEY || process.env.GRAPHQL_API_KEY;
|
|
4
|
+
|
|
5
|
+
async function gql(url, query, variables = {}) {
|
|
6
|
+
const res = await fetch(url, {
|
|
7
|
+
method: "POST",
|
|
8
|
+
headers: {
|
|
9
|
+
"x-api-key": GRAPHQL_API_KEY,
|
|
10
|
+
"content-type": "application/json",
|
|
11
|
+
},
|
|
12
|
+
body: JSON.stringify({ query: query.trim(), variables }),
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
if (res.ok) {
|
|
16
|
+
const { data, errors } = await res.json();
|
|
17
|
+
|
|
18
|
+
if (errors && errors.length > 0) {
|
|
19
|
+
throw new Error(JSON.stringify(errors, null, 2));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return data;
|
|
23
|
+
} else {
|
|
24
|
+
throw new Error(await res.text());
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
module.exports = {
|
|
29
|
+
gql,
|
|
30
|
+
};
|
package/indexer.js
CHANGED
|
@@ -2,10 +2,11 @@ const meow = require("meow");
|
|
|
2
2
|
const { createRecord, getRecordByKey } = require("./dynamodb");
|
|
3
3
|
const { getEnvironment } = require("./env");
|
|
4
4
|
const { exponentialRetry } = require("./availability");
|
|
5
|
-
const { range, fillRange } = require("./util");
|
|
5
|
+
const { range: numberRange, fillRange: fillNumberRange } = require("./util");
|
|
6
6
|
const { getSelectorFlags, getSelectorDesc, toSelectorString } = require("./selector");
|
|
7
7
|
const { getBinaryName } = require("./cli");
|
|
8
8
|
const { inline } = require("./log");
|
|
9
|
+
const { findDateAfter, dateRange, daysInRange: fillDateRange } = require("./date");
|
|
9
10
|
|
|
10
11
|
const STATE_TABLE_NAME = "skynet-" + getEnvironment() + "-indexer-state";
|
|
11
12
|
|
|
@@ -45,6 +46,14 @@ async function getIndexerValidatedId(name, selectorFlags) {
|
|
|
45
46
|
return 0;
|
|
46
47
|
}
|
|
47
48
|
|
|
49
|
+
function increaseId(type, currentId, n) {
|
|
50
|
+
if (type === "date") {
|
|
51
|
+
return findDateAfter(currentId, n);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return currentId + n;
|
|
55
|
+
}
|
|
56
|
+
|
|
48
57
|
// for those indexers that can have progress tracked by a numeric state.type
|
|
49
58
|
// such as block height, or timestamp
|
|
50
59
|
// managing state would be helpful to reduce the build time
|
|
@@ -77,6 +86,23 @@ function createModeIndexerApp({
|
|
|
77
86
|
...state,
|
|
78
87
|
};
|
|
79
88
|
|
|
89
|
+
// type based range functions
|
|
90
|
+
function range(from, to, step) {
|
|
91
|
+
if (finalState.type === "date") {
|
|
92
|
+
return dateRange(from, to, step);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return numberRange(from, to, step);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function fillRange(from, to) {
|
|
99
|
+
if (finalState.type === "date") {
|
|
100
|
+
return fillDateRange(from, to);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return fillNumberRange(from, to);
|
|
104
|
+
}
|
|
105
|
+
|
|
80
106
|
async function runMode({ mode, from, to, status, verbose, ...selectorFlags }) {
|
|
81
107
|
if (status) {
|
|
82
108
|
const stateItem = await getRecordByKey(STATE_TABLE_NAME, {
|
|
@@ -107,7 +133,7 @@ function createModeIndexerApp({
|
|
|
107
133
|
);
|
|
108
134
|
|
|
109
135
|
if (mode === "reset") {
|
|
110
|
-
await runReset(selectorFlags
|
|
136
|
+
await runReset(selectorFlags);
|
|
111
137
|
} else if (mode === "rebuild") {
|
|
112
138
|
await runReset(selectorFlags);
|
|
113
139
|
await runRebuild(selectorFlags, from, to > 0 ? to : await finalState.getMaxId(selectorFlags), verbose);
|
|
@@ -116,7 +142,7 @@ function createModeIndexerApp({
|
|
|
116
142
|
|
|
117
143
|
await runRebuild(
|
|
118
144
|
selectorFlags,
|
|
119
|
-
previousRebuildEnds ? previousRebuildEnds
|
|
145
|
+
previousRebuildEnds ? increaseId(finalState.type, previousRebuildEnds, 1) : from,
|
|
120
146
|
to > 0 ? to : await finalState.getMaxId(selectorFlags),
|
|
121
147
|
verbose
|
|
122
148
|
);
|
|
@@ -588,6 +614,7 @@ ${getSelectorDesc(selector)}
|
|
|
588
614
|
}
|
|
589
615
|
|
|
590
616
|
module.exports = {
|
|
617
|
+
increaseId,
|
|
591
618
|
createModeIndexerApp,
|
|
592
619
|
createIndexerApp,
|
|
593
620
|
getIndexerState,
|
package/log.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@certik/skynet",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.41",
|
|
4
4
|
"description": "Skynet Shared JS library",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"author": "CertiK Engineering",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"which": "^2.0.2"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"ava": "^
|
|
32
|
+
"ava": "^5.0.1",
|
|
33
33
|
"eslint": "^8.18.0",
|
|
34
34
|
"eslint-plugin-import": "^2.26.0",
|
|
35
35
|
"sinon": "^14.0.0"
|
package/transaction.js
CHANGED
|
@@ -3,7 +3,9 @@ const { PROTOCOLS } = require("./const");
|
|
|
3
3
|
const { exponentialRetry } = require("./availability");
|
|
4
4
|
|
|
5
5
|
async function getTxReceipt(protocol, txHash, verbose = false) {
|
|
6
|
-
|
|
6
|
+
const { endpoint } = PROTOCOLS[protocol];
|
|
7
|
+
|
|
8
|
+
console.log("got endpoint", protocol, endpoint);
|
|
7
9
|
|
|
8
10
|
const body = {
|
|
9
11
|
jsonrpc: "2.0",
|
package/inquiry.d.ts
DELETED
package/inquiry.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
const fetch = require("node-fetch");
|
|
2
|
-
const { getEnvironment } = require("./env");
|
|
3
|
-
|
|
4
|
-
const ADDRESS_INQUIRY_URL = getEnvironment() === "prd" ? (
|
|
5
|
-
"https://aml-inquiry.certik-skynet.com/"
|
|
6
|
-
) : (
|
|
7
|
-
"https://2kbfm0t10j.execute-api.us-east-1.amazonaws.com/dev/"
|
|
8
|
-
);
|
|
9
|
-
|
|
10
|
-
async function createAddressRecord(address) {
|
|
11
|
-
// Use skynet-aml-address-inquiry to add addresses as EOA or smart contract
|
|
12
|
-
return await fetch(`${ADDRESS_INQUIRY_URL}?address=${address}`);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
module.exports = { createAddressRecord };
|
package/labelling.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
type Tag = {
|
|
2
|
-
type: string;
|
|
3
|
-
label: string;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
export function addTagsToAddress(
|
|
7
|
-
address: string,
|
|
8
|
-
tags: Tag[],
|
|
9
|
-
verbose: boolean
|
|
10
|
-
): Promise<{
|
|
11
|
-
tableName: string;
|
|
12
|
-
updateItemTags: Tag[];
|
|
13
|
-
} | undefined>;
|
|
14
|
-
|
|
15
|
-
export function queryAddressTags(address: string): Promise<Tag[]>;
|
package/labelling.js
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
const fetch = require("node-fetch");
|
|
2
|
-
const { getRecordByKey, updateRecordByKey } = require("./dynamodb");
|
|
3
|
-
const { getEnvironment } = require("./env");
|
|
4
|
-
|
|
5
|
-
const ADDRESSES_TABLE_NAME = `skynet-${getEnvironment()}-aml-addresses`;
|
|
6
|
-
const SMART_CONTRACTS_TABLE_NAME = `skynet-${getEnvironment()}-aml-smart-contracts`;
|
|
7
|
-
|
|
8
|
-
async function addTagsToAddress(address, tags, verbose) {
|
|
9
|
-
let tableName = null;
|
|
10
|
-
let updateItemTags;
|
|
11
|
-
|
|
12
|
-
// Validate tags
|
|
13
|
-
tags.forEach((tag) => {
|
|
14
|
-
if (!tag.type || !tag.label) {
|
|
15
|
-
throw new Error("error: tag must be in format { type, label }");
|
|
16
|
-
}
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
// check if address is a smart contract
|
|
20
|
-
let queryResult = await getRecordByKey(SMART_CONTRACTS_TABLE_NAME, { address });
|
|
21
|
-
|
|
22
|
-
if (queryResult) {
|
|
23
|
-
tableName = SMART_CONTRACTS_TABLE_NAME;
|
|
24
|
-
updateItemTags = queryResult.tags ?? [];
|
|
25
|
-
} else {
|
|
26
|
-
// check if address is an EOA
|
|
27
|
-
queryResult = await getRecordByKey(ADDRESSES_TABLE_NAME, { address });
|
|
28
|
-
|
|
29
|
-
if (queryResult) {
|
|
30
|
-
tableName = ADDRESSES_TABLE_NAME;
|
|
31
|
-
updateItemTags = queryResult.tags ?? [];
|
|
32
|
-
} else {
|
|
33
|
-
// Unknown address type, inquiry endpoint to create a record
|
|
34
|
-
const url = `https://aml-inquiry.certik-skynet.com/address?address=${address}`;
|
|
35
|
-
const response = await fetch(url);
|
|
36
|
-
const json = await response.json();
|
|
37
|
-
if (!json.type) {
|
|
38
|
-
throw new Error(`Unknown address type in inquiry response: ${address}`);
|
|
39
|
-
}
|
|
40
|
-
const { type } = json;
|
|
41
|
-
tableName = type === "EOA" ? ADDRESSES_TABLE_NAME : SMART_CONTRACTS_TABLE_NAME;
|
|
42
|
-
updateItemTags = [];
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (tableName) {
|
|
47
|
-
// record available, add tag
|
|
48
|
-
const newTags = tags.filter((tag) => !updateItemTags.includes(tag));
|
|
49
|
-
|
|
50
|
-
if (newTags.length + updateItemTags.length === 0) {
|
|
51
|
-
throw new Error("error: no tags to add and none already in database");
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (newTags.length === 0) {
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
updateItemTags = [...updateItemTags, ...newTags];
|
|
59
|
-
|
|
60
|
-
// keep distinct tags
|
|
61
|
-
updateItemTags = updateItemTags.filter(
|
|
62
|
-
(value, index, self) => self.findIndex((t) => t.type === value.type && t.label === value.label) === index
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
await updateRecordByKey(tableName, { address: address }, { tags: updateItemTags }, null, verbose);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return { tableName, updateItemTags };
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
async function queryAddressTags(address) {
|
|
72
|
-
let updateItemTags = [];
|
|
73
|
-
|
|
74
|
-
let queryResult = await getRecordByKey(SMART_CONTRACTS_TABLE_NAME, { address });
|
|
75
|
-
|
|
76
|
-
if (queryResult) {
|
|
77
|
-
updateItemTags = queryResult.tags ?? [];
|
|
78
|
-
} else {
|
|
79
|
-
// check if address is an EOA
|
|
80
|
-
queryResult = await getRecordByKey(ADDRESSES_TABLE_NAME, { address });
|
|
81
|
-
|
|
82
|
-
if (queryResult) {
|
|
83
|
-
updateItemTags = queryResult.tags ?? [];
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return updateItemTags;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
module.exports = { addTagsToAddress, queryAddressTags };
|
package/rateLimit.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export function isRateLimited(name: string, unitTime: number, maxAccess: number): Promise<boolean>;
|
package/rateLimit.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
const fetch = require("node-fetch");
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Record the api access and return the rate limit result.
|
|
5
|
-
* @async
|
|
6
|
-
* @param {string} name - The name of the key.
|
|
7
|
-
* @param {number} unitTime - The sliding window for rate limiting, in seconds.
|
|
8
|
-
* @param {number} maxAccess - The total count of allowed accesses in a sliding window.
|
|
9
|
-
* @returns {Promise<boolean>} This request should be allowed or not.
|
|
10
|
-
*/
|
|
11
|
-
exports.isRateLimited = async (name, unitTime, maxAccess) => {
|
|
12
|
-
try {
|
|
13
|
-
const url = `https://rate-limit.certik-skynet.com?name=${name}&unitTime=${unitTime}&maxAccess=${maxAccess}`;
|
|
14
|
-
const response = await fetch(url);
|
|
15
|
-
const result = await response.json();
|
|
16
|
-
if (result.remaining > 0) return false;
|
|
17
|
-
return true;
|
|
18
|
-
} catch {
|
|
19
|
-
return false;
|
|
20
|
-
}
|
|
21
|
-
};
|