@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 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
+ };
@@ -45,10 +45,10 @@ const app = modeIndexer({
45
45
  env: {},
46
46
 
47
47
  state: {
48
- type: "block", // can be omitted, default is block
49
- getMinId: async () => 2, // default returns 1
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
@@ -0,0 +1,5 @@
1
+ import { Response } from "node-fetch";
2
+
3
+ type GraphqlVariables = { [key: string]: any };
4
+
5
+ export function gql(query: string, variables?: GraphqlVariables): Promise<Response>;
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, from);
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 + 1 : from,
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
@@ -41,6 +41,7 @@ const inline = {
41
41
  };
42
42
 
43
43
  module.exports = {
44
+ getLine,
44
45
  print,
45
46
  inline,
46
47
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@certik/skynet",
3
- "version": "0.10.39",
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": "^4.3.0",
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
- let { endpoint } = PROTOCOLS[protocol];
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
@@ -1,3 +0,0 @@
1
- import { Response } from "node-fetch";
2
-
3
- export function createAddressRecord(address: string): Promise<Response>;
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
- };